Skip to content

HTTP API Reference

Base URL is your mounted app (e.g. http://localhost:3000). JSON bodies use Content-Type: application/json unless noted.

Errors

Failed requests return JSON:

{
"code": "VALIDATION_ERROR",
"message": "Validation failed",
"details": {},
"requestId": ""
}

code values align with @timbl/core ErrorCodes (e.g. NOT_FOUND, UNAUTHORIZED). Typical status codes: 400 validation, 401 unauthorized, 404 not found, 409 conflict, 501 not implemented, 500 internal.

Collections

:collection is the collection key from defineCollection.

MethodPathAuthDescription
GET/api/:collectionpublicList entries (limit, offset, sort, filters, … query params)
GET/api/:collection/:slugpublicGet one by slug
POST/api/:collectionsessionCreate
PUT/api/:collection/:idsessionReplace / update by id
DELETE/api/:collection/:idsessionDelete

List response (GET /api/posts?status=published):

{
"collection": "posts",
"total": 42,
"limit": 20,
"offset": 0,
"items": [
{
"id": "abc123",
"title": "Hello",
"slug": "hello",
"body": "# Hello",
"bodyHtml": "<h1>Hello</h1>",
"status": "published",
"createdAt": "2026-06-19T12:00:00.000Z",
"updatedAt": "2026-06-19T12:00:00.000Z"
}
]
}

Single entry (GET /api/posts/hello):

{
"id": "abc123",
"title": "Hello",
"slug": "hello",
"body": "# Hello",
"bodyHtml": "<h1>Hello</h1>",
"status": "published",
"createdAt": "2026-06-19T12:00:00.000Z",
"updatedAt": "2026-06-19T12:00:00.000Z"
}

Globals

MethodPathAuth
GET/api/globals/:keypublic
PUT/api/globals/:keysession

Response (GET /api/globals/siteSettings):

{
"key": "siteSettings",
"siteName": "My Site",
"siteUrl": "https://example.com"
}

Assets

MethodPathAuth
GET/api/assetspublic (list)
GET/api/assets/:idpublic
POST/api/assetssession (multipart/form-data: file, optional directory, filename, alt)
DELETE/api/assets/:idsession

Asset response (GET /api/assets/asset_123):

{
"id": "asset_123",
"filename": "cover.jpg",
"originalName": "photo.jpg",
"mimeType": "image/jpeg",
"size": 524288,
"path": "posts/cover.jpg",
"url": "/uploads/posts/cover.jpg"
}

GET /uploads/* is reserved; the default headless stack does not serve files from that path—use your reverse proxy or storage URLs.

OpenAPI & docs

MethodPathNotes
GET/openapi.jsonOpenAPI 3.1 document with auth security schemes, route schemas, and plugin OpenAPI extensions
GET/docsAPI docs UI (default Scalar; configurable via apiDocs)

The default Scalar docs consume /openapi.json. Auth-capable operations include OpenAPI security metadata for sessionCookie and bearerAuth, so protected requests can be authorized from the docs UI. Auth provider passthrough routes are shown when the runtime adapter advertises providerRoutes; the default Better Auth adapter exposes /api/auth/*. Timbl always shows canonical auth actions as concrete routes such as /api/cms/auth/actions/login, /api/cms/auth/actions/register, and /api/cms/auth/actions/logout; adapter actions can refine those schemas or add more routes through AuthCapabilities.actions.

Health

MethodPathNotes
GET/api/healthProcess health check
GET/api/readyDependency readiness check (503 when the database check fails)

Export

MethodPathAuth
GET/api/exportsession

The export route is registered only when ENABLE_CMS_EXPORT=true. The default export handler requires an authenticated service principal.

Session & auth actions

MethodPathAuth
GET/api/cms/auth/sessionpublic
POST/api/cms/auth/actions/:actionpublic
POST/api/cms/auth/actions/<advertised-action>public

POST forwards the JSON body as the second argument to AuthAdapter.invoke. Better Auth provider traffic is also handled under /api/auth/* by default.

See Auth API Reference for OpenAPI security scheme behavior, action response conventions, and provider passthrough details.

Plugin routes

Static routes on plugins and routes registered in setup use the exact paths you provide; they are merged into the router with core routes.