Contents
- Domma CMS User Manual
- 1. Using the CMS
- 2. Tutorials
- 3. Components
- 4. API Reference
- 5. Tools
API Builder
Updated by Darryl Waterhouse on 29 September 2026 · 3 min read
API Builder publishes named, read-only endpoints over collection data at /api/x/<project><path> - for example /api/x/world-cup/fixtures-day/:date. A definition is data, never code: it binds a path to one fixed collection query. An endpoint grants access to exactly that query, whatever the collection's own external API settings say.
How it works
- Definitions are entries in the file-based
api-endpointspreset collection, edited under Data > API Builder (permission familyapi-endpoints.*) or created by a scaffolder recipe (apiEndpoints: [...]). - The first URL segment after
/api/x/is the endpoint's project; the rest is matched against itspath. Static segments beat:paramsegments, so/m/latestwins over/m/:day. - An endpoint may only expose a collection in its own project or in
core, and never a system-managed or preset collection (roles, users, API tokens and so on). - Only
GETis served. An unknown project, unknown path or switched-off endpoint answers404identically; so does every endpoint of a switched-off project. - Endpoints are project artefacts: a project that still has endpoints cannot be deleted.
The API Builder screen
Data > API Builder lists the endpoints you can see (your project scope applies), with the public ones counted on the sidebar badge. The editor has three tabs and a try-it console:
- Definition - name, project (fixed once saved), path, collection, auth and mode.
- Query - filter rows (field, operator, value; a value can use a
:paramor a query placeholder), sort, order and limit. - Response fields - tick the fields the endpoint returns. None ticked returns every field.
- Try it - calls the saved definition with the path parameters and query you enter, keeps a history, and copies a request as curl. Save first to test a change. For a token endpoint, paste a token.
Definition
| Field | Default | Rules |
|---|---|---|
name | - | Required |
project | - | Required, must exist; cannot be changed after creation |
path | - | Starts with /; segments are lower-case letters, digits and hyphens, or :name. Two endpoints in one project cannot share a path shape (/a/:x and /a/:y collide - 409). |
collection | - | Required; own project or core; not system-managed |
auth | public | public, token or an existing role name |
mode | list | list returns { entries, total, page, limit }; single returns the first match or 404 |
filter | {} | { "field_op": value } with the standard operators (_eq, _ne, _gt, _gte, _lt, _lte, _in, _nin, _contains, _starts, _ends, _exists). Values are strings, numbers or booleans. |
sort / order | createdAt / desc | Order is asc or desc |
limit | 50 | Integer 0-500; 0 means no limit |
fields | [] | Response allowlist of data fields; empty returns all |
enabled | true | Off answers 404 |
Filter values may carry placeholders:
{{params.name}}- from a:namepath segment. It must exist in the path (checked on save); empty at request time answers400.{{query.name}}- from?name=. When absent, the whole clause is dropped, so it works as an optional refinement.
{
"name": "Fixtures by day",
"project": "world-cup",
"path": "/fixtures-day/:date",
"collection": "wc-schedule",
"auth": "public",
"mode": "list",
"filter": { "date": "{{params.date}}", "stage": "{{query.stage}}" },
"sort": "seq", "order": "asc", "limit": 0,
"fields": ["seq", "date", "title", "stage"],
"enabled": true
}
Calling an endpoint
List-mode endpoints also accept, within the definition's bounds:
| Query | Effect |
|---|---|
page | Page number |
limit | Smaller pages; never above the definition's limit (or 500 when that is 0) |
sort / order | Sort by any field the endpoint returns |
<field>_<op>=value | Extra filters on fields the endpoint returns (no filter[...] wrapper). A field the definition already filters on cannot be overridden. |
# Public, list mode
curl 'https://example.com/api/x/world-cup/fixtures-day/2026-06-11?stage=group&limit=10'
# Token auth
curl -H 'Authorization: Bearer dcms_0123...cdef' \
https://example.com/api/x/world-cup/squad/eng
# Role auth - a user's access token
curl -H 'Authorization: Bearer eyJ...' https://example.com/api/x/members/directory
Auth follows the same rules as the external API:
- public - anyone. These responses are cached and refreshed automatically when the collection's entries or the definition change.
- token - a project API token whose project is the endpoint's project. Scopes are checked against the endpoint's collection with the
readverb. A JWT is refused. - role name - a signed-in user with that role or a more senior one.
Errors: 401/403 from auth, 400 for a missing path parameter, 404 for no such endpoint or no match in single mode.
Managing endpoints over HTTP
All need a JWT; project scope applies to the endpoint and to the collection it queries (403 otherwise).
| Method | Path | Permission | Description |
|---|---|---|---|
GET | /api/api-endpoints | api-endpoints.read | List definitions |
GET | /api/api-endpoints/:id | api-endpoints.read | One definition |
POST | /api/api-endpoints | api-endpoints.create | Create; 201, 400 invalid, 409 duplicate path shape |
PUT | /api/api-endpoints/:id | api-endpoints.update | Update the fields sent; project is ignored |
DELETE | /api/api-endpoints/:id | api-endpoints.delete | Delete; the URL answers 404 at once |
The base super-admin and admin roles hold api-endpoints.*; custom roles need it granted in the role editor.