Лимиты и соглашения

Лимиты и соглашения

Лимиты, размеры запросов, версионирование URL, request-id, retry-политика. Один документ для всех соглашений API.

Rate limits — per-token

Лимит считается per-token и сбрасывается раз в минуту (fixed window). Превышение → 429 rate_limited + HTTP header Retry-After.

ПолеТипОписание
integrationpurposeDefault: 60 запросов в минуту.
mcppurposeDefault: 300 запросов в минуту (агенты бывают шумными).
rate_limit_per_minuteoverridePer-token override через admin UI. Min 1, max разумных значений (10000) — реально нужно редко.

:::info Что считается одним запросом Любой HTTP request, который дошёл до RequireAPIToken middleware. Запросы без Bearer не считаются (они в принципе не имеют token-binding'а). Failed requests (401 / 403 / 422 / 500) — считаются. :::

429 response

HTTP/1.1 429 Too Many Requests
Retry-After: 30
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1747569600
Content-Type: application/json
 
{
  "error": {
    "code": "rate_limited",
    "message": "Превышен лимит запросов; повторите через 30 секунд",
    "details": { "retry_after_seconds": 30 }
  }
}

Клиент обязан уважать Retry-After (секунды). Реализуйте exponential backoff на случай нескольких подряд 429: retry_after, ×2, ×4, max 5 минут.

Размеры запросов

EndpointЛимит
POST /integration/payments/imports — multipart file10 MB. Превышение → 413 payload_too_large.
POST /api/v1/mcp — JSON-RPC body16 KB. Превышение → 413 payload_too_large.
Прочие POST/PUT bodies1 MB (хватает с большим запасом на любой типовой payload).

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

Текущий префикс — /api/v1/. Внутри v1 backend гарантирует:

  • Добавление новых полей в response — не breaking. Клиент должен игнорировать неизвестные поля (forward-compat).
  • Добавление новых endpoint'ов — не breaking.
  • Изменение типа существующего поля — breaking, не делается в v1.
  • Удаление поля или endpoint'а — breaking, не делается в v1.
  • Smaller изменения семантики error.code — breaking; новые error-коды добавляются, существующие не пере-используются.

Breaking changes выйдут под новым префиксом (/api/v2/). v1 будет жить в параллель минимум 12 месяцев после релиза v2.

HTTP headers — соглашения

HeaderГдеОписание
AuthorizationrequestОбязателен везде. Bearer bcs_….
Content-Typerequestapplication/json для POST/PUT body. Для POST /payments/importsmultipart/form-data.
X-Request-Idrequest/responseКлиент может слать свой; иначе backend генерирует. Возвращается в response header. Включайте в repro при баг-репортах.
X-MCP-Session-IdrequestТолько REST /api/v1/mcp/* (stdio bcs-mcp). UUIDv4, генерируется клиентом per-process.
Mcp-Session-Idrequest/responseТолько Streamable HTTP POST /api/v1/mcp. Server-issued на initialize, клиент-echo'ит на последующих запросах.
Retry-AfterresponseНа 429 — секунды до следующей попытки.
X-RateLimit-Limit / -Remaining / -ResetresponseТекущее окно: лимит, остаток, unix-timestamp сброса. Возвращаются на каждом запросе с rate-limited middleware.
OriginrequestТолько MCP HTTP transport — для проверки allowlist (MCP_ALLOWED_ORIGINS).

Кодировки

КонтекстКодировка
JSON request/responseUTF-8 без BOM.
1CClientBankExchange (upload payments / export statements format=1c)cp1251 (как 1С его и пишет). Charset в Content-Type экспорта явно проставлен.
CSV export (format=csv)UTF-8, разделитель , (RFC 4180).

Идемпотентность по endpoint'ам

EndpointИдемпотентен?
POST /payments/importsНет (каждый upload — новый batch). Идемпотентность встроена в submit, не в upload.
POST /payments/imports/{id}/submitДа — по (api_token_id, external_id, payload_hash).
POST /payments/imports/{id}/items/{id}/submitДа — то же правило.
POST /statementsДа — по (api_token_id, external_id, bank_account_id, date_from, date_to).
GET endpointsЕстественно — нет side-effects.
POST /api/v1/mcp method=initializeНет — каждый initialize создаёт новую сессию.
DELETE /api/v1/mcpДа — удаление несуществующей сессии = success (204).

Что НЕ возвращается ни в одном ответе

Data-minimization инвариант. Эти поля никогда не появляются в integration / MCP response'ах (только в admin-зоне за логином):

  • token_hash, raw bcs_… токены;
  • банковские credentials (credentials_id, metadata_json, secret_id);
  • signing_secret, raw refresh_token, access_token, private_key;
  • bank_reference, sign_url (внутренние bank-side handle'ы);
  • Полный 20-значный номер РС (только _masked форма — кроме export'а выписки в JSON, где он машинно-нужен).

Если в response какого-то endpoint'а вы видите одно из этих полей — это баг backend'а, прошу репортить.