Templates API
https://api.airogelcms.com/v1/accounts/:account_id/templates
Templates are Liquid files that render your site's HTML. The same resource is used for page templates, layouts and partials. A template's role comes from how it is referenced: a collection's or entry's layout_handle makes it a layout, template_handle makes it a page template, and an include from another template makes it a partial. There is no type field. See Liquid Templates.
Operations
- GET
/v1/accounts/:account_id/templates- List templates - GET
/v1/accounts/:account_id/templates/:id- Get one template - POST
/v1/accounts/:account_id/templates- Create a template - PUT / PATCH
/v1/accounts/:account_id/templates/:id- Update a template - DELETE
/v1/accounts/:account_id/templates/:id- Delete a template (returns204)
:id is the template's tmplt_ ID or handle. Lists are sorted by title and leave out html. Fetch a single template to get its source.
Writable fields
The body must be wrapped in template, for example {"template": {"handle": "post", ...}}. A flat body returns 400.
| Field | Type | Required | Description |
|---|---|---|---|
template.handle | string | yes | Identifier referenced by template_handle/layout_handle. POST with an existing handle updates that template. |
template.title | string | yes | Display name |
template.html | string | yes | Liquid source. It is validated before saving. |
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
account_id
|
string | Required |
Path. Your account prefix ID (acct_...).
|
id
|
string | Optional |
Path, for show/update/delete. Template tmplt_ ID or handle.
|
handle
|
string | Optional | Query, list only. Return only the record with exactly this handle. |
page
|
integer | Optional | Query, list only. Page number, starting at 1. The page size is fixed at 20. |
template
|
object | Required | Body. Required wrapper around the fields below. |
template.handle
|
string | Required | Body. Identifier. POST with an existing handle updates it. |
template.title
|
string | Required | Body. Display name. |
template.html
|
string | Required | Body. Liquid source. Invalid Liquid returns 422. |
Request Example
# List templates (no html in list items)
curl "https://api.airogelcms.com/v1/accounts/$ACCOUNT_ID/templates" \
-H "Authorization: Bearer $API_TOKEN"
# Create a template
curl -X POST "https://api.airogelcms.com/v1/accounts/$ACCOUNT_ID/templates" \
-H "Authorization: Bearer $API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"template": {
"title": "Blog Post",
"handle": "post",
"html": "\n {{ posts.title }}
\n {{ posts.body }}\n "
}
}'
# Update the source (still wrapped in "template")
curl -X PATCH "https://api.airogelcms.com/v1/accounts/$ACCOUNT_ID/templates/post" \
-H "Authorization: Bearer $API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"template": {
"html": "\n {{ posts.title }}
\n {{ posts.published_at | date: \"%B %d, %Y\" }}
\n {{ posts.body }}\n "
}
}'
# Delete
curl -X DELETE "https://api.airogelcms.com/v1/accounts/$ACCOUNT_ID/templates/post" \
-H "Authorization: Bearer $API_TOKEN"
Response Example
// Single template (show, create, update) is wrapped in "template"
{
"template": {
"id": "tmplt_4gHj8Kl",
"handle": "post",
"title": "Blog Post",
"html": "\n {{ posts.title }}
\n {{ posts.body }}\n ",
"created_at": "2026-09-05T11:00:00Z",
"updated_at": "2026-09-05T11:00:00Z"
}
}
// List - no html
{
"data": [
{ "id": "tmplt_4gHj8Kl", "handle": "post", "title": "Blog Post", "created_at": "2026-09-05T11:00:00Z", "updated_at": "2026-09-05T11:00:00Z" }
],
"pagination": {
"page": 1,
"per_page": 20,
"total": 1,
"total_pages": 1,
"next_page": null,
"prev_page": null
}
}
// 422 - invalid Liquid (flat "errors" list)
{
"errors": ["Liquid syntax error: 'if' tag was never closed"]
}
Additional Notes
Syntax validation. Liquid is parsed before saving. A syntax error returns 422 with {"errors": ["..."]}, a flat list of messages rather than the details shape other resources use, and nothing is saved. Messages look like Liquid syntax error: ... (prefixed with html on create). Validation checks syntax only. Use the MCP theme validation and preview tools, or Liquiditor, to check how a template actually renders.
Assigning templates. Set template_handle, layout_handle and index_template_handle on a collection, or template_handle and layout_handle on an entry to override it. Upload templates before anything that references them, because an unknown handle returns 422.
Variables. On an entry page, the entry is available under its collection handle, for example {{ posts.title }} and {{ posts.body }} for a posts collection.
Useful tags. Include {% cms_scripts %} in layouts so CMS features work on the page, and use {% form_for %} to render forms (see form_for). The variables available depend on the page type. See the Liquid Templates guide.