Skip to content
Руководства

Best practices

Practices for a reliable Clipia API integration — idempotent retries, webhooks over polling, error and 429 handling with backoff, cost estimation, and storing request_id.

To make your Clipia API integration reliable and predictable on cost, follow five practices: make submissions idempotent, prefer webhooks over polling, handle errors and 429 with exponential backoff, estimate cost before submitting, and store the request_id on your side. Each practice is covered below.

Idempotent retries

Send an Idempotency-Key (a unique UUID v4 per logical request) on every submit. If the network drops, retry with the same key and the same parameters — you get the same request_id back, with no duplicate generation and no second charge. The key is stored for 24 hours.

curl -X POST https://api.clipia.ai/v1/models/nano-banana-2 \
  -H "Authorization: Bearer clipia_live_xxx" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 8f3a1c7e-2b41-4d2a-9c0e-1200304cf45b" \
  -d '{ "input": { "prompt": "a sunset over mountains, cinematic" } }'
ScenarioResult
same key + same parametersthe same request_id, no second charge
same key + different parameters409 idempotency_key_reuse
retry while the first is still processing409 request_in_progress

One key per logical request

Generate a fresh UUID v4 for each new generation, not for each network retry. Never put sensitive data (an email and so on) in the key.

Webhooks over polling

Pass a webhook_url on submit — Clipia sends a POST when the job finishes, so you don't have to poll. Keep polling as a fallback. If you do poll, do it sensibly (say, once every 1–3 seconds), not in a tight loop.

  • Respond 2xx within 10 seconds, or delivery is retried (up to 6 attempts with exponential backoff).
  • Verify the X-Clipia-Signature (HMAC-SHA256) on every delivery.
  • Handle deliveries idempotently by request_id — redelivery is possible.

Error and 429 handling with backoff

Errors arrive in a single JSON shape with error.type, error.code, and error.message. React by HTTP status.

HTTPcodeWhat to do
400 / 422invalid_request / model_input_invalidfix the body/parameters; don't retry as-is
401 / 403invalid_api_key / insufficient_scopecheck the key and scope
402insufficient_creditstop up the balance
429rate_limit_exceededwait Retry-After seconds, then retry
500 / 503internal_error / service_unavailableretry with exponential backoff

On 429, follow the Retry-After header and the RateLimit-* metrics:

RateLimit-Limit: 120
RateLimit-Remaining: 0
RateLimit-Reset: 37
Retry-After: 37

Exponential backoff with jitter

For 429, 500, and 503, retry with a growing pause and random jitter (e.g. 1s, 2s, 4s, 8s… plus a random add-on) to avoid thundering herds. Default limits are 120 RPM and 10 concurrent generations per key.

Estimate cost before submitting

The operation price is fixed and known up front. To learn the cost of a specific parameter set without queuing, use POST /v1/models/{model}/estimate — it returns credits. This lets you show the cost to a user or reject expensive requests early. On submit the price is echoed in the cost field; if credits are short, submit returns 402.

Store the request_id

Persist each submission's request_id in your database right after the submit response. You need it to:

  • match an incoming webhook to your entity;
  • poll status_url / response_url when needed;
  • enforce idempotency on your side (don't process a delivery twice).

Pair request_id with Idempotency-Key

Store the pair Idempotency-Keyrequest_id: if the submit response is lost, a retry with the same key returns the same request_id, so you never create a duplicate generation.