API v1 · стабильный контракт

API ScanBase — проверяйте сайты на 152-ФЗ программно

Один HTTP-запрос → оценка соответствия, список нарушений с суммами штрафов, разбор политики/оферты/согласия, cookie и трекеров. Тот же движок, что и на scanbase.ru. Для CI/CD, агентств, платформ и AI-агентов (через MCP).

Base URL: https://scanbase.ru/wp-json/scanbase-api/v1 Auth: Authorization: Bearer sb_live_…

Аутентификация

Каждый запрос — с API-ключом формата sb_live_… в заголовке. Ключ в URL-параметрах не принимается (утекает в логи).

# предпочтительно
Authorization: Bearer sb_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
# либо
X-Api-Key: sb_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Тариф и доступ определяются аккаунтом ключа, а не параметрами запроса. Ключ вы получаете сами в личном кабинете — см. Получить ключ.

Квоты и тарифы

РежимОбъёмДоменыBurstОтчёт
Free5 / суткилюбые1 / минурезанный (часть деталей и несоответствия скрыты)
Подписка30 / местолько свои (мониторинг)3 / минполный
API-пакетыпо пакетулюбые3 / минполный

Доступ — по аккаунту ключа. Free сбрасывается в 00:00 UTC. Пакеты (кредиты) действуют 12 месяцев и дают полный отчёт по любому домену. Остаток — в GET /account и в заголовках X-RateLimit-*. Превышение → 429 с Retry-After.

Пакеты сканов

Разовая покупка, без подписки. Полный отчёт по любому домену, кредиты живут 12 месяцев. Оплата и активация — в личном кабинете.

ПакетСкановЦенаЗа скан
P10 10 12 000 ₽ 1 200 ₽
P50 50 45 000 ₽ 900 ₽
P200 200 140 000 ₽ 700 ₽
P1000 1000 500 000 ₽ 500 ₽

Нужен объём вне пакетов, приоритетная поддержка или счёт на юрлицо — info@scanbase.ru.

Ошибки

Единый конверт ошибки:

{ "success": false, "error": { "code": "quota_exceeded", "message": "Daily quota exceeded" } }
HTTPcodeЗначение
401unauthorizedНет/неверный/отозванный ключ
429quota_exceeded / rate_limitedДневная квота / burst-лимит
503scanner_busyСканер временно недоступен
404no_active_scan / not_foundНет активного скана для опроса / скан не найден или не ваш

Статус 202 с {"status":"pending"} — это не ошибка, а «скан ещё идёт» (тяжёлый сайт). Опрашивайте GET /scans/pending.

Запустить скан

POST/scansвсе тарифы

Сканирует URL. Быстрый сайт (≤120с) → 200 с результатом. Тяжёлый → 202 pending, добор через /scans/pending.

curl -X POST https://scanbase.ru/wp-json/scanbase-api/v1/scans \
  -H "Authorization: Bearer sb_live_…" \
  -H "Content-Type: application/json" \
  -d '{"url":"https://example.ru/"}'

Ответ 200 (сокращённо)

{
  "success": true, "scan_id": "0b8e…-uuid", "schema_version": 1,
  "url": "https://example.ru/", "domain": "example.ru",
  "score": 62, "tier": "subscription",
  "summary": { "violations_count": 7, "total_fine_max": 1200000 },
  "all_checks": [ { "id": "cookie_reject", "category": "Cookie",
      "name": "Кнопка «Отклонить»…", "passed": false, "fine": 300000 } ],
  "documents": { … }, "foreign_services": [], "mismatch_findings": [],
  "subdomains": [], "subdomains_meta": { "status": "ok|partial|unavailable", "source": "ct+dns|dns|links" },
  "dev_tasks": [], "edu_documents": null, "peer_percentile": 41, "industry": null
}

Ответ 202 (тяжёлый сайт)

{ "success": false, "status": "pending", "reason": "scan_running",
  "url": "https://example.ru/",
  "poll": { "path": "/scans/pending?url=…", "retry_after": 15 } }

Добрать длинный скан

GET/scans/pending?url=<url>все тарифы

Опрос результата после 202. Тем же ключом, что запускал скан. Опрашивайте раз в ~15с.

ОтветЗначит
200Готово — тело как у POST /scans 200
202Ещё идёт — опрашивайте дальше
404no_active_scan — нечего опрашивать (истёк/не запускался)

Сохранённый результат

GET/scans/{scan_id}все тарифы

Прошлый скан по scan_id (uuid). Доступны только сканы вашего аккаунта. Гейтится по текущему тарифу (кончилась подписка → отчёт деградирует до free). Тело — идентичная схема scan_result.

curl https://scanbase.ru/wp-json/scanbase-api/v1/scans/0b8e…-uuid \
  -H "Authorization: Bearer sb_live_…"

