Collections API
https://api.airogelcms.com/v1/accounts/:account_id/collections
A collection groups entries of one kind, such as posts, pages or products. It sets the URL pattern its entries are served at, the blueprint (field schema) they use, the default template and layout, and an optional paginated index page. See Collections and Routing for the concepts.
Operations
- GET
/v1/accounts/:account_id/collections- List collections - GET
/v1/accounts/:account_id/collections/:id- Get one collection - POST
/v1/accounts/:account_id/collections- Create a collection - PUT / PATCH
/v1/accounts/:account_id/collections/:id- Update a collection - DELETE
/v1/accounts/:account_id/collections/:id- Delete a collection (returns204)
:id can be the collection's clctn_ prefix ID or its handle. Lists are sorted by name.
Routing placeholders
The routing string is a path pattern. It can use these tokens:
| Placeholder | Replaced with | Example |
|---|---|---|
:handle | The entry's handle | my-post |
:year | 4-digit year of published_at (or created_at if unset) | 2026 |
:month | 2-digit month of the same date | 09 |
:day | 2-digit day of the same date | 25 |
:<field_handle> | The handle of the entry referenced by that entity field. This gives parent/child URLs such as docs/:section/:handle. | getting-started |
For example, blog/:handle serves /blog/my-post, :year/:month/:handle serves /2026/09/my-post, and :handle serves /about. The referenced entity field must be set on the entry. Otherwise its path cannot be generated.
Writable fields
| Field | Type | Required | Description |
|---|---|---|---|
name | string | yes | Display name |
handle | string | yes | Unique identifier within the account. POST with an existing handle updates that collection. |
routing | string | yes | URL pattern for entries, for example blog/:handle |
root_routing | boolean | no | Default false. Set to true on the one collection whose entry with handle index should serve the home page / (with routing: ":handle"). |
orderable | string | no | no (default), ascending or descending. Entries always sort by position ascending first. This setting controls the tiebreak on publish date. With no, the tiebreak is newest first by creation date. |
schema_type | string | no | schema.org type for structured data, for example BlogPosting. Rendering falls back to WebPage when unset. |
template_handle | string | no | Default template for entries |
layout_handle | string | no | Default layout for entries |
index_routing | string | no | Path of the index (listing) page, for example blog |
index_template_handle | string | no | Template for the index page |
index_per_page | integer | no | Entries per index page. Default 10. |
blueprint_handle | string | no | Create only. Attach an existing blueprint. |
blueprint | object | no | Create only. Create a blueprint inline: {"title", "handle", "fields": [...]}. Uses the same field format as Blueprints. The title and handle default to the collection's. |
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
account_id
|
string | Required |
Path. Your account prefix ID (acct_...).
|
id
|
string | Optional |
Path, for show/update/delete. Collection clctn_ 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. |
name
|
string | Required | Body. Display name. |
handle
|
string | Required | Body. Unique identifier. POST with an existing handle updates it. |
routing
|
string | Required |
Body. Entry URL pattern using :handle, :year, :month, :day or an entity field handle.
|
root_routing
|
boolean | Optional |
Body. Default false. true lets this collection's index entry serve /.
|
orderable
|
string | Optional |
Body. no (default), ascending or descending.
|
schema_type
|
string | Optional |
Body. schema.org type, for example BlogPosting.
|
template_handle
|
string | Optional | Body. Default entry template. Unknown handle returns 422. |
layout_handle
|
string | Optional | Body. Default entry layout. Unknown handle returns 422. |
index_routing
|
string | Optional |
Body. Index page path, for example blog.
|
index_template_handle
|
string | Optional | Body. Index page template. Unknown handle returns 422. |
index_per_page
|
integer | Optional | Body. Entries per index page. Default 10. |
blueprint_handle
|
string | Optional |
Body, create only. Attach an existing blueprint. Takes precedence over blueprint.
|
blueprint
|
object | Optional |
Body, create only. Inline blueprint {title, handle, fields}.
|
Request Example
# List collections
curl "https://api.airogelcms.com/v1/accounts/$ACCOUNT_ID/collections" \
-H "Authorization: Bearer $API_TOKEN"
# Get one collection by handle
curl "https://api.airogelcms.com/v1/accounts/$ACCOUNT_ID/collections/posts" \
-H "Authorization: Bearer $API_TOKEN"
# Create a collection that uses an existing blueprint and has an index page
curl -X POST "https://api.airogelcms.com/v1/accounts/$ACCOUNT_ID/collections" \
-H "Authorization: Bearer $API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Blog Posts",
"handle": "posts",
"routing": "blog/:handle",
"orderable": "descending",
"schema_type": "BlogPosting",
"blueprint_handle": "blog_post",
"template_handle": "post",
"layout_handle": "default",
"index_routing": "blog",
"index_template_handle": "blog-index",
"index_per_page": 10
}'
# Create a collection with an inline blueprint
curl -X POST "https://api.airogelcms.com/v1/accounts/$ACCOUNT_ID/collections" \
-H "Authorization: Bearer $API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Products",
"handle": "products",
"routing": "shop/:handle",
"blueprint": {
"title": "Product",
"fields": [
{"handle": "price", "display": "Price", "type": "number", "options": {"number_type": "decimal", "decimal_places": 2}},
{"handle": "photo", "display": "Photo", "type": "image"}
]
}
}'
# Update (PUT or PATCH; only the fields you send change)
curl -X PATCH "https://api.airogelcms.com/v1/accounts/$ACCOUNT_ID/collections/posts" \
-H "Authorization: Bearer $API_TOKEN" \
-H "Content-Type: application/json" \
-d '{"index_per_page": 20}'
# Delete (also deletes every entry in the collection)
curl -X DELETE "https://api.airogelcms.com/v1/accounts/$ACCOUNT_ID/collections/posts" \
-H "Authorization: Bearer $API_TOKEN"
Response Example
// GET /collections/posts (single collection; create and update return the same shape)
{
"id": "clctn_3kLm9pQr",
"handle": "posts",
"name": "Blog Posts",
"routing": "blog/:handle",
"root_routing": false,
"orderable": "descending",
"schema_type": "BlogPosting",
"template_handle": "post",
"layout_handle": "default",
"index_template_handle": "blog-index",
"index_routing": "blog",
"index_per_page": 10,
"feed_enabled": false,
"feed_path": null,
"feed_title": null,
"feed_description": null,
"feed_limit": 20,
"blueprint_handles": ["blog_post"],
"entries_count": 42,
"created_at": "2026-09-01T14:05:00Z",
"updated_at": "2026-09-20T08:30:00Z",
"blueprints": [
{
"id": "blprt_8xNw2Ls",
"handle": "blog_post",
"title": "Blog Post",
"fields": [
{ "handle": "body", "display": "Body", "type": "rich_text", "position": 0, "options": {} },
{ "handle": "excerpt", "display": "Excerpt", "type": "text", "position": 1, "options": {} },
{ "handle": "featured_image", "display": "Featured Image", "type": "image", "position": 2, "options": {} }
],
"created_at": "2026-09-01T14:00:00Z",
"updated_at": "2026-09-01T14:00:00Z"
}
]
}
// GET /collections (list)
{
"data": [
{ "id": "clctn_3kLm9pQr", "handle": "posts", "name": "Blog Posts", "...": "same fields as above" }
],
"pagination": {
"page": 1,
"per_page": 20,
"total": 1,
"total_pages": 1,
"next_page": null,
"prev_page": null
}
}
// 422 - unknown template
{
"error": "Validation failed",
"details": [
{ "path": "template_handle", "message": "Template 'post' not found" }
]
}
Additional Notes
Attaching a blueprint. Use blueprint_handle to attach an existing blueprint (recommended for imports), or blueprint to create one inline. If you send both, blueprint_handle wins. A blueprint_handle that does not exist is silently skipped, so create blueprints first. A blueprint that already belongs to another collection, global or navigation returns 422 (path: "blueprint_handles"). Both fields are read only on POST. PUT/PATCH ignores them.
Template references. template_handle, layout_handle and index_template_handle must name existing templates, or the request fails with 422.
Index pages. An index page is served only when both index_routing and index_template_handle are set. index_per_page controls its pagination.
Home page. To serve /, a collection needs routing: ":handle", root_routing: true and an entry with handle index.
Read-only values. feed_*, blueprint_handles and entries_count appear in responses but cannot be set through REST. Configure feeds in the dashboard or through MCP. See Feeds. schema_type is null in responses when unset.
Handles. REST accepts hyphenated handles. The MCP tools require snake_case, so prefer snake_case if you use both.
Deleting a collection deletes all of its entries.