MMeerPartners docs

API: лимиты и идемпотентность

Rate limiting и идемпотентность API MeerPartners: лимиты на постбэк и вход, заголовок Retry-After, Idempotency-Key и дедупликация постбэков по external_order_id.

Чтобы интеграция была устойчивой, API ограничивает частоту запросов и гарантирует безопасные повторы. Эта страница — про оба механизма: что произойдёт при превышении лимита и как повторять запросы, не создавая дубликатов.

Rate limiting

Лимиты считаются в фиксированном окне (счётчик в Redis). Ключ лимита зависит от эндпоинта:

ЭндпоинтЛимитКлючКод при превышении
POST /api/v1/postback~600 / минна tenant_api_key (key_id)POSTBACK_RATE_LIMITED (429)
POST /api/v1/auth/meerid/exchange20 / минна IPRATE_LIMIT_EXCEEDED (429)
GET /r/{code}, GET /p/{code}.gifанти-флудна хэш IPTRACKING_RATE_LIMITED (429)

Точные значения — за оператором

Числа выше — значения по умолчанию (постбэк — 600 запросов в минуту на ключ, вход — 20 в минуту на IP). Оператор платформы может их изменить. Закладывайте экспоненциальный backoff, а не фиксированные паузы.

Заголовок Retry-After

При ответе 429 платформа сообщает, когда можно повторить, заголовком Retry-After (секунды), а в теле — лимит и окно:

Ответ 429
{
  "error": {
    "code": "POSTBACK_RATE_LIMITED",
    "message": "Слишком много postback",
    "details": { "limit": 600, "window_seconds": 60 }
  }
}
HTTP/1.1 429 Too Many Requests
Retry-After: 23

Как обрабатывать 429

Не «долбите» эндпоинт в цикле. Получив 429, подождите Retry-After секунд (или используйте экспоненциальный backoff с джиттером) и повторите. Для постбэка повтор безопасен — он идемпотентен по external_order_id (см. ниже).

Постбэк защищён независимо от лимитов

Даже при всплеске нагрузки приём постбэков защищён HMAC-подписью и проверкой timestamp, а идемпотентность по external_order_id исключает двойной учёт при ретраях.

Идемпотентность

Idempotency-Key

На мутирующих POST, которые создают ресурс или двигают деньги (/affiliate/links, /payouts, /merchant/offers, выпуск ключей и платёжные операции), передавайте заголовок:

Idempotency-Key: 3f8a1c2e-7b3d-4c1a-9f2e-1a2b3c4d5e6f
Idempotency-Keystringoptional
UUID v4, который генерирует клиент. Повтор того же запроса с тем же ключом и тем же телом вернёт сохранённый ответ.

Поведение при повторе:

  • Тот же ключ + то же тело → возвращается сохранённый ответ (тот же 2xx) с заголовком Idempotent-Replay: true. Побочный эффект (создание, списание) выполняется ровно один раз.
  • Используйте один и тот же ключ при ретраях из-за сетевого таймаута — так вы не создадите второй оффер/вторую заявку на вывод.

Дедупликация постбэка

У постбэка собственная, более сильная идемпотентность — по external_order_id, поэтому Idempotency-Key для него вторичен и не обязателен.

  • Ключ дедупликации — external_order_id бизнеса (в связке с tenant и видом события).
  • Повторный постбэк с тем же external_order_id не создаёт вторую конверсию: ответ — 200 с "duplicate": true и тем же conversion_id.
  • Конкурентные одновременные постбэки сериализуются advisory-блокировкой — гонка не приводит к дублю.
  • Дедуп-запись хранится постоянно; для практических ретраев ориентируйтесь на окно 24 часа — в его пределах повтор гарантированно вернёт исходный результат.
Повторный постбэк → 200
{ "accepted": true, "duplicate": true, "conversion_id": 778 }

Уникальность external_order_id

external_order_id должен быть уникальным на стороне бизнеса для каждого заказа. Если переиспользовать его для разных конверсий, второе событие будет воспринято как дубликат и не засчитается.

Анти-replay подписи (S2S)

Для подписанных S2S-запросов (постбэк, token-exchange) дополнительно действует защита от воспроизведения перехваченного запроса:

  • X-Timestamp должен быть в пределах ±300 секунд от серверного времени, иначе POSTBACK_STALE_TIMESTAMP (400).
  • Пара (key_id, signature) помечается использованной в Redis на 600 секунд; повтор той же подписи → POSTBACK_REPLAY (409).

Это значит: каждый S2S-запрос подписывайте заново с актуальным X-Timestamp, а ретраи делайте именно повторной отправкой того же external_order_id (логическая идемпотентность), а не переотправкой байт-в-байт той же подписи. Детали подписи — на странице Постбэк.

Что дальше