The async contract#
POST /v1/renders returns 202 immediately. The image is not ready yet and there is no URL in this response:
{ "id": "6f1c…", "status": "pending", "output_url": null }Poll GET /v1/renders/:id until status is completed, then read output_url. A failed render reports status: "failed" with an error message — and the credit is refunded automatically. You are charged only for images you receive.
The Prefer: wait shortcut#
Send the header Prefer: wait and the API blocks for up to ~10 seconds. Most renders finish well inside that, so you get a 200 with output_url already filled in. If it can’t finish in time, you get the normal 202 and fall back to polling — handle both.
curl -X POST https://api.anjin.design/v1/renders \
-H "Authorization: Bearer $ANJIN_API_KEY" \
-H "Content-Type: application/json" \
-H "Prefer: wait" \
-d '{"template": "acme_story_1080x1920", "modifications": [
{"name": "headline", "text": "New drop Friday"}]}'Two URLs, two lifetimes#
| Field | Lifetime | Use |
|---|---|---|
output_url | signed, ~1 hour | For immediate download. It expires roughly an hour after you fetched the response — never store or hotlink it. |
asset_url | permanent | The durable public copy placed in your project's Renders folder. Use this for anything you save or hand to another system. |
Formats and scale#
format:png(default),jpgorwebp.scale:1–4, multiplying the template’s own dimensions. Cost is scale² credits — 1, 4, 9, 16 — because that is what the pixels do. The response tells you what was charged.
Input image limits#
Images you pass into slots via image_url are bounded twice, and both failures are structured 422s that charge nothing:
- 25 MB maximum encoded file size.
- 40 megapixels maximum decoded size — a small file that decodes enormous is rejected as
image_too_largebefore rendering starts.
Errors#
Every error is a structured envelope — { "error": { "code", "message" } }:
| Code | Status | Meaning |
|---|---|---|
template_not_published | 422 | Publish the frame first. No credit charged. |
unknown_slot | 422 | Names the offending slot. No credit charged. |
image_out_of_folder | 422 | A folder-bound slot was given an image outside its folder. |
image_too_large | 422 | A slot image exceeded the size limits above. |
insufficient_credits | 402 | Includes the amount required. |
invalid_scale / invalid_format | 400 | scale must be 1–4; format must be png, jpg or webp. |
rate_limited | 429 | Back off for the seconds in the Retry-After header. See rate limits. |
