> ## Documentation Index
> Fetch the complete documentation index at: https://platform.doodocs.kz/llms.txt
> Use this file to discover all available pages before exploring further.

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

> Где работает Idempotency-Key и как безопасно повторять запросы

Сеть рвётся посреди запроса, и клиент не знает, дошёл он или нет. Повтор без
защиты создаёт вторую загрузку или второй документ. Заголовок `Idempotency-Key`
решает эту задачу: сервер запоминает ключ и на повтор отвечает так же, как на
первый запрос, ничего не создавая заново.

## Где он работает сегодня

| Эндпоинт                     | `Idempotency-Key` |
| ---------------------------- | ----------------- |
| `POST /ingest/{source_type}` | **обязателен**    |
| `POST /documents`            | необязателен      |
| Остальные записи             | не поддерживается |

<Warning>
  `POST /files`, `POST /documents/{id}/_send` и остальные записывающие эндпоинты
  заголовок не принимают. Повтор `_send` или действия участника вернёт ошибку
  состояния, а не создаст дубль, поэтому опасен только повтор создания —
  см. «Как жить без идемпотентности» ниже.
</Warning>

## Создание документа

Передайте `Idempotency-Key` в `POST /documents`, и повтор того же запроса
вернёт **тот же** документ вместо второго.

```bash theme={null}
curl -X POST https://app.doodocs.kz/api/developer/v1/documents \
  -H "X-API-Key: $DOODOCS_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: hire-2026-02-10-emp-3f2a" \
  -d '{ "title": "Приказ о приёме", "type_id": "5c9e…", "template_id": "tpl_7c1a…", "template_version": 3 }'
```

| Ситуация                                   | Ответ                                           |
| ------------------------------------------ | ----------------------------------------------- |
| Первый запрос                              | `200`, документ создан                          |
| Повтор того же запроса                     | `200`, тот же документ, второй не создаётся     |
| Тот же ключ, но другое тело                | `409`, код `DEVELOPER.IDEMPOTENCY_KEY_CONFLICT` |
| Повтор, пока первый запрос ещё выполняется | `409`, код `DEVELOPER.IDEMPOTENCY_IN_PROGRESS`  |

Ключ живёт 24 часа и привязан к вашему API-ключу: два разных ключа могут
использовать одинаковую строку, не мешая друг другу. Ключ занимается **до**
создания документа, поэтому два одновременных запроса с одним ключом не создадут
двух документов — это и есть защита от двойной отправки.

Ответ на повтор не берётся из кеша: сервер перечитывает документ обычным путём,
поэтому права проверяются на каждом ответе, а данные всегда свежие.

## Ingest

Ключ передаётся заголовком и выбирается вами. Он должен быть уникальным для
содержимого пачки: одна и та же пачка — один ключ, новая пачка — новый ключ.

```bash theme={null}
curl -X POST https://app.doodocs.kz/api/developer/v1/ingest/KEDO \
  -H "X-API-Key: $DOODOCS_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: employees-2026-02-10-001" \
  -d '{ "payload_type": "EMPLOYEES", "create_missing": true, "records": [] }'
```

| Ситуация                    | Ответ                                          |
| --------------------------- | ---------------------------------------------- |
| Заголовок не передан        | `400`, код `INTEGRATION.IDEMPOTENCY_REQUIRED`  |
| Первый запрос с этим ключом | `200`, загрузка принята со статусом `ACCEPTED` |
| Повтор с тем же ключом      | `409`, код `INTEGRATION.IDEMPOTENCY_REQUIRED`  |

`409` — это не ошибка вашей логики, а подтверждение, что первая попытка дошла.
Обрабатывайте его как успех: повторно слать пачку не нужно.

<Tip>
  Хороший ключ детерминирован и выводится из данных: `employees-2026-02-10-001`,
  `persons-<хеш пачки>`. Случайный UUID, сгенерированный на каждой попытке, защиту
  не даёт — при ретрае он будет новым.
</Tip>

## Как жить без идемпотентности

Для создания документа используйте `Idempotency-Key`. Для остальных записей
снижайте риск так:

<Steps>
  <Step title="Сохраняйте свой идентификатор до вызова">
    Запишите у себя намерение («создать приказ для сотрудника X по шаблону Y»)
    вместе со своим ключом операции, и только потом вызывайте API.
  </Step>

  <Step title="После обрыва не повторяйте вслепую">
    Сначала проверьте, не создался ли документ:
    `GET /documents?type_id=…&created_after=…&search=…`. Если он есть, сохраните
    его `id` и не повторяйте вызов.
  </Step>

  <Step title="Ретраите только чтения и явно безопасные действия">
    `GET`-запросы можно повторять свободно. Повтор `_approve` или `_sign` на уже
    отработавшем слоте вернёт ошибку состояния, а не создаст дубль.
  </Step>
</Steps>

Список документов и его фильтры описаны в
[Списке документов](/ru/guides/documents/list).
