Skip to Content
Safe Retries

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/html
  • POST /v1/image/template
  • POST /v1/image/bulk
  • POST /v1/pdf/html
  • POST /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 - The Idempotency-Key is empty, longer than 255 characters, or holds a space or a character outside visible ASCII. code is idempotency_key_invalid.
  • 409 - A request with this key is still rendering. code is idempotency_key_in_progress, and Retry-After and retryAfter give the wait in seconds.
  • 422 - The key was sent before with a different request. code is idempotency_key_reused. Send a new key for a new request.