Что такое ключ идемпотентности (Idempotency-Key)
Ключ идемпотентности (Idempotency-Key) — уникальный идентификатор запроса, по которому сервер распознаёт повтор и возвращает прежний результат вместо повторного выполнения операции.
Сеть ненадёжна. Ваш сервер отправил запрос «создать выплату», а ответ не пришёл — таймаут, обрыв соединения, перезапуск. Выплата создалась или нет? Если отправить запрос ещё раз без защиты, можно заплатить дважды. Ключ идемпотентности решает эту проблему: клиент генерирует уникальную строку, передаёт её в заголовке Idempotency-Key, и сервер запоминает результат, связанный с этим ключом.
Если запрос с тем же ключом приходит повторно, сервер не выполняет операцию заново, а возвращает тот же ответ, что и в первый раз. Для клиента это значит, что повторять запросы безопасно: сколько бы раз вы ни отправили «создать выплату с ключом X», выплата будет одна. Такой подход популяризировал Stripe, а сейчас заголовок Idempotency-Key описывается в черновике стандарта IETF.
Ключ должен быть привязан к намерению, а не к попытке. Правильно — генерировать его один раз для конкретной операции (например, UUID, сохранённый вместе с заказом или заявкой на выплату) и использовать при всех повторах. Неправильно — генерировать новый ключ при каждой попытке: тогда защита не работает. Ещё одна ошибка — использовать один ключ для разных операций: сервер вернёт результат первой, и вторая просто не выполнится или вызовет ошибку несовпадения параметров.
Идемпотентность важна именно там, где повтор стоит денег: создание платежа, выплаты, подписки. Для чтения данных она не нужна — GET-запрос и так безопасно повторять. На своей стороне то же правило стоит применять к обработке вебхуков: событие с уже известным идентификатором обрабатывать повторно нельзя.
В API Moonvex заголовок Idempotency-Key обязателен при создании платежей, выплат и подписок: повторный запрос с тем же ключом не создаст второй платёж или вторую выплату.