Image renders
Give this prompt to your AI agent. The agent does the task for you.
Read https://thirds.ai/docs/api-reference/image and help me choose the right thirds.ai endpoint and write a request. Check the fields and credentials in this reference.
Create PNG, JPEG, or WebP images from HTML or saved templates, then check each render and download the result.
See all API resources or read API keys and requests.
Endpoints
createImage
POST /v1/image
Create a static image
Render one PNG, JPEG, or WebP from raw HTML, an inline stateless template, or one owned saved-template version. Returns 200 for a terminal job or 202 while the accepted job remains queued or running. A terminal job can be succeeded, failed, or cancelled; check status before downloading. Send wait=false to skip the bounded wait. A successful render costs exactly one credit; a failed or cancelled render costs zero.
Authentication: bearer API key. See authentication.
| Parameter | Location | Required | Rule |
|---|---|---|---|
Idempotency-Key | header | No | {"type":"string","minLength":1,"maxLength":255,"pattern":"^[ -~]+$"} |
Request body: application/json, ImageRequest.
| Status | Meaning | Body |
|---|---|---|
| 200 | The job is terminal. Check status for succeeded, failed, or cancelled; HTTP 200 does not mean the render succeeded. | application/json: ImageJob |
| 202 | The image job is durable and remains queued or running. | application/json: ImageJob |
| 400 | The one error envelope every backend response uses. | application/json: ErrorEnvelope |
| 401 | The one error envelope every backend response uses. | application/json: ErrorEnvelope |
| 402 | The one error envelope every backend response uses. | application/json: ErrorEnvelope |
| 403 | The authenticated account is suspended. The code is account_suspended. | application/json: ErrorEnvelope |
| 405 | The method is not allowed on this route. | application/json: ErrorEnvelope |
| 409 | The one error envelope every backend response uses. | application/json: ErrorEnvelope |
| 413 | The one error envelope every backend response uses. | application/json: ErrorEnvelope |
| 415 | The one error envelope every backend response uses. | application/json: ErrorEnvelope |
| 429 | The one error envelope every backend response uses. | application/json: ErrorEnvelope |
| 431 | The request has more than 64 headers or more than 32 KiB of header names and values. | application/json: ErrorEnvelope |
| 500 | The one error envelope every backend response uses. | application/json: ErrorEnvelope |
| 503 | The one error envelope every backend response uses. | application/json: ErrorEnvelope |
listImageHistory
GET /v1/image
List image history
List the authenticated account's image jobs, newest first. Failed or cancelled jobs removed through DELETE do not appear. Bounded by keyset: pass the previous page's next_cursor to continue, rather than an offset, so a page already read stays stable while new jobs are created.
Authentication: bearer API key. See authentication.
| Parameter | Location | Required | Rule |
|---|---|---|---|
q | query | No | Case-insensitive search of references, template names, and file types. {"type":"string","maxLength":200,"pattern":"^[^\\u0000-\\u001f\\u007f-\\u009f]*$"} |
limit | query | No | 1 to 100. Defaults to 20. A value outside this range is clamped rather than refused. {"type":"integer","default":20} |
cursor | query | No | An opaque value from an earlier page's next_cursor. A cursor that cannot be read is refused with 400. {"type":"string","maxLength":128} |
| Status | Meaning | Body |
|---|---|---|
| 200 | One page of the account's image history. | application/json: ImageHistoryPage |
| 400 | The limit parameter was not a whole number, the cursor could not be read, or the query held an unknown parameter. | application/json: ErrorEnvelope |
| 401 | The request did not carry a valid, active API key. | application/json: ErrorEnvelope |
| 405 | The method is not allowed on this route. | application/json: ErrorEnvelope |
| 431 | The request has more than 64 headers or more than 32 KiB of header names and values. | application/json: ErrorEnvelope |
| 500 | An internal error occurred. | application/json: ErrorEnvelope |
getImage
GET /v1/image/{id}
Get a static image's status
Authentication: bearer API key. See authentication.
| Parameter | Location | Required | Rule |
|---|---|---|---|
id | path | Yes | {"type":"string","pattern":"^image_[0-9a-f]{32}$"} |
| Status | Meaning | Body |
|---|---|---|
| 200 | The image job's current status. | application/json: ImageJob |
| 401 | The one error envelope every backend response uses. | application/json: ErrorEnvelope |
| 403 | The authenticated account is suspended. The code is account_suspended. | application/json: ErrorEnvelope |
| 404 | The one error envelope every backend response uses. | application/json: ErrorEnvelope |
| 405 | The method is not allowed on this route. | application/json: ErrorEnvelope |
| 431 | The request has more than 64 headers or more than 32 KiB of header names and values. | application/json: ErrorEnvelope |
| 500 | The one error envelope every backend response uses. | application/json: ErrorEnvelope |
deleteImage
DELETE /v1/image/{id}
Delete an image file or an unsuccessful render
Remove a successful job's file, or remove a failed or cancelled job from history. Repeated requests are safe. The job stays readable by ID, and billing, abuse limits, and idempotency keys stay unchanged. Queued and running jobs return 409.
Authentication: bearer API key. See authentication.
| Parameter | Location | Required | Rule |
|---|---|---|---|
id | path | Yes | {"type":"string","pattern":"^image_[0-9a-f]{32}$"} |
| Status | Meaning | Body |
|---|---|---|
| 200 | The image job after file or history removal. | application/json: ImageJob |
| 401 | The one error envelope every backend response uses. | application/json: ErrorEnvelope |
| 403 | The authenticated account is suspended. The code is account_suspended. | application/json: ErrorEnvelope |
| 404 | The one error envelope every backend response uses. | application/json: ErrorEnvelope |
| 405 | The method is not allowed on this route. | application/json: ErrorEnvelope |
| 409 | The one error envelope every backend response uses. | application/json: ErrorEnvelope |
| 431 | The request has more than 64 headers or more than 32 KiB of header names and values. | application/json: ErrorEnvelope |
| 500 | The one error envelope every backend response uses. | application/json: ErrorEnvelope |
Schemas
ImageRequestCommon
| Field | Required | Description and type |
|---|---|---|
filename | No | Download name. Surrounding spaces are refused. The server uses the real output extension. Omit it for a safe template-name and UTC creation-date name, or html-render and date for HTML. {"type":"string","minLength":1,"maxLength":120,"pattern":"^(?!.* $)(?!.*\\.\\.)[A-Za-z0-9][A-Za-z0-9 ._-]*$"} |
reference | No | Your reference, preserved in the job, history, and webhook. Omitted when not supplied. {"type":"string","minLength":1,"maxLength":200,"pattern":"^[^\\u0000-\\u001f\\u007f-\\u009f]+$"} |
brand_kit_id | No | Select an owned active brand kit. This uses template evaluation and its 1 MiB source and data limits even when data is omitted. Overrides the source thirds-brand-kit meta default. Supplies reserved brand.name, brand.palette, brand.colours.primary/secondary/accent, brand.logo, brand.logos, and brand.fonts entries with family and src. data.brand is refused when a kit is selected. Only present palette roles and logos are supplied. Assets are captured before enqueue. Schemas validate customer data before brand is added. {"type":["string","null"],"pattern":"^kit_[a-f0-9]{32}$"} |
image | Yes | {"type":"object","properties":{"format":{"type":"string","enum":["png","jpeg","webp"]},"width":{"type":"integer","minimum":320,"maximum":7680,"default":1280},"height":{"type":"integer","minimum":200,"maximum":4320,"default":720},"quality":{"type":"integer","minimum":1,"maximum":100},"transparent":{"type":"boolean","default":false}},"required":["format"],"allOf":[{"if":{"properties":{"format":{"const":"png"}}},"then":{"not":{"required":["quality"]}},"else":{"properties":{"quality":{"default":80}}}},{"if":{"properties":{"format":{"const":"jpeg"}}},"then":{"properties":{"transparent":{"const":false}}}}],"additionalProperties":false} |
javascript | No | {"type":"object","properties":{"mode":{"type":"string","enum":["disabled","enabled"]}},"additionalProperties":false} |
wait | No | {"type":"boolean","default":true} |
Schema rules: {"type":"object"}.
RawImageRequest
Schema rules: {"allOf":[{"$ref":"#/components/schemas/ImageRequestCommon"},{"type":"object","properties":{"html":{"type":"string","minLength":1,"maxLength":5242880}},"required":["html"]}],"unevaluatedProperties":false} — ImageRequestCommon.
StatelessTemplateImageRequest
Schema rules: {"allOf":[{"$ref":"#/components/schemas/ImageRequestCommon"},{"type":"object","properties":{"html":{"type":"string","minLength":1,"maxLength":1048576},"data":{"type":"object"}},"required":["html","data"]}],"unevaluatedProperties":false} — ImageRequestCommon.
SavedTemplateImageRequest
Schema rules: {"allOf":[{"$ref":"#/components/schemas/ImageRequestCommon"},{"type":"object","properties":{"template_id":{"$ref":"#/components/schemas/TemplateId"},"version":{"type":"integer","minimum":1},"data":{"type":"object"},"size_id":{"type":["string","null"],"pattern":"^[a-z0-9][a-z0-9-]{0,39}$","description":"Selects one saved size of the template instead of the original. The image width and height must match the size exactly."}},"required":["template_id","data"]}],"unevaluatedProperties":false} — ImageRequestCommon, TemplateId.
ImageRequest
Schema rules: {"oneOf":[{"$ref":"#/components/schemas/RawImageRequest"},{"$ref":"#/components/schemas/StatelessTemplateImageRequest"},{"$ref":"#/components/schemas/SavedTemplateImageRequest"}]} — RawImageRequest, StatelessTemplateImageRequest, SavedTemplateImageRequest.
ImageJob
| Field | Required | Description and type |
|---|---|---|
reference | No | Your reference, preserved in the job, history, and webhook. Omitted when not supplied. {"type":"string","minLength":1,"maxLength":200,"pattern":"^[^\\u0000-\\u001f\\u007f-\\u009f]+$"} |
id | Yes | {"type":"string","pattern":"^image_[0-9a-f]{32}$"} |
status | Yes | {"type":"string","enum":["queued","running","succeeded","failed","cancelled"]} |
created_at | Yes | {"type":"string","format":"date-time"} |
finished_at | Yes | {"type":["string","null"],"format":"date-time"} |
template | Yes | The exact saved template version this job rendered. Null for raw HTML or an inline stateless template. {"type":["object","null"],"properties":{"id":{"$ref":"#/components/schemas/TemplateId"},"version":{"type":"integer","minimum":1}},"required":["id","version"],"additionalProperties":false} — TemplateId |
credit | Yes | What happened to the credit this job holds: "reserved" while it is queued or running, "settled" once it succeeded, "released" once it failed or was cancelled, and "none" when the job was never billed. {"type":"string","enum":["reserved","settled","released","none"]} |
artifact | Yes | {"type":["object","null"],"properties":{"media_type":{"type":"string","enum":["image/png","image/jpeg","image/webp"]},"byte_size":{"type":"integer","minimum":0},"sha256":{"type":"string","pattern":"^[0-9a-f]{64}$"},"expires_at":{"type":"string","format":"date-time","description":"When retention ends and the file stops being served."},"removed_reason":{"type":["string","null"],"enum":["expired","deleted",null]}},"required":["media_type","byte_size","sha256","expires_at","removed_reason"],"additionalProperties":false} |
error | Yes | {"type":["object","null"],"properties":{"category":{"type":"string","enum":["invalid_input","unsafe_asset","resource_limit","timeout","renderer_failure","internal_failure"]},"code":{"type":"string"}},"required":["category","code"],"additionalProperties":false} |
download | Yes | {"type":["object","null"],"properties":{"url":{"type":"string"},"expires_at":{"type":"string","format":"date-time"}},"required":["url","expires_at"],"additionalProperties":false} |
Schema rules: {"type":"object","additionalProperties":false}.
ImageHistoryItem
One job in a bounded account history — the subset of ImageJob a history page lists. Never carries a download link, since a history page can name many jobs at once.
| Field | Required | Description and type |
|---|---|---|
reference | No | Your reference, preserved in the job, history, and webhook. Omitted when not supplied. {"type":"string","minLength":1,"maxLength":200,"pattern":"^[^\\u0000-\\u001f\\u007f-\\u009f]+$"} |
id | Yes | {"type":"string","pattern":"^image_[0-9a-f]{32}$"} |
status | Yes | {"type":"string","enum":["queued","running","succeeded","failed","cancelled"]} |
created_at | Yes | {"type":"string","format":"date-time"} |
finished_at | Yes | {"type":["string","null"],"format":"date-time"} |
template | Yes | The exact saved template version this job rendered. Null for raw HTML or an inline stateless template. {"type":["object","null"],"properties":{"id":{"$ref":"#/components/schemas/TemplateId"},"version":{"type":"integer","minimum":1}},"required":["id","version"],"additionalProperties":false} — TemplateId |
credit | Yes | What happened to the credit this job holds: "reserved" while it is queued or running, "settled" once it succeeded, "released" once it failed or was cancelled, and "none" when the job was never billed. {"type":"string","enum":["reserved","settled","released","none"]} |
artifact | Yes | {"type":["object","null"],"properties":{"media_type":{"type":"string","enum":["image/png","image/jpeg","image/webp"]},"byte_size":{"type":"integer","minimum":0},"sha256":{"type":"string","pattern":"^[0-9a-f]{64}$"},"expires_at":{"type":"string","format":"date-time","description":"When retention ends and the file stops being served."},"removed_reason":{"type":["string","null"],"enum":["expired","deleted",null]}},"required":["media_type","byte_size","sha256","expires_at","removed_reason"],"additionalProperties":false} |
error | Yes | {"type":["object","null"],"properties":{"category":{"type":"string","enum":["invalid_input","unsafe_asset","resource_limit","timeout","renderer_failure","internal_failure"]},"code":{"type":"string"}},"required":["category","code"],"additionalProperties":false} |
Schema rules: {"type":"object","additionalProperties":false}.
ImageHistoryPage
One bounded page of an account's image history, newest first.
| Field | Required | Description and type |
|---|---|---|
items | Yes | {"type":"array","maxItems":100,"items":{"$ref":"#/components/schemas/ImageHistoryItem"}} — ImageHistoryItem |
next_cursor | Yes | Pass as the cursor query parameter to read the next page. Null on the last page. {"type":["string","null"],"maxLength":128} |
Schema rules: {"type":"object","additionalProperties":false}.
Shared errors, headers, and authentication schemes are in shared types and security.