Domma CMS User Manual

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-endpoints preset collection, edited under Data > API Builder (permission family api-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 its path. Static segments beat :param segments, so /m/latest wins 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 GET is served. An unknown project, unknown path or switched-off endpoint answers 404 identically; 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 :param or 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

FieldDefaultRules
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
authpublicpublic, token or an existing role name
modelistlist 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 / ordercreatedAt / descOrder is asc or desc
limit50Integer 0-500; 0 means no limit
fields[]Response allowlist of data fields; empty returns all
enabledtrueOff answers 404

Filter values may carry placeholders:

  • {{params.name}} - from a :name path segment. It must exist in the path (checked on save); empty at request time answers 400.
  • {{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:

QueryEffect
pagePage number
limitSmaller pages; never above the definition's limit (or 500 when that is 0)
sort / orderSort by any field the endpoint returns
<field>_<op>=valueExtra 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 read verb. 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).

MethodPathPermissionDescription
GET/api/api-endpointsapi-endpoints.readList definitions
GET/api/api-endpoints/:idapi-endpoints.readOne definition
POST/api/api-endpointsapi-endpoints.createCreate; 201, 400 invalid, 409 duplicate path shape
PUT/api/api-endpoints/:idapi-endpoints.updateUpdate the fields sent; project is ignored
DELETE/api/api-endpoints/:idapi-endpoints.deleteDelete; 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.