Collections
Reading requires any API key. Writing requires a secret key with content:write and an Idempotency-Key header — see Write Operations.
GET /api/v1/collections/:type
List published collection items by collection type slug.
Authentication: API key required Rate Limit: Standard rate limits apply
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
type | string | Yes | Collection type slug (kebab-case or snake_case — snake_case is normalised to kebab-case) |
Query Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
page | integer | 1 | Page number (1-indexed) |
limit | integer | 20 | Items per page (1-100) |
sort | string | -publishedAt | Sort field with optional - prefix for descending order (e.g. name, -name, -publishedAt,slug). Allowed fields: createdAt, updatedAt, publishedAt, name, slug, _sortOrder (authored order). |
filter[field][op] | string | — | Filter by core fields or custom fields |
Request Example
GET /api/v1/collections/products?page=1&limit=10&sort=name
X-API-Key: tento_pk_your_key_here
Response (200 OK)
{
"data": [
{
"price": 99.99,
"description": "A great product",
"_sortOrder": 0,
"_publishedAt": "2025-06-01T12:00:00.000Z",
"_updatedAt": "2025-06-01T12:00:00.000Z"
}
],
"collectionType": {
"id": "ct-123",
"name": "Products",
"slug": "products"
},
"pagination": {
"page": 1,
"limit": 10,
"total": 42,
"totalPages": 5
}
}
Singleton Collections
Singleton collections return a single object instead of a paginated list:
{
"data": {
"siteName": "My Website",
"tagline": "Welcome",
"_sortOrder": 0,
"_publishedAt": "2025-06-01T12:00:00.000Z",
"_updatedAt": "2025-06-01T12:00:00.000Z"
},
"collectionType": {
"id": "ct-456",
"name": "Site Settings",
"slug": "site-settings",
"isSingleton": true
}
}
Errors:
401 Unauthorized(UNAUTHORIZED) - Missing or invalid API key404 Not Found(NOT_FOUND) - Collection type slug doesn't exist for this tenant404 Not Found(NOT_FOUND) - Singleton collection type exists but has no content item yet (message:Singleton content for "<type>" not found)404 Not Found(NOT_FOUND) - Singleton content exists but isn't published yet, and no preview key was supplied (message:Singleton content for "<type>" is not published)400 Bad Request(INVALID_SORT_FIELDS) -sortreferences a field outsidecreatedAt,updatedAt,publishedAt,name,slug,_sortOrder400 Bad Request(INVALID_FILTER_FIELD) -filter[field]uses a core field outside thename/slugwhitelist (use thefields.prefix for custom fields instead)400 Bad Request(INVALID_JSON_FIELD_PATH) -filter[fields.xxx]has a malformed JSON path (only alphanumerics, underscores, and dots are allowed, no leading/trailing/consecutive dots)400 Bad Request- Invalidpage/limit— this endpoint validates them with a rawzValidatorcall and returns Zod's default shape rather than one of the codes above; see the raw Zod shape note below500 Internal Server Error(INTERNAL_ERROR) - Server error
GET /api/v1/collections/:type/:slug
Get a single published collection item by slug.
Authentication: API key required Rate Limit: Standard rate limits apply
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
type | string | Yes | Collection type slug |
slug | string | Yes | Item slug |
Request Example
GET /api/v1/collections/products/awesome-product
X-API-Key: tento_pk_your_key_here
Response (200 OK)
{
"data": {
"price": 99.99,
"description": "A great product",
"_sortOrder": 0,
"_publishedAt": "2025-06-01T12:00:00.000Z",
"_updatedAt": "2025-06-01T12:00:00.000Z"
},
"collectionType": {
"id": "ct-123",
"name": "Products",
"slug": "products"
}
}
Redirect Response (301)
If the slug was an old slug that has been renamed, you'll get a redirect hint:
{
"redirect": {
"from": "old-product-slug",
"to": "awesome-product",
"url": "/collections/products/awesome-product"
}
}
Errors:
401 Unauthorized(UNAUTHORIZED) - Missing or invalid API key404 Not Found(NOT_FOUND) - Collection type slug doesn't exist for this tenant404 Not Found(NOT_FOUND) - Item slug doesn't exist within this collection type, and it isn't a redirect from a renamed slug either (message:Collection item "<slug>" not found in "<type>")500 Internal Server Error(INTERNAL_ERROR) - Server error
Create Collection Item
POST /api/v1/collections/:type
Path Parameters:
type— Collection type slug
Request Body:
{
"name": "Jane Smith",
"slug": "jane-smith",
"fields": {
"bio": "Writer and editor",
"role": "Content Strategist"
},
"status": "draft"
}
Request Body Fields:
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Display name (1-255 characters) |
slug | string | Yes | URL slug (unique within collection type) |
fields | object | No | Content fields, max 1 MB, validated against collection schema |
status | string | No | draft (default) or published |
Response (201):
{
"data": {
"id": "123e4567-e89b-12d3-a456-426614174000",
"collectionTypeId": "abc123...",
"name": "Jane Smith",
"slug": "jane-smith",
"status": "draft",
"draftContent": { ... },
"publishedContent": null,
"sortOrder": 0,
"version": 1,
"createdAt": "2026-02-09T10:00:00Z",
"updatedAt": "2026-02-09T10:00:00Z"
}
}
If status: "published", the item is created and immediately published.
Errors:
404— Collection type not found409— Slug already exists within collection413— Content fields exceed 1 MB400— Content validation failed
Update Collection Item
PUT /api/v1/collections/:type/:slug
Path Parameters:
type— Collection type slugslug— Collection item slug
Request Body (Partial Update):
All fields are optional. Only provided fields will be updated.
{
"name": "Jane Smith (Updated)",
"slug": "jane-smith-updated",
"fields": {
"bio": "Senior Writer and Editor"
}
}
Response (200):
{
"data": {
"id": "123e4567-e89b-12d3-a456-426614174000",
"name": "Jane Smith (Updated)",
"version": 2,
...
}
}
Errors:
404— Collection type or item not found409— Slug conflict or version conflict413— Content fields exceed 1 MB400— Content validation failed
Delete Collection Item
DELETE /api/v1/collections/:type/:slug
Path Parameters:
type— Collection type slugslug— Collection item slug
No request body required.
Soft-deletes the item (sets deleted_at timestamp). Cache is invalidated.
Response (200):
{
"success": true
}
Errors:
404— Collection type or item not found

