Saved templates
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.
| Status | Meaning | Body |
|---|---|---|
| 201 | The created template, including version 1 source and schema. | application/json: TemplateDetail |
| 400 | The one error envelope every backend response uses. | application/json: ErrorEnvelope |
| 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 |
| 405 | The method is not allowed on this route. | application/json: ErrorEnvelope |
| 413 | 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 |
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.
| Parameter | Location | Required | Rule |
|---|---|---|---|
status | query | No | {"type":"string","enum":["active","archived","all"],"default":"all"} |
q | query | No | Search names on the server. {"type":"string","maxLength":120,"pattern":"^[^\\u0000-\\u001f\\u007f-\\u009f]*$"} |
tag | query | No | Match one exact tag on the server. {"type":"string","minLength":1,"maxLength":40,"pattern":"^[^\\u0000-\\u001f\\u007f-\\u009f]+$"} |
limit | query | No | {"type":"integer","default":20} |
cursor | query | No | {"type":"string","maxLength":128} |
| Status | Meaning | Body |
|---|---|---|
| 200 | One page of saved-template summaries. | application/json: TemplatePage |
| 400 | The one error envelope every backend response uses. | application/json: ErrorEnvelope |
| 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 |
| 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 |
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.
| Status | Meaning | Body |
|---|---|---|
| 200 | The expanded HTML. This response uses Cache-Control: private, no-store. | application/json: TemplatePreview |
| 400 | The one error envelope every backend response uses. | application/json: ErrorEnvelope |
| 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 |
| 405 | The method is not allowed on this route. | 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 |
| 503 | The 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.
| Status | Meaning | Body |
|---|---|---|
| 200 | One entry per requested size, each with its adapted source or a safe error code. | application/json: TemplateAdaptResponse |
| 400 | The one error envelope every backend response uses. | application/json: ErrorEnvelope |
| 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 |
| 405 | The method is not allowed on this route. | 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 |
| 504 | The 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.
| Parameter | Location | Required | Rule |
|---|---|---|---|
template_id | path | Yes | TemplateId |
| Status | Meaning | Body |
|---|---|---|
| 200 | The template and its latest immutable version. | application/json: TemplateDetail |
| 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 |
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.
| Parameter | Location | Required | Rule |
|---|---|---|---|
template_id | path | Yes | TemplateId |
Request body: application/json, TemplateRename.
| Status | Meaning | Body |
|---|---|---|
| 200 | The template with its new name. | application/json: TemplateSummary |
| 400 | The one error envelope every backend response uses. | application/json: ErrorEnvelope |
| 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 |
| 413 | 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 |
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.
| Parameter | Location | Required | Rule |
|---|---|---|---|
template_id | path | Yes | TemplateId |
| Status | Meaning | Body |
|---|---|---|
| 200 | The template is archived. | application/json: TemplateSummary |
| 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 |
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.
| Parameter | Location | Required | Rule |
|---|---|---|---|
template_id | path | Yes | TemplateId |
Request body: application/json, TemplateVersionWriteRequest.
| Status | Meaning | Body |
|---|---|---|
| 201 | The new immutable version, including source and schema. | application/json: TemplateVersionDetail |
| 400 | The one error envelope every backend response uses. | application/json: ErrorEnvelope |
| 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 |
| 413 | 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 |
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.
| Parameter | Location | Required | Rule |
|---|---|---|---|
template_id | path | Yes | TemplateId |
limit | query | No | {"type":"integer","default":20} |
cursor | query | No | {"type":"string","maxLength":32} |
| Status | Meaning | Body |
|---|---|---|
| 200 | One page of immutable version summaries. | application/json: TemplateVersionPage |
| 400 | The one error envelope every backend response uses. | application/json: ErrorEnvelope |
| 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 |
getTemplateVersion
GET /v1/templates/{template_id}/versions/{version}
Get a template version
Authentication: bearer API key. See authentication.
| Parameter | Location | Required | Rule |
|---|---|---|---|
template_id | path | Yes | TemplateId |
version | path | Yes | {"type":"integer","minimum":1} |
| Status | Meaning | Body |
|---|---|---|
| 200 | The exact immutable template version. | application/json: TemplateVersionDetail |
| 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 |
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
| Field | Required | Description and type |
|---|---|---|
tags | No | TemplateTags |
name | No | TemplateName |
input_mode | No | How 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"} |
source | Yes | {"type":"string","maxLength":1048576} |
schema | No | {"oneOf":[{"type":"object"},{"type":"boolean"},{"type":"null"}]} |
sizes | No | SizeVariantList |
Schema rules: {"type":"object","additionalProperties":false}.
TemplateVersionWriteRequest
| Field | Required | Description and type |
|---|---|---|
source | Yes | {"type":"string","maxLength":1048576} |
schema | No | {"oneOf":[{"type":"object"},{"type":"boolean"},{"type":"null"}]} |
sizes | No | SizeVariantList |
Schema rules: {"type":"object","additionalProperties":false}.
TemplatePreviewRequest
| Field | Required | Description and type |
|---|---|---|
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}$"} |
source | Yes | {"type":"string","maxLength":1048576} |
data | Yes | Template values, bounded to 1,048,576 encoded JSON bytes with the template depth and collection limits. {"type":"object"} |
schema | No | {"oneOf":[{"type":"object"},{"type":"boolean"},{"type":"null"}]} |
Schema rules: {"type":"object","additionalProperties":false}.
TemplatePreview
| Field | Required | Description and type |
|---|---|---|
html | Yes | {"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.
| Field | Required | Description and type |
|---|---|---|
archived_at | No | Restore the item. Omit this field to keep its archive state. {"type":"null"} |
tags | No | TemplateTags |
name | No | TemplateName |
Schema rules: {"type":"object","additionalProperties":false}.
TemplateSummary
| Field | Required | Description and type |
|---|---|---|
tags | Yes | TemplateTags |
id | Yes | TemplateId |
name | Yes | TemplateName |
created_at | Yes | {"type":"string","format":"date-time"} |
archived_at | Yes | {"type":["string","null"],"format":"date-time"} |
latest_version | Yes | {"type":"integer","minimum":1} |
Schema rules: {"type":"object","additionalProperties":false}.
TemplateDetail
| Field | Required | Description and type |
|---|---|---|
archive_history | Yes | {"type":"array","items":{"$ref":"#/components/schemas/ArchivePeriod"}} — ArchivePeriod |
tags | Yes | TemplateTags |
id | Yes | TemplateId |
name | Yes | TemplateName |
created_at | Yes | {"type":"string","format":"date-time"} |
archived_at | Yes | {"type":["string","null"],"format":"date-time"} |
latest_version | Yes | {"type":"integer","minimum":1} |
source | Yes | {"type":"string","maxLength":1048576} |
schema | Yes | {} |
sizes | Yes | SizeVariantList |
Schema rules: {"type":"object","additionalProperties":false}.
TemplatePage
| Field | Required | Description and type |
|---|---|---|
tag_options | Yes | The 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}} |
items | Yes | {"type":"array","maxItems":100,"items":{"$ref":"#/components/schemas/TemplateSummary"}} — TemplateSummary |
next_cursor | Yes | {"type":["string","null"],"maxLength":128} |
Schema rules: {"type":"object","additionalProperties":false}.
TemplateVersionSummary
| Field | Required | Description and type |
|---|---|---|
version | Yes | {"type":"integer","minimum":1} |
created_at | Yes | {"type":"string","format":"date-time"} |
Schema rules: {"type":"object","additionalProperties":false}.
TemplateVersionDetail
| Field | Required | Description and type |
|---|---|---|
version | Yes | {"type":"integer","minimum":1} |
created_at | Yes | {"type":"string","format":"date-time"} |
source | Yes | {"type":"string","maxLength":1048576} |
schema | Yes | {} |
sizes | Yes | SizeVariantList |
Schema rules: {"type":"object","additionalProperties":false}.
TemplateVersionPage
| Field | Required | Description and type |
|---|---|---|
items | Yes | {"type":"array","maxItems":100,"items":{"$ref":"#/components/schemas/TemplateVersionSummary"}} — TemplateVersionSummary |
next_cursor | Yes | {"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.
| Field | Required | Description and type |
|---|---|---|
id | Yes | Unique 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}$"} |
name | Yes | {"type":"string","minLength":1,"maxLength":120} |
width | Yes | {"type":"integer","minimum":320,"maximum":7680} |
height | Yes | {"type":"integer","minimum":200,"maximum":4320} |
status | Yes | {"type":"string","enum":["auto","edited"]} |
source | Yes | The source canvas must declare exactly width by height. {"type":"string","maxLength":1048576} |
data_overrides | No | Merged 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.
| Field | Required | Description and type |
|---|---|---|
source | Yes | {"type":"string","maxLength":1048576} |
sizes | Yes | {"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
| Field | Required | Description and type |
|---|---|---|
sizes | Yes | {"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.