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

Идемпотентность защищает от повторного выполнения одного действия при повторах HTTP-запроса. Используйте один `Idempotency-Key` для одного действия, например создания или отмены счёта. Если ответ потерян, повторите запрос с тем же ключом и входными данными: API может вернуть сохранённый результат без повторного выполнения действия.

## Где нужен заголовок 

Обязательность заголовка указана в справочнике операции. Сам по себе метод POST не определяет правило.

| API | Где обязателен | Исключения |
|  --- | --- | --- |
| [Platform v2](/ru/apis/platform/api) | Указанные в контракте изменения и внешние действия, включая обновление баланса, тест канала и повторную отправку уведомления | GET, поиск балансов и симуляция EVM |
| [Management](/ru/apis/mgmt/api) | Все POST, PATCH и DELETE этого API | GET; операции с сессией личного кабинета находятся вне API для management-ключа |
| [VKS](/ru/apis/vks/api) | Все POST и DELETE, включая приглашения signer, прерывание и запросы отправки транзакций | GET |


Эти правила не распространяются на blockchain JSON-RPC и gRPC. Защита от повторного выполнения HTTP-операции не гарантирует однократную доставку вебхука, подпись или исполнение в блокчейне. Ответ `202` на отправку через VKS означает сохранение запроса; результат смотрите в логах транзакции, а подтверждение сети проверяйте отдельно.

## Заголовок и привязка к действию 

Отправляйте ровно один заголовок `Idempotency-Key` со значением из **1–128 видимых ASCII-байтов** (`0x21`–`0x7e`, шаблон `^[!-~]+$`). Значение непрозрачно и чувствительно к регистру. UUID допустим, но не обязателен. Не обрезайте значение, не меняйте регистр и не делите его: запятая является частью данных. Повторные заголовки недопустимы даже с одинаковыми значениями; пробельные и не-ASCII символы тоже недопустимы.

Ключ связывается с вызывающим, операцией и её целью. Platform дополнительно учитывает проект, VKS - рабочее пространство. В Management цель запроса определяет рабочее пространство или ресурс. Тот же ключ у другого вызывающего или для другой цели не восстанавливает исходный результат. При повторе сохраняйте исходные учётные данные и область доступа.

До первой попытки сохраните ключ, метод, цель, параметры и полное тело запроса вместе с описанием действия в вашем приложении. Данные должны переживать перезапуск процесса. Генерируйте даты, сроки и случайные поля тела один раз; повтор не должен обновлять `expires_at` счёта. Каждому отдельному действию нужен другой ключ. Не используйте ключ завершённого действия для следующего даже после истечения срока ответа.

Каждая попытка, включая повтор, проверяет текущую [аутентификацию](/ru/apis/authentication) и [права](/ru/apis/permissions). Ключ идемпотентности не даёт доступа. Отзыв учётных данных или прав может запретить повтор; смена вызывающего может привести к отдельному эффекту.

## Запрос и повтор 

1. Откройте [регистрацию внешнего адреса](/ru/apis/platform/api/address/create-external-address). Используйте ключ проекта с правом `api:address:write`.
2. Выберите свой адрес, семейство сети и метку. Создайте один `Idempotency-Key` и сохраните его вместе с полным телом запроса.
3. Отправьте запрос через форму на странице операции или используйте один из её примеров для своего клиента.
4. Если ответ потерян, повторите запрос с тем же ключом, телом, параметрами и учётными данными. Не создавайте новый ключ, пока исход неизвестен.
5. Сохраните возвращённый идентификатор ресурса. Для другого адреса или метки сначала выясните результат предыдущего действия, затем начните новое.


## Сроки повтора и текущее состояние 

| Результат | Срок и условия повтора |
|  --- | --- |
| Обычный успешный ответ | 24 часа с исходного успешного завершения |
| Ответ Platform с секретом подписи вебхука | 60 секунд с завершения, только пока секрет текущий; замена, удаление или отзыв могут сделать повтор недоступным |
| Секрет API/RPC-ключа, созданного через Management API | 60 секунд с успешного создания при текущем доступе и допустимом состоянии ключа; отозванные или удалённые ключи не восстанавливаются |
| Секрет приглашения VKS `POST /signers` | 60 секунд с успешного создания, только пока приглашение не использовано, не истекло и не удалено |


