Safe retries
A render can take up to about 95 seconds. If your connection drops or your client gives up before
the answer arrives, you cannot tell whether the render was made and its credits spent. Send an
Idempotency-Key header, and sending the request again gives you the first answer instead of a
second render.
The Idempotency-Key header is optional. Without it, every request renders and spends credits.
These endpoints take it:
POST /v1/image/htmlPOST /v1/image/templatePOST /v1/image/bulkPOST /v1/pdf/htmlPOST /v1/pdf/template
Send a key
Pick a key that names the job, such as an order or invoice number, or a random UUID. A key is 1 to 255 visible ASCII characters.
curl -X POST https://api.ojo.so/v1/pdf/template \
-H "Authorization: Bearer <your API key>" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: invoice-2026-0042" \
-d '{"templateId": "<your template id>", "modify": {"customer": "Acme Inc."}}'How it works
- A retry is the same request with the same key: the same endpoint, body and render option headers.
- The first request with a key renders. A request with the same key after it has answered gets that
answer again, with the header
Idempotent-Replayed: true, and spends nothing. - Only an answer that spent credits is stored. A request that failed stores nothing, so you can send it again under the same key and it renders as new.
- Keys are per account: every API key of your account shares them, and another account’s keys never meet yours.
- oJo keeps an answered key for 24 hours. After 24 hours the key is forgotten, and a request with it renders again and spends credits.
When to retry
If your request times out, send the same request again with the same key.
A 409 means the first request with this key is still rendering: wait the seconds in Retry-After,
then send the same request again with the same key to get its answer.
A bulk answer lists each item that failed in errors. For a bulk request, retry the failed items in
a new request under a new key, since the first key replays the first answer.
Give your client a timeout of at least 100 seconds, so it waits for the render to finish.
Answers for a key
400- TheIdempotency-Keyis empty, longer than 255 characters, or holds a space or a character outside visible ASCII.codeisidempotency_key_invalid.409- A request with this key is still rendering.codeisidempotency_key_in_progress, andRetry-AfterandretryAftergive the wait in seconds.422- The key was sent before with a different request.codeisidempotency_key_reused. Send a new key for a new request.