API reference

Saved templates

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/templates and help me choose the right thirds.ai endpoint and write a request. Check the fields and credentials in this reference.

Create and manage editable templates, preview changes, and publish fixed versions for repeat renders.

See all API resources or read API keys and requests.

Endpoints

createTemplate

POST /v1/templates

Create a saved template

Authentication: bearer API key. See authentication.

Request body: application/json, TemplateWriteRequest.

StatusMeaningBody
201The created template, including version 1 source and schema.application/json: TemplateDetail
400The one error envelope every backend response uses.application/json: ErrorEnvelope
401The 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
413The 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

listTemplates

GET /v1/templates

List saved templates

List the account's active and archived templates newest first. Source and schema are omitted. Pass next_cursor to continue with a stable keyset page.

Authentication: bearer API key. See authentication.

ParameterLocationRequiredRule
statusqueryNo{"type":"string","enum":["active","archived","all"],"default":"all"}
qqueryNoSearch names on the server. {"type":"string","maxLength":120,"pattern":"^[^\\u0000-\\u001f\\u007f-\\u009f]*$"}
tagqueryNoMatch one exact tag on the server. {"type":"string","minLength":1,"maxLength":40,"pattern":"^[^\\u0000-\\u001f\\u007f-\\u009f]+$"}
limitqueryNo{"type":"integer","default":20}
cursorqueryNo{"type":"string","maxLength":128}
StatusMeaningBody
200One page of saved-template summaries.application/json: TemplatePage
400The one error envelope every backend response uses.application/json: ErrorEnvelope
401The 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
431The request has more than 64 headers or more than 32 KiB of header names and values.application/json: ErrorEnvelope

previewTemplate

POST /v1/templates/preview

Preview template data as HTML

Expand source and a JSON data object through the bounded template engine. Optional schema validation uses the saved-template rules. This does not save a template, create a render, or spend credits. The response is untrusted customer HTML for an isolated preview. Browser sessions need the current CSRF token.

Authentication: bearer API key. See authentication.

Request body: application/json, TemplatePreviewRequest.

StatusMeaningBody
200The expanded HTML. This response uses Cache-Control: private, no-store.application/json: TemplatePreview
400The one error envelope every backend response uses.application/json: ErrorEnvelope
401The 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
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
503The one error envelope every backend response uses.application/json: ErrorEnvelope

adaptTemplate

POST /v1/templates/adapt

Adapt one HTML source to many canvas sizes

Deterministically adapt one canonical HTML source to up to 20 target canvas sizes. This is free, needs a session or key, and uses the preview rate limit. It does not save a template, create a render, or spend credits. The response gives the adapted source per size, or a safe error code for that size.

Authentication: bearer API key. See authentication.

Request body: application/json, TemplateAdaptRequest.

StatusMeaningBody
200One entry per requested size, each with its adapted source or a safe error code.application/json: TemplateAdaptResponse
400The one error envelope every backend response uses.application/json: ErrorEnvelope
401The 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
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
504The one error envelope every backend response uses.application/json: ErrorEnvelope

getTemplate

GET /v1/templates/{template_id}

Get a saved template

Authentication: bearer API key. See authentication.

ParameterLocationRequiredRule
template_idpathYesTemplateId
StatusMeaningBody
200The template and its latest immutable version.application/json: TemplateDetail
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

renameTemplate

PATCH /v1/templates/{template_id}

Rename a saved template

Set or clear the name of one owned template. The name is trimmed and can have 1 to 120 characters. A null or blank name clears it.

Authentication: bearer API key. See authentication.

ParameterLocationRequiredRule
template_idpathYesTemplateId

Request body: application/json, TemplateRename.

StatusMeaningBody
200The template with its new name.application/json: TemplateSummary
400The one error envelope every backend response uses.application/json: ErrorEnvelope
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
413The 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

archiveTemplate

DELETE /v1/templates/{template_id}

Archive a saved template

Archive one owned template. The operation is idempotent. Archived templates and versions remain readable, but they cannot receive another version or create another render.

Authentication: bearer API key. See authentication.