Повторы не продлевают эти сроки. Сразу сохраняйте секреты в менеджере секретов; поздний GET не восстанавливает открытое значение.

Окно повтора ответа с приглашением VKS отличается от срока первого использования и от повтора регистрации тем же signer с ранее полученным токеном. Приглашение может оставаться пригодным для использования после закрытия окна повтора HTTP-ответа. После успешной регистрации тот же signer может повторить настройку с исходным токеном даже после срока первого использования, пока signer не удалён.

Повтор возвращает исходный снимок ответа, включая первоначальное состояние ресурса. Для текущего состояния используйте GET ресурса, **если знаете его ID**. Повтор прерывания или удаления в VKS и удаления проекта в Management может вернуть исходный успех после изменения или удаления цели, пока текущий доступ к рабочему пространству разрешает повтор. Удалённое рабочее пространство не остаётся доступным через старый ключ идемпотентности.

Надёжно сохранённая привязка ключа остаётся навсегда после истечения срока ответа. Истечение срока не запускает операцию заново и не разрешает второй эффект с этой привязкой. Отказ из-за заголовка или валидации до эффекта сам по себе не доказывает наличие сохранённой привязки: не каждый отправленный ключ резервируется и не каждый ответ с ошибкой кешируется.

## Ответы и восстановление 

Читайте `code` проблемы вместе с HTTP-статусом. Другие бизнес-конфликты тоже возвращают `409`; см. [Ошибки](/ru/apis/errors).

| Ответ | Действие |
|  --- | --- |
| Отсутствующий, некорректный или повторный заголовок: `400` | Исправьте заголовок. Platform и VKS используют `idempotency_key_invalid`; Management описывает схему ответа `InvalidRequestProblem`. Отклонённый заголовок не доказывает сохранение эффекта. |
| `409 idempotency_in_progress` | Другая попытка с этой привязкой выполняется. Выдержите паузу и повторите тот же ключ и данные; не запускайте параллельные замены. |
| `409 idempotency_request_mismatch` | Сравните с сохранёнными исходными методом, целью, параметрами и телом. Для повтора восстановите исходные данные; изменённые данные не должны перезаписывать сохранённый исходный запрос. |
| `409 idempotency_result_expired` | Сохранённый ответ больше недоступен. Выясните результат исходного действия; операция не повторяется. VKS также использует этот код, когда приглашение signer больше не допускает повторную выдачу секрета. |
| `409 idempotency_result_unavailable` (Platform) | Проверьте текущее состояние ресурса или секрета. Повтор не восстанавливает заменённый или удалённый секрет. |
| Текущие `401`, `403` или `404` области доступа/ресурса | По возможности восстановите законный доступ. Ключ идемпотентности не обходит проверки. |
| Тайм-аут, обрыв соединения или `5xx` | Эффект уже мог произойти. Повторяйте с паузой, тем же ключом и неизменными данными, пока сохранённый ответ доступен. |
| Явный отказ валидации до любого эффекта | Исправьте данные по правилам операции. Это отличается от потери ответа с неизвестным исходом; не считайте любую ошибку сохранённым результатом. |


Сначала выясните результат исходного действия
Не генерируйте новый ключ автоматически после истечения срока, недоступного ответа или неопределённого исхода. Новый ключ может создать второй эффект. Создание нового ключа должно быть отдельным решением после проверки исходного результата.

Если ID ресурса известен, прочитайте его и связанные логи. Если ответ создания потерян и ID неизвестен, используйте только реально доступные в этом API списки и фильтры, сопоставляя их с сохранёнными бизнес-данными. Публичного эндпоинта статуса идемпотентности или поиска по ключу нет. Список не всегда позволяет однозначно найти ресурс, а metadata не является универсальным фильтром. Если исход не выяснен, сохраните описание исходного действия и данные запроса для обращения в поддержку; восстановить потерянный ID удаётся не всегда.