Your data. Their app. No code in between.
Use the Collections API for structured data, or the read-only Content API for published pages, menus, site settings and search. Tokens are project-scoped and revocable. Build custom endpoints in the admin when you need a clean URL for a specific query.
From raw data to client-ready API.
Every collection, queryable over REST: 12 filter operators, sorting, pagination, reference resolution. Per-verb access control - enable exactly the reads and writes you mean to expose, nothing more.
Machine credentials done properly: hashed at rest, shown once, revocable instantly. Each token is bound to one project and can be narrowed to specific collections and verbs. Expiry and last-used tracking included.
Bind a clean URL to a fixed collection query in the admin. Path parameters, optional query refinements, field allowlists, single-or-list responses - then test it live before you ship it.
A read-only API for pages and navigation.
The Content API serves published pages, menus, public site settings and search as JSON at /api/content/v1. Use it for a mobile app, a separate front end or another service that needs the content your site publishes. It is off until an administrator enables it.
Read how the Content API works or see the user manual.
A fixtures API in one minute.
A client runs a World Cup site on Domma. Their schedule lives in a collection - 104 entries. They wanted their mobile app to ask one simple question: "what's on today?"
In the API Builder: pick the collection, type the path /fixtures-day/:date, add one filter - date equals {{params.date}} - tick the fields the app should see, and save. That's the whole job.
curl https://example.com/api/x/world-cup/fixtures-day/Thu%2011%20Jun
{
"entries": [{
"data": {
"seq": "001",
"date": "Thu 11 Jun",
"title": "Mexico vs South Africa",
"stage": "group"
}
}],
"total": 1
}
The URL is the contract. The collection's internal columns stay private, the schema can evolve behind it, and the client never sees a query string they didn't ask for.
Definitions are data, never code - there is no way for an endpoint to execute anything:
{
"path": "/fixtures-day/:date",
"collection": "wc-schedule",
"auth": "public",
"mode": "list",
"filter": { "date": "{{params.date}}" },
"sort": "seq",
"fields": ["seq", "date", "title", "stage"]
}
{{params.date}} - from the URL, required{{query.team}} - optional refinementsmode: single - first match or 404
Test it before anyone else does.
The builder's try-it console sends a real, credential-free request to your saved endpoint - exactly what an external caller experiences. Status code, pretty-printed JSON, and a copy-as-curl line you can paste straight into an email to your client.
- Live URL preview as you type the path
- Param inputs appear automatically for every
:segment - Token field appears when the endpoint is token-gated
- Copy as curl - the handover is one click
- Send stays disabled until you've saved - you always test what's actually live
Raw fetch Copy as curl Status + JSON
Tokens that behave like they should.
Created in the admin, shown once, stored only as a hash. Bound to a single project - a world-cup token simply does not work anywhere else - and optionally narrowed to specific collections and verbs. Disable for a pause; revoke for forever. Every token tracks when it was last used.
curl -H 'Authorization: Bearer dcms_…' \
https://example.com/api/v1/wc-schedule?filter[stage]=group&sort=seq
- SHA-256 at rest - the plaintext exists only in the moment you copy it
- Project binding - wrong project, instant 403
- Scopes -
jobs: readmeans read jobs, and nothing else - Expiry & last-used - audit and rotation built in
- Revocation is final - takes effect on the very next request
Safe by construction.
The platform is designed so the easy thing is the safe thing - guardrails are structural, not advisory.