REST API reference
Read-only, token-authenticated, cached at the edge
Your frontend reads published content from kura over HTTP. Base URL: https://kuracms.com/api/v1/{project}, where {project} is your project slug.
Authentication
Send your project token (prefixed kr_live_) as a Bearer token on every request:
Authorization: Bearer kr_live_your_token The project token is full-access: the same kr_live_ token
authenticates both reads and writes (the public API has create/update endpoints, and a POST
auto-publishes). Keep it server-side, never in client-side code. Create one
from your project page (/app/{slug}, the Developer section); it's shown once, so copy it on creation.
Status codes
200- content returned. Envelope:{ "data": [...], "meta": { "count", "limit", "offset" } }.meta.countis the number of entries in this response (up tolimit), not a grand total - there is no total-count field; page withlimit/offsetuntil you get back fewer thanlimit.401- missing or invalid bearer token.402 Subscription inactive- the project is not billing-active, so content is not served. A brand-new project is on thefreetier (not active); start the free trial to flip it to active. A lapsed or paused project also returns402.404- unknown project or content type.
(Write endpoints, used by the admin and MCP, also return 400 for a malformed body
and 409 for a slug conflict on create - you won't hit these on read.)
Endpoints
GET /api/v1/{project}/{type}- list published entries of a content type.GET /api/v1/{project}/{type}/{entry}- one entry by its slug.GET /api/v1/{project}/types- every content type with its full field schema.GET /api/v1/{project}/types/{type}- one content type's schema.
Don't know your type slugs? Call /types first - it lists every content type and
field.
Query parameters (list endpoint)
- Sorting:
sort=-fieldis descending,sort=fieldis ascending (the-prefix is the canonical form). Sort on several: comma-separated, e.g.sort=-published_at,title. (sort=field:descstill works but is legacy - use the-fieldform.) - Filtering:
field=value(equals), plus operators in brackets:field[gt|lt|gte|lte|ne]=value,field[contains]=str(case-insensitive),field[startswith]=str,field[in]=a,b,c(comma list, max 50), andfield[isnull]=true|false. Example:?bedrooms[gte]=3&status=Available. - Field selection:
fields=a,b,creturns only those fields (idandslugare always returned);exclude=a,bdrops those. - Pagination:
limit(default 20, max 100) andoffset(default 0). There is nopageparam. - Drafts/preview: add
?preview(same token) to return unpublished draft content; preview reads are never cached. Default returns published only. Wire?previewto a/previewroute so editors can check changes before publishing.
Note: object-valued fields (rich_text, coordinates, gallery) cannot be filtered or sorted on.
What you get back - and four things to know
The response is clean JSON. Four field types behave in ways worth knowing before you build against them:
Relations return a bare slug
A relation field (a Listing linked to an Agent, say) comes back as
the linked entry's slug string, not the embedded object. There is no ?expand. To get the linked entry's content, make a second request for that slug.
// a Listing entry
{ "title": "...", "agent": "jane-smith" } // <- slug, not the agent object
// fetch it: GET /api/v1/{project}/agent/jane-smith Images return a relative media path
An image field comes back as a relative path, /media/{key} (e.g. /media/abc123.jpg), not a full URL. Your frontend must prefix it with the base URL to load it: ${KURA_BASE_URL}/media/abc123.jpg -> https://kuracms.com/media/abc123.jpg. (The example frontends do exactly this prefix
on any /media/ path.) A gallery field is a list of these paths.
Coordinates return {lat, lon}
A coordinates field comes back as an object: { "lat": 35.68, "lon": 139.76 } (the keys are lat and lon, not lng).
Rich text returns rendered HTML
A rich_text field comes back as a rendered HTML string, ready to drop into your
page (the same shape a markdown field gives).
The schema is additive (v0.1)
You can add content types and fields, but not rename or delete them yet. Treat the shapes you read here as append-only for now.
Setting kura up for the first time? Start with Getting started. Managing the schema from your AI tool? See MCP setup.