Most Templified API endpoints that trigger a render return immediately with a 202 Accepted response and a poll_url — the render runs in the background while your code moves on. This article explains the response shapes, how to poll for the result, when to use synchronous mode, and what happens when billing blocks a request.
The default: 202 Accepted
When you call POST /api/v1/create (or POST /api/v1/studio/create-and-render, POST /api/v1/design-groups/create, or the Studio export routes) without ?sync=true, the API accepts the job immediately and returns:
HTTP/1.1 202 Accepted
{
"job_id": "clx_abc123...",
"status": "pending",
"poll_url": "/api/v1/create/clx_abc123..."
}
The render is now queued. Your code must record job_id and poll poll_url — or set up a webhook_url on the request body — to learn when the image is ready.
A second type of 202: async export
Export routes (GFcrew send, Dropbox send, webhook send, Send-To preset) use a slightly different 202 shape when the export is queued asynchronously:
HTTP/1.1 202 Accepted
{
"ok": true,
"async": true,
"job_id": "clx_abc123..."
}
Always branch on result.async. When async is true, fields like outputUrl or destination-specific identifiers are not present — they are only available after the render and dispatch complete. Code that reads those fields without checking result.async first will see undefined.
// ✅ Correct — branch before reading response fields
if (result.async) {
// store result.job_id; poll or await webhook
} else {
// result.outputUrl is present now
console.log(result.outputUrl);
}
// ❌ Wrong — crashes when the response is async
console.log(result.outputUrl.length);
Polling for a result
Use GET /api/v1/create/:job_id (authenticated with your API key) to check status. Poll every 2–3 seconds until status is a terminal value.
status |
Meaning | What to do |
|---|---|---|
pending |
Job is in the queue, not yet picked up | Keep polling |
processing |
Render is actively running | Keep polling |
complete |
Render finished successfully | Read output_url and stop polling |
failed |
Render encountered an error | Read the error, stop polling, and retry if appropriate |
A complete response includes:
HTTP/1.1 200 OK
{
"job_id": "clx_abc123...",
"status": "complete",
"template_id": "tpl_...",
"output_url": "https://cdn.templified.io/renders/...",
"render_ms": 4210,
"created_at": "2026-06-12T14:00:00.000Z",
"completed_at": "2026-06-12T14:00:04.210Z"
}
If you submitted the job with a send_to destination, the poll response also includes send_to_status (one of pending, delivering, delivered, or failed) once the render itself is complete. A send_to_status of failed adds a send_to_error field with a human-readable reason.
Synchronous mode (?sync=true)
POST /api/v1/create?sync=true blocks the request for up to 25 seconds and returns the completed render inline (200 OK) if it finishes in time. If the render takes longer than 25 seconds, the endpoint falls back to a 202 with a poll_url so you can continue polling.
Synchronous mode is convenient when:
- You are building a real-time integration where polling is cumbersome (for example, a single render triggered by a user action).
- Your renders reliably complete in well under 25 seconds (simple templates without Background Removal typically render in 2–8 seconds).
Avoid sync mode for:
- Batch workflows or design-group renders — queue many jobs and poll or use webhooks instead.
- Renders that include Background Removal — these can take longer and will regularly time out to 202.
- High-volume automation — holding a connection open for 25 seconds under load is inefficient.
Using a webhook instead of polling
Pass a webhook_url on the POST /api/v1/create request body to receive a push notification instead of polling. Templified POSTs the result to your URL when the render (and any Send-To side-effect) completes. This is the most efficient pattern for background batch processing.
See Setting up a webhook for the full notification shape and security (HMAC verification).
402: billing blocked
If your organization's balance is exhausted or the account is suspended, the API returns 402 Payment Required before a render job is created:
HTTP/1.1 402 Payment Required
{
"error": "Insufficient balance"
}
Renders are never silently dropped — a 402 means no job was queued and no charge was attempted. To resume, add funds to your balance on the Billing page and resubmit the request. A suspended account (dunning after a failed card charge) requires a payment-method update before any renders can proceed.
Summary of routes and their async behavior
| Route | Default response | Sync mode available |
|---|---|---|
POST /api/v1/create |
202 with job_id + poll_url
|
Yes — ?sync=true
|
POST /api/v1/studio/create-and-render |
202 with job_id + poll_url
|
Yes — ?sync=true
|
POST /api/v1/design-groups/create |
202 with job_id + poll_url
|
No |
| Studio export routes (GFcrew, Dropbox, webhook, preset) |
202 with ok/async/jobId shape (when async-flagged) |
No |
GET /api/v1/create/:job_id |
200 with current status |
N/A (poll endpoint) |
Comments
0 comments
Article is closed for comments.