---
title: Рекомендации
description: Как надёжно интегрироваться с Clipia API — идемпотентные повторы, вебхуки вместо опроса, обработка ошибок и 429, оценка стоимости и хранение request_id.
icon: BadgeCheck
---

Чтобы интеграция с Clipia API была надёжной и предсказуемой по стоимости, придерживайтесь пяти практик: делайте отправки идемпотентными, предпочитайте вебхуки опросу, обрабатывайте ошибки и `429` с растущей паузой, оценивайте стоимость до отправки и сохраняйте `request_id` у себя.

## Идемпотентность при повторах [#idempotency]

Передавайте `Idempotency-Key` при каждой отправке — уникальный UUID v4 на каждый **логический** запрос. Если соединение оборвалось, повторите запрос с тем же ключом и тем же телом: вернётся **тот же** `request_id`, без второй генерации и второго списания. Ключ действует 24 часа в пределах одного API-ключа.

```bash
curl -X POST https://api.clipia.ai/v1/models/nano-banana-2 \
  -H "Authorization: Bearer $CLIPIA_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 8f3a1c7e-2b41-4d2a-9c0e-1200304cf45b" \
  -d '{ "input": { "prompt": "a sunset over mountains, cinematic" } }'
```

| Ситуация | Результат |
| --- | --- |
| Тот же ключ и то же тело | Тот же `request_id`, без повторного списания |
| Тот же ключ, другая модель или другое тело | `409 idempotency_key_reuse` |
| Повтор, пока первый запрос ещё обрабатывается | `409 request_in_progress` — повторите через несколько секунд |

<Callout type="warn" title="Один ключ на логический запрос">
Создавайте новый UUID на каждую новую генерацию, а не на каждую сетевую попытку. SDK подставляют случайный ключ сами, но для безопасного повтора передайте свой и используйте его снова. Не кладите в ключ персональные данные. Подробнее — в разделе [«Идемпотентность»](/ru/docs/api-reference/idempotency).
</Callout>

## Вебхуки вместо опроса [#webhooks]

Передайте `webhook_url` (только `https://`) при отправке — Clipia сам пришлёт `POST`, когда задача завершится, и опрашивать статус не придётся. Опрос держите запасным вариантом и делайте его не чаще раза в 1–3 секунды.

- Отвечайте `2xx` в течение 10 секунд, иначе доставка повторится — всего до 15 попыток с растущей паузой, около 24 часов.
- Проверяйте подпись `X-Clipia-Signature` (HMAC-SHA256) на каждой доставке. Секрет вебхуков свой у каждого API-ключа.
- Обрабатывайте доставки **идемпотентно** по `request_id`: одна и та же доставка может прийти повторно.

Подробнее — в разделе [«Вебхуки»](/ru/docs/api-reference/webhooks).

## Ошибки и 429 [#errors]

Ошибки приходят в едином формате: объект `error` с полями `type`, `code` и `message`. Решение принимайте по HTTP-статусу и `code`.

| HTTP | `code` | Что делать |
| --- | --- | --- |
| `400` / `422` | `invalid_request` / `model_input_invalid` | Исправить тело или параметры, не повторять как есть |
| `401` / `403` | `invalid_api_key` / `insufficient_scope` | Проверить ключ и его права |
| `402` | `insufficient_credits` | Пополнить баланс |
| `409` | `request_in_progress` | Повторить через несколько секунд с тем же ключом идемпотентности |
| `429` | `rate_limit_exceeded` | Подождать `Retry-After` секунд и повторить |
| `429` | `concurrency_limit_exceeded` | Дождаться завершения одной из задач |
| `500` / `503` | `internal_error` / `service_unavailable` | Повторить с растущей паузой |

При `429` ориентируйтесь на `Retry-After` и заголовки `RateLimit-*`. `RateLimit-Reset` — момент сброса окна в Unix-секундах, а не число секунд до него:

```http
RateLimit-Limit: 120
RateLimit-Remaining: 0
RateLimit-Reset: 1760011260
Retry-After: 37
```

<Callout type="info" title="Растущая пауза со случайной добавкой">
Для `429`, `500` и `503` повторяйте с растущей паузой и случайной добавкой — например 1, 2, 4, 8 секунд, не больше пяти попыток, — чтобы повторы разных клиентов не совпадали. Лимиты по умолчанию: 120 запросов в минуту на ключ и 600 на все ключи аккаунта. Лимит одновременных генераций действует, только если он задан для ключа или аккаунта. Подробнее — в разделе [«Лимиты»](/ru/docs/api-reference/rate-limits).
</Callout>

## Оценка стоимости до отправки [#estimate]

Чтобы узнать цену конкретного набора параметров без постановки в очередь, вызовите `POST /v1/models/{model}/estimate` — он вернёт `credits`. Так можно показать стоимость пользователю или заранее отсечь дорогие запросы. При отправке в поле `cost` приходит сумма, зарезервированная под задачу; при нехватке кредитов отправка вернёт `402`. Подробнее — в разделе [«Оценка стоимости»](/ru/docs/api-reference/estimate).

<Callout type="info" title="Цены">
Цены моделей меняются вместе с каталогом: точную сумму в кредитах под ваши параметры возвращает `estimate`, а при отправке она приходит в поле `cost` до списания.
</Callout>

## Хранение request_id [#request-id]

Сохраняйте `request_id` каждой отправки в своей базе сразу после ответа. Он нужен, чтобы:

- сопоставить пришедший вебхук с вашей сущностью;
- при необходимости опросить `status_url` или `response_url`;
- не обработать одну доставку дважды.

<Callout type="warn" title="Связка Idempotency-Key и request_id">
Храните пару `Idempotency-Key` → `request_id`. Если ответ на отправку потерялся, повтор с тем же ключом вернёт тот же `request_id`, и дубль генерации не появится.
</Callout>
