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

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

Как безопасно повторять запросы — idempotencyKey на переводах и другие механизмы защиты от дублей.

Сетевые сбои делают ретраи неизбежными. V3 Custody защищает от случайных дублей — прежде всего, у перевода есть idempotencyKey, поэтому повтор запроса не задвоит платёж.

idempotencyKey на переводах

POST /api/v1/vaults/{code}/transfers принимает idempotencyKey. Повтор запроса с тем же ключом вернёт уже созданный перевод, а broadcast не повторяется — в ответе приходит существующая операция (replay).

# первый запрос создаёт перевод; повтор с тем же ключом вернёт его же
curl -X POST "[BASE_URL]/api/v1/vaults/acme-otc/transfers" \
  -H "Authorization: Bearer $V3_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "fromAddressId": "cmr3f41z20001psp7phmyapw3",
    "toAddress": "TQ2m...p4rX",
    "token": "usdt",
    "amount": "1350.00",
    "idempotencyKey": "payout-2026-03-14-001"
  }'

Ключ сохраняется вместе с созданным переводом: второй запрос с тем же ключом коротко замыкается на существующую операцию, а не создаёт и не отправляет её повторно.

Рекомендации

  • Всегда передавайте idempotencyKey на переводах.
  • Делайте ключ стабильным идентификатором бизнес-операции (id инвойса, выплаты), а не случайным на каждый ретрай, — иначе повтор создаст новый платёж.
  • Один ключ = один платёж; для нового платежа — новый ключ.

Другие механизмы безопасного повтора

idempotencyKey — про переводы. У других изменяющих операций своя защита от дублей и гонок:

  • Гранты на адрес (POST /shares) идемпотентны по субъекту: повторная выдача обновляет или реактивирует грант, а не плодит дубли.
  • Финальное подтверждение заявки использует optimistic-lock: если цель изменилась с момента создания, применение не повторяется — заявка помечается REJECTED (stale). Подробнее — на странице Аппрувалы.
  • Создание адреса подбирает pathIndex с повтором при конкурентном конфликте, поэтому параллельные запросы не займут один путь.

Что дальше