Интеграции

API и webhooks: как не потерять заявки и события

Интеграция считается рабочей не тогда, когда один запрос прошёл, а когда она переживает повторы, падения внешнего сервиса, задержки сети и дубли событий.

1. Webhook сначала сохраняем

Не делай тяжёлую обработку прямо в webhook request. Сначала сохрани payload, ответь 200, дальше обработай worker’ом.

POST /webhooks/payment
1. verify signature
2. save raw payload
3. return 200 OK
4. enqueue processing job

2. Idempotency key

Один и тот же webhook может прийти несколько раз. Используй внешний event_id или собственный idempotency key.

if Event.objects.filter(external_id=event_id).exists():
    return "already processed"

Event.objects.create(external_id=event_id, payload=payload)

3. Retry policy

  1. Сетевые ошибки повторять.
  2. HTTP 429 повторять позже.
  3. HTTP 400 не повторять без исправления payload.
  4. После нескольких ошибок отправлять alert.

4. Очередь и dead letter

Если обработка несколько раз падает, событие не должно исчезать. Переводи его в failed/dead-letter состояние и показывай в админке кнопку ручного повторения.

status: pending -> processing -> processed
status: processing -> failed
manual action: retry failed event

5. Подписи и безопасность

  • Проверяй signature/HMAC, если сервис её даёт.
  • Не доверяй сумме платежа с frontend.
  • Храни raw payload для разбора спорных случаев.
  • Не логируй токены и персональные данные без нужды.

6. Версии API

Не ломай старых клиентов без переходного периода. Для публичного API лучше сразу держать версию в URL или header.

/api/v1/orders
/api/v1/webhooks/payment
Accept: application/vnd.pyaidev.v1+json

Checklist перед запуском

  • Есть таблица входящих событий.
  • Повтор webhook не создаёт дубль заявки.
  • Ошибки обработки видны в админке или логах.
  • Есть ручной retry для failed events.
  • Есть test endpoint или sandbox mode.
Все постыСледующая инструкция