ParameterLocationRequiredRule
template_idpathYesTemplateId
StatusMeaningBody
200The template is archived.application/json: TemplateSummary
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

createTemplateVersion

POST /v1/templates/{template_id}/versions

Create a template version

Edit a template by publishing one complete new immutable source and optional schema. Existing versions never change. Archived templates cannot receive another version.

Authentication: bearer API key. See authentication.

ParameterLocationRequiredRule
template_idpathYesTemplateId

Request body: application/json, TemplateVersionWriteRequest.

StatusMeaningBody
201The new immutable version, including source and schema.application/json: TemplateVersionDetail
400The one error envelope every backend response uses.application/json: ErrorEnvelope
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
413The 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

listTemplateVersions

GET /v1/templates/{template_id}/versions

List template versions

List immutable versions newest first. Source and schema are omitted. Archived template versions remain readable.

Authentication: bearer API key. See authentication.

ParameterLocationRequiredRule
template_idpathYesTemplateId
limitqueryNo{"type":"integer","default":20}
cursorqueryNo{"type":"string","maxLength":32}
StatusMeaningBody
200One page of immutable version summaries.application/json: TemplateVersionPage
400The one error envelope every backend response uses.application/json: ErrorEnvelope
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

getTemplateVersion

GET /v1/templates/{template_id}/versions/{version}

Get a template version

Authentication: bearer API key. See authentication.

ParameterLocationRequiredRule
template_idpathYesTemplateId
versionpathYes{"type":"integer","minimum":1}
StatusMeaningBody
200The exact immutable template version.application/json: TemplateVersionDetail
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

Schemas

TemplateTags

Trimmed tags. Each tag is nonblank. Case is preserved.

Schema rules: {"type":"array","maxItems":20,"uniqueItems":true,"items":{"type":"string","minLength":1,"maxLength":40}}.

TemplateName

The customer's own name for a template. It is trimmed and can have 1 to 120 characters. Null or blank means no name.

Schema rules: {"type":["string","null"],"maxLength":120}.

TemplateWriteRequest

FieldRequiredDescription and type
tagsNoTemplateTags
nameNoTemplateName
input_modeNoHow this new template starts. It records a blank-page start or imported HTML. New versions do not accept this field. {"type":"string","enum":["blank","html"],"default":"html"}
sourceYes{"type":"string","maxLength":1048576}
schemaNo{"oneOf":[{"type":"object"},{"type":"boolean"},{"type":"null"}]}
sizesNoSizeVariantList

Schema rules: {"type":"object","additionalProperties":false}.

TemplateVersionWriteRequest

FieldRequiredDescription and type
sourceYes{"type":"string","maxLength":1048576}
schemaNo{"oneOf":[{"type":"object"},{"type":"boolean"},{"type":"null"}]}
sizesNoSizeVariantList

Schema rules: {"type":"object","additionalProperties":false}.

TemplatePreviewRequest

FieldRequiredDescription and type
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}$"}
sourceYes{"type":"string","maxLength":1048576}
dataYesTemplate values, bounded to 1,048,576 encoded JSON bytes with the template depth and collection limits. {"type":"object"}
schemaNo{"oneOf":[{"type":"object"},{"type":"boolean"},{"type":"null"}]}

Schema rules: {"type":"object","additionalProperties":false}.

TemplatePreview

FieldRequiredDescription and type
htmlYes{"type":"string","maxLength":5242880}

Schema rules: {"type":"object","additionalProperties":false}.

TemplateRename

Omitted fields keep their current values. Set name to null to clear it, tags to an empty array to clear them, or archived_at to null to restore the template.

FieldRequiredDescription and type
archived_atNoRestore the item. Omit this field to keep its archive state. {"type":"null"}
tagsNoTemplateTags
nameNoTemplateName

Schema rules: {"type":"object","additionalProperties":false}.

TemplateSummary

FieldRequiredDescription and type
tagsYesTemplateTags
idYesTemplateId
nameYesTemplateName
created_atYes{"type":"string","format":"date-time"}
archived_atYes{"type":["string","null"],"format":"date-time"}
latest_versionYes{"type":"integer","minimum":1}