История сканов

GET/scans?page=1&per_page=20все тарифы

Компактный список сканов аккаунта. per_page ≤ 50.

{ "success": true, "scans": [ { "scan_id": "…", "url": "…", "domain": "…",
      "score": 62, "violations_count": 7, "total_fine_max": 1200000, "created_at": "…" } ],
  "page": 1, "per_page": 20, "total": 48, "total_pages": 3, "has_more": true }

Полная серверная пагинация: total — всего сканов аккаунта, has_more — есть ли ещё страницы. Листайте page до has_more:false.

Статус аккаунта

GET/accountвсе тарифы
{ "success": true, "api_version": "v1", "schema_version": 1,
  "email": "you@company.ru", "tier": "subscription", "subscription_active": true,
  "entitlement": {
    "credits": { "balance": 40, "scope": "any_domain" },
    "subscription": { "active": true, "domains": ["site.ru"],
      "quota": { "period": "month", "limit": 30, "used": 4, "remaining": 26 } },
    "free": { "quota": { "period": "day", "limit": 5, "remaining": 5 } } } }

Доступ зависит от домена конкретного скана: кредиты пакета — любой домен; подписка — только свои; иначе free. Есть также GET /rate-limit — быстрый остаток без лишней нагрузки.

Справочник проверок

GET/checksбез ключа

Публичный каталог всех проверок сканера — id, название, категория, тип (violation/warning/check), статья закона и верхняя граница штрафа. Ключ не нужен. Удобно промаппить наши id на свою систему до первого скана.

{ "success": true, "count": 44, "categories": [ … ],
  "checks": [ { "id": "google_analytics", "category": "Трансграничная передача",
      "type": "violation", "law": "ст. 12 ФЗ-152, ст. 13.11 КоАП РФ", "fine_max": 6000000 } ] }

Схема scan_result

Единая для всех путей (POST /scans sync, /scans/pending, /scans/{id}).

ПолеТипОписание
scan_idstring|nulluuid скана — им вызывается GET /scans/{scan_id}. Обычно строка; в редком sync-race может быть null (сам результат уже получен, а id найдёте в GET /scans)
scoreint|nullОценка соответствия 0–100
tierstringfree / subscription — под каким гейтом отдан результат
summaryobject{ violations_count, total_fine_max }
all_checks[]arrayПроверки: { id, category, name, passed, warning, fine, … }
documentsobject|nullНайденные документы (политика/оферта/согласие/cookie)
foreign_services[]arrayЗарубежные сервисы (трансграница)
subdomains[]arrayСвязанные хосты домена (периметр организации)
subdomains_metaobject|nullПолнота перечня: statusok (проверены журналы TLS-сертификатов), partial (только ссылки и типовые имена — список может быть неполным), unavailable; source — использованные источники. Пустой subdomains при partial не означает отсутствия поддоменов.
mismatch_findings[]arrayНесоответствия документ↔сайт (подписка)
dev_tasks[]arrayТЗ на устранение (подписка)
edu_documentsarray|nullОбязательные документы образовательной организации
peer_percentileint|nullПерцентиль относительно отрасли
schema_versionintВерсия схемы результата (сейчас 1)

Состав all_checks постоянно расширяется вместе со сканером — новые проверки не ломают контракт. Контракт — это структура полей, конверт и коды ошибок. Клиент должен игнорировать незнакомые поля.

Версионирование

Версия в пути: scanbase-api/v1. Внутри v1 — только аддитивные изменения (новые поля/эндпоинты). Ломающие изменения → v2 рядом, с окном деприкации. schema_version в результате и api_version в /account — для страховки.

MCP-сервер (AI-агенты)

Для Claude Desktop, Cursor и других AI-агентов — MCP-сервер scanbase-mcp: агент вызывает наш скан как инструмент («проверь этот сайт на 152-ФЗ»). Добавьте в конфиг MCP:

{
  "mcpServers": {
    "scanbase": {
      "command": "npx",
      "args": ["-y", "scanbase-mcp"],
      "env": { "SCANBASE_API_KEY": "sb_live_…" }
    }
  }
}

Инструменты: scan_site, get_scan, list_scans, account. Ключ sb_live_…из личного кабинета.

Получить ключ

  1. Войдите в личный кабинет (вход по email — magic-link).
  2. Вкладка 💳 Аккаунт → 🔌 API-доступ → кнопка «Создать бесплатный ключ».
  3. Скопируйте ключ sb_live_… — он показывается один раз. Готово: 5 сканов в сутки бесплатно.

Нужно больше — там же докупите пакет сканов или оформите подписку. Ключей можно завести до трёх (например, dev и prod), любой отзывается в один клик.