Единый API для провайдеров: дизайн, версияция, совместимость
Полный текст статьи
1) Зачем «единый API» и что это такое
Единый API — это спецификация и набор эндпоинтов/событий, через которые любой провайдер контента (RGS, live-студия, джекпот, KYC/AML, аффилиаты) общается с платформой по одним правилам:- единая ресурсная модель (players, sessions, bets, settlements, bonuses, jackpots, payments), общие контракты событий и идентификаторы, стандарты безопасности и обратной совместимости, SDK/инструменты для ускорения интеграций.
Цель: сократить time-to-integrate, снизить ошибки на «денежных путях» и обеспечить предсказуемые апгрейды.
2) Принципы дизайна
1. Domain-first. Сначала словарь и инварианты (ставка, сеттлмент, лимиты RG), потом эндпоинты.
2. Compatibility by default. Любое изменение — совместимое по умолчанию; breaking-изменения строго по процессу.
3. Idempotency everywhere. Все денежные команды повторяемы без побочных эффектов.
4. Events are source of truth (в дистрибуции). Операции → события в шину; аналитика слушает шину, а не бьёт OLTP.
5. Least privilege & zero-trust. Токены, подписи, сегментация по бренду/региону.
6. Observability. Сквозной `trace_id`, понятная модель ошибок, метрики p95/p99.
3) Ресурсная модель (упрощённо)
Player: псевдо-ID игрока на стороне платформы, гео/валюта/статусы RG.
Session: канал между провайдером и платформой (`session_id`, TTL, гео/ограничения).
Bet: авторизация/дебет ставки.
Settlement: исход раунда и кредит выигрыша.
Bonus / Wager: состояние бонуса/остатка вейджера.
Jackpot: взносы/триггеры/выплаты.
Event: неизменяемые доменные события (Kafka/аналоги).
Идентификаторы: `tenant_id`, `brand_id`, `region`, `player_id`, `session_id`, `round_id`, `bet_id`, `settlement_id`. Все — строковые, глобально уникальные (UUID/KSUID/Snowflake), включаются в логи и события.
4) Контракты API: запросы, ответы, ошибки
4.1 Авторизация и безопасность
OAuth2 Client Credentials или mTLS + подпись тела запроса (HMAC/EdDSA).
Скоупы вида: `bets:write`, `settlements:write`, `sessions:read`, `events:publish`.
В каждом запросе обязательны заголовки:- `X-Trace-Id`, `X-Brand-Id`, `X-Region`, `X-Idempotency-Key`.
4.2 Примеры эндпоинтов
Создание сессии
POST /v1/sessions
{
"player_id":"p_19f3",  "game_id":"studio:slot_forge_02",  "currency":"EUR",  "locale":"de-DE",  "constraints":{"max_bet":5,"rg_flags":["self_exclusion":false]}
}
→ 201
{
"session_id":"s_456",  "expires_at":"2025-10-23T19:10:00Z"
}Авторизация ставки (hold)
POST /v1/bets/authorize
Headers: X-Idempotency-Key: bet_r_8c12_1
{
"session_id":"s_456",  "bet_id":"b_001",  "round_id":"r_8c12",  "amount":{"amount":2.00,"currency":"EUR"}
}
→ 200 { "status":"authorized","hold_id":"h_zz1" }Сеттлмент
POST /v1/bets/settle
Headers: X-Idempotency-Key: settle_r_8c12_1
{
"bet_id":"b_001",  "round_id":"r_8c12",  "win":{"amount":14.60,"currency":"EUR"},  "bonus_state":{"in_bonus":true,"freespins_left":7}
}
→ 200 { "status":"credited","settlement_id":"st_77" }4.3 Ошибки (единая модель)
`code`: машинное имя (`RG_BLOCK`, `LIMIT_EXCEEDED`, `DUPLICATE`, `IDEMPOTENCY_MISMATCH`, `INVALID_STATE`, `AUTH_FAILED`).
`message`: кратко для человека.
`retryable`: `true/false`.
`trace_id`: для поиска в логах.
Пример:
409 CONFLICT
{
"code":"DUPLICATE",  "message":"Bet already authorized with a different amount",  "retryable":false,  "trace_id":"tr_a1b2c3"
}5) Событийная шина и схемы
5.1 Базовые топики
5.2 Схема события (Avro/JSON Schema)
json
{
"event_id":"uuid",  "event_type":"bet.settled",  "occurred_at":"2025-10-23T16:21:05Z",  "tenant_id":"brand-7",  "region":"EU",  "player_id":"p_19f3",  "trace_id":"tr_a1b2c3",  "payload":{
"round_id":"r_8c12",   "bet":{"amount":1.00,"currency":"EUR"},   "win":{"amount":14.60,"currency":"EUR"},   "in_bonus":true
},  "idempotency_key":"bet_r_8c12_1",  "schema_version":"1.2.0"
}Правила: backward-compatible эволюция схем, registry + контрактные тесты.
6) Версияция API: стратегии и правила
6.1 Где хранить версию
Path-версия: `/v1/...` (просто кешировать/маршрутизировать).
Header-версия: `Accept: application/vnd.platform.api+json;version=1.2`.
События: `schema_version` в поле события + registry.
Практика: path для HTTP, schema_version для событий, фичфлаги для точечных возможностей.
6.2 SemVer и типы изменений
PATCH (minor) — обратносостыковочные: новые необязательные поля, новые эндпоинты, новые типы событий.
MAJOR — breaking: переименование полей, изменение семантики, удаление. Разрешены только через новый `/vN/` и депрекацию старого.
6.3 Стабильные контракты (что нельзя ломать)
Имена и типы ключевых полей идентификации (`_id`, `idempotency_key`).
Денежную модель (`amount/currency`, точность).
Семантику статусов (`authorized`, `credited`, `forfeited` и т. д.).
Идемпотентность: поведение при повторе строго определено.
7) Совместимость и эволюция
7.1 Добавления (safe)
Новые необязательные поля с дефолтами.
Новые события/эндпоинты без изменения существующих.
Расширение enum с fallback в `unknown`.
7.2 Изменения (risky)
Изменение типа поля (число → строка).
Изменение обязательности (optional → required).
Разворот бизнес-логики (`settle` раньше `authorize`).
→ требуется новая мажорная версия и миграционный гайд.
7.3 Депрекация
Поле/эндпоинт помечается `deprecated_since: 1.7`, `removed_in: 2.0`.
Коммуникация: release notes, рассылка, deprecation-headers (`Sunset`, `Deprecation`).
Трассировка использования «устаревших» путей для проактивных уведомлений партнёров.
8) Идемпотентность и согласованность
Заголовок `X-Idempotency-Key` обязателен для всех записывающих операций.
Семантика: повтор с тем же ключом → тот же результат (200 с прежним body).
Ключи привязаны к композиции параметров (например, `bet_id + amount`).
Саги на длинных процессах: `authorize → commit/lock → settle → credit`; компенсации — событиями `rollback`.
9) Пагинация, фильтры, сортировка
Cursor-based пагинация (строго предпочтительнее `page/limit` для больших потоков).
Унификация: `?cursor=...&limit=200&order=asc`.
В ответе: `next_cursor`, `has_more`.
Фильтры: по времени (`occurred_at_from/to`), `tenant_id`, `game_id`, `status`.
10) Локали, валюты, резидентность данных
Валюта в ISO-4217; точность хранится в схеме (`scale`), расчёты — в minor-units (cents).
Локали — BCP 47 (`en-GB`, `pt-BR`).
В каждом запросе — `region`; PII и денежные операции не пересекают регионы.
Маскирование PII и RLS в витринах BI.
11) Наблюдаемость и лимиты
Обязательные заголовки: `X-Trace-Id`, `X-Provider-Id`, корреляция с событиями.
Метрики: p50/p95/p99 latency, error rate (по кодам), throughput, queue lag (для событий).
Rate limits: per provider / per brand; ответы с `Retry-After`.
WORM-аудит критичных изменений (лимиты, RTP-пулы, формулы джекпота).
12) Тестирование и качество контрактов
Контрактные тесты (Pact/другие): провайдер ↔ платформа ↔ консьюмеры событий.
Нагрузочные: «шторм» ставок/сеттлментов; цели p95.
Хаос-кейсы: дубль-доставки, out-of-order, задержки кошелька.
Песочница `/sandbox` с фиктивными деньгами и тестовыми `player_id`.
13) SDK, генераторы и документация
OpenAPI/AsyncAPI → генерация SDK (TypeScript/Java/Kotlin/Go/Rust).
Примеры кода для `authorize/settle/rollback`, ретраев и обработки ошибок.
Live-док с примерами запрос/ответ (curl + JSON), коллекции Postman/Insomnia.
Changelog с типами изменений и метками совместимости.
14) Дорожная карта миграций (пример)
1. v1.6 → v1.7 (minor): добавили поле `bonus_state` в `settle` (optional).
2. v1.x EOL анонс: за 6 месяцев — письмо + `Deprecation` header + дашборд использования.
3. v2.0 (major): отдельный `wallet.commit` (ранее implicit), новое поле `settlement_id` обязательно.
4. Миграционный гайд: маппинг полей, timeline, фичфлаг «двойного письма» (параллельная публикация `v1`/`v2` событий).
5. Sunset v1: блокировка новых интеграций, продление только по SLA-исключениям.
15) Чек-листы
Для архитекторов платформы
- Есть единый словарь доменных сущностей и инвариантов.
- OpenAPI/AsyncAPI + Schema Registry, semver, process депрекаций.
- Идемпотентность на всех write-операциях; ключи документированы.
- Единая ошибка-модель и коды.
- Саги и outbox/CDC на денежных путях.
- Rate-limits, observability, WORM-аудит.
- Песочница и контрактные тесты доступны партнёрам.
- Data residency и RLS/маскирование.
Для провайдера
- Отправляю `X-Trace-Id` и `X-Idempotency-Key` всегда.
- Повторы запросов обрабатываю безопасно; дубли не создаю.
- Обрабатываю `Deprecation/Sunset` и читаю Changelog.
- Публикую/читаю события по схемам registry; храню версию.
- Имею retry/backoff и дедупликацию на своей стороне.
16) Анти-паттерны (красные флаги)
Ручные правки балансов/сеттлментов в БД.
Публикация событий «мимо» outbox/CDC.
Отсутствие idempotency → дубли выплат/дебетов.
Смешение PII/денег разных регионов без маркировки `region`.
«Тихие» breaking-изменения без новой версии и депрекации.
Генерация SDK вручную (дрейф с реальной спеки).
Big-bang миграции без фичфлагов и двойного письма событий.
Единый API — это не только «коллекция эндпоинтов», а контракт экосистемы: согласованный словарь, стабильные денежные инварианты, события с версионированием, понятные правила совместимости и управляемые депрекации. Опираясь на семантическую версияцию, идемпотентность, outbox/CDC, наблюдаемость и строгую безопасность, платформа подключает провайдеров быстро и безболезненно, а апгрейды превращаются из риска в рутину.
