Retry requests and download files
Use with your agent
Read https://thirds.ai/docs/recovery and add safe retries, job polling, and verified downloads to my thirds.ai integration
A request can reach thirds.ai even when your app loses the response. Keep the job ID as soon as you receive it, then check that job before you create another output. This guide shows how to retry a request and collect its file without paying for a duplicate.
Retry a request without a second job
Give each intended output one Idempotency-Key. Save the key with the request and reuse it after a connection timeout. The same account, operation, key, and input return the same job. Even if retries arrive together, they create at most one job and one credit reservation.
Keys last 24 hours. A reused key can return Idempotency-Replayed: true during that period. If you change the input, the same key returns 409 idempotency_conflict.
For saved templates, send an exact version number in requests you may retry. If you leave it out, publishing a new template version can change which version the request selects.
The wait field changes only how long the response waits. It does not change the output or its price. After a key expires, it no longer protects you from a second job. Keep the job ID beside your own record, such as the invoice that needs that PDF.
Poll the job until it ends
POST /v1/pdf and POST /v1/image return a job object. A 200 response means the job has finished, which can include failure or cancellation. Read status to find out which. A 202 response means you need to check the job again. Send wait: false to skip the initial wait.
Check GET /v1/pdf/{id} or GET /v1/image/{id} with an API key from the same account. Use Location and Retry-After when the response includes them. Set a time deadline for polling in your app. If the deadline ends first, save the job ID and check it later.
| Status | Next step |
|---|---|
queued | Wait before you check again. |
running | Keep polling with a delay while the render runs. |
succeeded | Read download and save the file. |
failed | Stop polling and inspect error.category and error.code. |
cancelled | Stop polling. This job produces no new output. |
A job in one of the last three states never restarts. thirds.ai retries some internal failures before the job reaches its final state. Keep checking the same job while it runs. You can use webhooks to receive the result on your server instead of polling.
Handle errors by code
Request errors include an error object with a stable code and request_id. Failed jobs include an error with category and code. Use these fields to decide what your app does next. The message text can change.
| Error | What to do |
|---|---|
400 or 422 validation error | Correct the named request fields or template data. |
401 authentication error | Check the API key and Bearer header. |
403 account_suspended | Contact support and stop submitting work. |
409 idempotency_conflict | Find the original request, or use a new key if you want a new output. |
402 credit or spend-cap error | Follow billing recovery. |
429 rate_limited, account_concurrency_limited, or key_concurrency_limited | Wait for Retry-After, then retry with the same key. Send fewer requests at once. |
429 abuse_limited | Stop repeated failures. Fix their cause and follow the retry delay. |
503 overloaded | Wait for Retry-After, then retry the same request with the same key. |
Job category invalid_input or unsafe_asset | Fix the HTML, script, or asset before you create another render. |
Job category resource_limit or timeout | Reduce the work or fix JavaScript readiness. The same unchanged request can fail again. |
Job category renderer_failure or internal_failure | Internal recovery has ended. Use a new job with a limit on retries, or contact support. |
The OpenAPI contract lists response fields. If you contact support, include the job ID, request ID, and error code. Keep API keys, signed links, and private content out of support messages and logs.
Download and keep the file
Read a successful job to get a fresh download.url while its file remains available. This signed link lasts 15 minutes. Resolve the path against https://thirds.ai before you download it. Anyone with the link can collect the file without an API key, so keep it private.
Save the file in your own storage before artifact.expires_at. Account outputs stay available for 30 days. Anonymous playground outputs stay for one hour. The two expiry fields tell you different things. download.expires_at is the link deadline, and artifact.expires_at is the file deadline.
An expired valid link returns 403. Read the job again for a fresh link. A missing, deleted, or expired file returns 404. A new link cannot restore that file. If download is null, check status and artifact.removed_reason.
Before you mark delivery complete, compare the file's byte count and SHA-256 with artifact.byte_size and artifact.sha256. If a transfer stops early, download the file again. You do not need another render.
Delete an output
Call DELETE /v1/pdf/{id} or DELETE /v1/image/{id} to remove a file before its expiry date. You can repeat the delete request safely. A successful job stays in history. A failed or cancelled job leaves history, but you can still read it by ID. Deletion does not change credits or retry keys. Queued and running jobs return 409.
Deletion stops new downloads. A download that has already opened the file can finish. The credit charge for a successful output stays in place. thirds.ai removes render input after the job ends. See the privacy policy for storage and backup terms.
Stay within the limits
Every plan has the same render limits. Higher plans give you more credits and a different place in the queue.
| Limit | Maximum |
|---|---|
| HTML input | 5 MiB |
| Template data | 1 MiB of canonical JSON |
| One fetched asset | 10 MiB |
| All fetched assets | 20 MiB across at most 128 assets |
| PDF output | 100 pages and 25 MiB |
| Image output | 32,000,000 pixels and 25 MiB |
| Worker render time | 30 seconds |
| Live jobs per account | 16 |
| Live jobs per API key | 8 |
| API-key request rate | 5 per second, with an idle burst of 21 |
Memory, CPU, browser processes, and temporary storage also have safety limits. You pay no credits for a limit failure, but repeated failures count toward abuse controls. Reduce source size, asset count, or document length before you retry.
Free accounts get a monthly credit grant. Anonymous playground use has its own limit of 200 renders per browser each month. There is no lifetime render quota. See credits and billing for credit grants, expiry dates, and spending limits.