REST / JSON
API-док
JSON API: ключ с балансом, оплата за запрос, тот же движок, что и в веб-версии.
Быстрый старт за три запроса
- Заведите ключ — вернётся csscl_… с пробным балансом
curl -X POST https://css-cleaner.ru/api/v1/key -H "Content-Type: application/json" -d '{"name":"my-app"}' - Пополните баланс: карта, СБП, крипта или песочница
curl -X POST https://css-cleaner.ru/api/v1/topup -d 'key=csscl_XXXX&amount=500&provider=yookassa' - Отправляйте CSS — возвращаем чистый CSS и отчёт
curl -X POST https://css-cleaner.ru/api/v1/dedup -H "X-API-Key: csscl_XXXX" -d '{"css":".a{color:red}.a{color:red}"}'
Аккаунта нет: ключ и есть счёт. Потеряли ключ — баланс не восстановить.
Аутентификация
Ключ можно передать любым из трёх способов.
X-API-Key: csscl_XXXXXXXXXXXXXXXX
Authorization: Bearer csscl_XXXXXXXXXXXXXXXX
POST /api/v1/dedup?key=csscl_XXXXXXXXXXXXXXXX
Без ключа доступно 20 бесплатных запросов в день на IP: годится для тестов, но для продакшена заведите ключ.
Эндпоинты
| Метод и путь | Что делает | Тариф |
|---|---|---|
POST /api/v1/dedup | Убирает дубликаты и пустые правила, безопасно склеивает переопределения одного селектора. | 0.10 ₽ |
POST /api/v1/filter | Оставляет только те правила, которые реально срабатывают в переданном HTML. | 0.20 ₽ |
POST /api/v1/block | Собирает стили одного блока: вместе с наследуемыми от html/body и всеми нужными var(). | 0.30 ₽ |
POST /api/v1/key | Создать ключ с пробным балансом | бесплатно |
GET /api/v1/key | Баланс, расход, число запросов, текущие цены | бесплатно |
POST /api/v1/topup | Счёт на пополнение — вернёт ссылку на оплату | бесплатно |
POST /api/dedup · /api/filter · /api/block | Те же три задачи без ключа и без тарификации | бесплатно |
Параметры запроса
POST /api/v1/dedup
| Поле | Тип | Обязательно | Значение |
|---|---|---|---|
css | string | да | CSS целиком, как в файле |
strip_comments | bool | нет | вырезать комментарии (по умолчанию нет) |
merge_overrides | bool | нет | слить правила одного селектора в одно — только если свойства не конфликтуют |
POST /api/v1/filter
| Поле | Тип | Обязательно | Значение |
|---|---|---|---|
css | string | да | CSS целиком, как в файле |
html | string | да | HTML страницы, для которой чистим CSS |
drop_keyframes | bool | нет | убрать @keyframes, на которые нет ни одной анимации |
drop_fonts | bool | нет | убрать @font-face, которые не используются |
POST /api/v1/block
| Поле | Тип | Обязательно | Значение |
|---|---|---|---|
css | string | да | CSS целиком, как в файле |
html | string | да | HTML страницы, для которой чистим CSS |
target | string | да | селектор блока: .card, #hero, main .btn |
prune | bool | нет | выбросить объявления, которые всё равно перекрываются позже по каскаду |
drop_keyframes | bool | нет | убрать @keyframes, на которые нет ни одной анимации |
drop_fonts | bool | нет | убрать @font-face, которые не используются |
POST /api/v1/topup
| Поле | Тип | Обязательно | Значение |
|---|---|---|---|
key | string | да | API-ключ, который пополняем |
amount | number | да | сумма в рублях: от 100 до 100000 |
provider | string | нет | yookassa · robokassa · cryptocloud · demo (пусто = первый доступный) |
Ответ
Успешный ответ — JSON с результатом и отчётом. Все суммы в копейках.
{
"ok": true,
"endpoint": "block",
"charged": 30,
"price": 30,
"balance": 970,
"output": ":root { --brand: #3b82f6; } body { color: #222; } .card { padding: 24px; }",
"report": {
"rules_total": 14, "rules_kept": 9, "rules_dropped": 5,
"elements_matched": 1, "inherited_kept": ["html", "body", ".content"],
"var_names": ["--brand", "--gap", "--text"],
"saved_bytes": 412, "reduction": 38.4
}
}
| Поле | Значение |
|---|---|
output | очищенный CSS одной строкой |
charged · price · balance | сколько списали, цена запроса, остаток на ключе |
report.saved_bytes · report.reduction | сколько байт сэкономлено и на сколько процентов |
report.rules_before · rules_after · duplicates · empty · merged_groups | статистика дедупликации: правил до и после, дубликаты, пустые, склейки |
report.rules_kept · rules_dropped · elements_matched · keyframes_dropped · fonts_dropped | статистика фильтрации: что оставили, что выбросили, сколько элементов совпало |
report.inherited_kept · var_names · decls_pruned · target | для блока: унаследованные селекторы, имена переменных, вырезанные объявления |
Ошибки
Любая ошибка — JSON вида {"error": "…"}.
| HTTP | Смысл |
|---|---|
400 | нет css/html или некорректный JSON |
401 | ключ не найден или не передан |
402 | недостаточно средств на ключе |
403 | ключ отключён |
404 | неизвестный эндпоинт, например /api/v1/pretty |
413 | вход больше 2 МБ |
429 | исчерпан дневной бесплатный лимит |
Лимиты
- до 2 МБ CSS на запрос — больше не бывает даже на реальных сайтах
- до 60 секунд на обработку одного запроса
- 20 бесплатных запросов в день на IP без ключа
- плата за запрос, а не за байты: 2 МБ и 2 КБ стоят одинаково
Примеры кода
JavaScript (fetch)
const r = await fetch("https://css-cleaner.ru/api/v1/filter", {
method: "POST",
headers: { "Content-Type": "application/json", "X-API-Key": "csscl_XXXX" },
body: JSON.stringify({ html: document.documentElement.outerHTML, css, drop_keyframes: true }),
});
const { output, report } = await r.json();
console.log(`−${report.saved_bytes} б, −${report.rules_dropped} правил`);
Python (requests)
import requests
r = requests.post("https://css-cleaner.ru/api/v1/block",
headers={"X-API-Key": "csscl_XXXX"},
json={"html": html, "css": css, "target": ".card", "prune": True},
timeout=60)
r.raise_for_status()
print(r.json()["output"], r.json()["balance"])