API reference

Image renders

Use with your agent

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.

ParameterLocationRequiredRule
Idempotency-KeyheaderNo{"type":"string","minLength":1,"maxLength":255,"pattern":"^[ -~]+$"}

Request body: application/json, ImageRequest.

StatusMeaningBody
200The job is terminal. Check status for succeeded, failed, or cancelled; HTTP 200 does not mean the render succeeded.application/json: ImageJob
202The image job is durable and remains queued or running.application/json: ImageJob
400The one error envelope every backend response uses.application/json: ErrorEnvelope
401The one error envelope every backend response uses.application/json: ErrorEnvelope
402The one error envelope every backend response uses.application/json: ErrorEnvelope
403The authenticated account is suspended. The code is account_suspended.application/json: ErrorEnvelope
405The method is not allowed on this route.application/json: ErrorEnvelope
409The one error envelope every backend response uses.application/json: ErrorEnvelope
413The one error envelope every backend response uses.application/json: ErrorEnvelope
415The one error envelope every backend response uses.application/json: ErrorEnvelope
429The one error envelope every backend response uses.application/json: ErrorEnvelope
431The request has more than 64 headers or more than 32 KiB of header names and values.application/json: ErrorEnvelope
500The one error envelope every backend response uses.application/json: ErrorEnvelope
503The 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.

ParameterLocationRequiredRule
qqueryNoCase-insensitive search of references, template names, and file types. {"type":"string","maxLength":200,"pattern":"^[^\\u0000-\\u001f\\u007f-\\u009f]*$"}
limitqueryNo1 to 100. Defaults to 20. A value outside this range is clamped rather than refused. {"type":"integer","default":20}
cursorqueryNoAn opaque value from an earlier page's next_cursor. A cursor that cannot be read is refused with 400. {"type":"string","maxLength":128}
StatusMeaningBody
200One page of the account's image history.application/json: ImageHistoryPage
400The limit parameter was not a whole number, the cursor could not be read, or the query held an unknown parameter.application/json: ErrorEnvelope
401The request did not carry a valid, active API key.application/json: ErrorEnvelope
405The method is not allowed on this route.application/json: ErrorEnvelope
431The request has more than 64 headers or more than 32 KiB of header names and values.application/json: ErrorEnvelope
500An internal error occurred.application/json: ErrorEnvelope

getImage

GET /v1/image/{id}

Get a static image's status

Authentication: bearer API key. See authentication.

ParameterLocationRequiredRule
idpathYes{"type":"string","pattern":"^image_[0-9a-f]{32}$"}
StatusMeaningBody
200The image job's current status.application/json: ImageJob
401The one error envelope every backend response uses.application/json: ErrorEnvelope
403The authenticated account is suspended. The code is account_suspended.application/json: ErrorEnvelope
404The one error envelope every backend response uses.application/json: ErrorEnvelope
405The method is not allowed on this route.application/json: ErrorEnvelope
431The request has more than 64 headers or more than 32 KiB of header names and values.application/json: ErrorEnvelope
500The 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.

ParameterLocationRequiredRule
idpathYes{"type":"string","pattern":"^image_[0-9a-f]{32}$"}
StatusMeaningBody
200The image job after file or history removal.application/json: ImageJob
401The one error envelope every backend response uses.application/json: ErrorEnvelope
403The authenticated account is suspended. The code is account_suspended.application/json: ErrorEnvelope
404The one error envelope every backend response uses.application/json: ErrorEnvelope
405The method is not allowed on this route.application/json: ErrorEnvelope
409The one error envelope every backend response uses.application/json: ErrorEnvelope
431The request has more than 64 headers or more than 32 KiB of header names and values.application/json: ErrorEnvelope
500The one error envelope every backend response uses.application/json: ErrorEnvelope

Schemas

ImageRequestCommon

FieldRequiredDescription and type
filenameNoDownload 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 ._-]*$"}
referenceNoYour 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_idNoSelect 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}$"}
imageYes{"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}
javascriptNo{"type":"object","properties":{"mode":{"type":"string","enum":["disabled","enabled"]}},"additionalProperties":false}
waitNo{"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

FieldRequiredDescription and type
referenceNoYour reference, preserved in the job, history, and webhook. Omitted when not supplied. {"type":"string","minLength":1,"maxLength":200,"pattern":"^[^\\u0000-\\u001f\\u007f-\\u009f]+$"}
idYes{"type":"string","pattern":"^image_[0-9a-f]{32}$"}
statusYes{"type":"string","enum":["queued","running","succeeded","failed","cancelled"]}
created_atYes{"type":"string","format":"date-time"}
finished_atYes{"type":["string","null"],"format":"date-time"}
templateYesThe 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
creditYesWhat 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"]}
artifactYes{"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}
errorYes{"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}
downloadYes{"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.

FieldRequiredDescription and type
referenceNoYour reference, preserved in the job, history, and webhook. Omitted when not supplied. {"type":"string","minLength":1,"maxLength":200,"pattern":"^[^\\u0000-\\u001f\\u007f-\\u009f]+$"}
idYes{"type":"string","pattern":"^image_[0-9a-f]{32}$"}
statusYes{"type":"string","enum":["queued","running","succeeded","failed","cancelled"]}
created_atYes{"type":"string","format":"date-time"}
finished_atYes{"type":["string","null"],"format":"date-time"}
templateYesThe 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
creditYesWhat 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"]}
artifactYes{"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}
errorYes{"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.

FieldRequiredDescription and type
itemsYes{"type":"array","maxItems":100,"items":{"$ref":"#/components/schemas/ImageHistoryItem"}}ImageHistoryItem
next_cursorYesPass 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.

Ready to make your first file?

Start in the playground with a gallery template, or get an API key and send your first request from your own terminal.