Schema rules: {"type":"object","additionalProperties":false}.

TemplateDetail

FieldRequiredDescription and type
archive_historyYes{"type":"array","items":{"$ref":"#/components/schemas/ArchivePeriod"}}ArchivePeriod
tagsYesTemplateTags
idYesTemplateId
nameYesTemplateName
created_atYes{"type":"string","format":"date-time"}
archived_atYes{"type":["string","null"],"format":"date-time"}
latest_versionYes{"type":"integer","minimum":1}
sourceYes{"type":"string","maxLength":1048576}
schemaYes{}
sizesYesSizeVariantList

Schema rules: {"type":"object","additionalProperties":false}.

TemplatePage

FieldRequiredDescription and type
tag_optionsYesThe first 100 distinct account tags, sorted. Use the tag filter for any other tag. {"type":"array","maxItems":100,"uniqueItems":true,"items":{"type":"string","minLength":1,"maxLength":40}}
itemsYes{"type":"array","maxItems":100,"items":{"$ref":"#/components/schemas/TemplateSummary"}}TemplateSummary
next_cursorYes{"type":["string","null"],"maxLength":128}

Schema rules: {"type":"object","additionalProperties":false}.

TemplateVersionSummary

FieldRequiredDescription and type
versionYes{"type":"integer","minimum":1}
created_atYes{"type":"string","format":"date-time"}

Schema rules: {"type":"object","additionalProperties":false}.

TemplateVersionDetail

FieldRequiredDescription and type
versionYes{"type":"integer","minimum":1}
created_atYes{"type":"string","format":"date-time"}
sourceYes{"type":"string","maxLength":1048576}
schemaYes{}
sizesYesSizeVariantList

Schema rules: {"type":"object","additionalProperties":false}.

TemplateVersionPage

FieldRequiredDescription and type
itemsYes{"type":"array","maxItems":100,"items":{"$ref":"#/components/schemas/TemplateVersionSummary"}}TemplateVersionSummary
next_cursorYes{"type":["string","null"],"maxLength":32}

Schema rules: {"type":"object","additionalProperties":false}.

SizeVariant

One saved canvas size for a template version. docs/SMART-RESIZE.md owns the rules.

FieldRequiredDescription and type
idYesUnique within the version. The id original is reserved for the version's own canvas. {"type":"string","pattern":"^[a-z0-9][a-z0-9-]{0,39}$"}
nameYes{"type":"string","minLength":1,"maxLength":120}
widthYes{"type":"integer","minimum":320,"maximum":7680}
heightYes{"type":"integer","minimum":200,"maximum":4320}
statusYes{"type":"string","enum":["auto","edited"]}
sourceYesThe source canvas must declare exactly width by height. {"type":"string","maxLength":1048576}
data_overridesNoMerged over the version's rendered data for this size only. {"type":"object"}

Schema rules: {"type":"object","additionalProperties":false}.

SizeVariantList

Schema rules: {"type":"array","maxItems":20,"items":{"$ref":"#/components/schemas/SizeVariant"}}SizeVariant.

TemplateAdaptRequest

Adapt one HTML source to many target canvas sizes with the deterministic layout algorithm. This is free and does not save anything.

FieldRequiredDescription and type
sourceYes{"type":"string","maxLength":1048576}
sizesYes{"type":"array","maxItems":20,"items":{"type":"object","properties":{"width":{"type":"integer","minimum":320,"maximum":7680},"height":{"type":"integer","minimum":200,"maximum":4320}},"required":["width","height"],"additionalProperties":false}}

Schema rules: {"type":"object","additionalProperties":false}.

TemplateAdaptResponse

FieldRequiredDescription and type
sizesYes{"type":"array","items":{"type":"object","properties":{"width":{"type":"integer"},"height":{"type":"integer"},"source":{"type":"string","maxLength":1048576},"error":{"type":"object","properties":{"code":{"type":"string","enum":["resize_source_unsupported","resize_no_layout"]}},"required":["code"],"additionalProperties":false}},"required":["width","height"],"additionalProperties":false}}

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.