API hub
The API hub is where a firm publishes its data as an API — without a deploy and without code. One declaration produces three doors at once:
- The data route —
/api/hub/v1/<resource>, JSON in and out. - The description —
/api/hub/v1/openapi.json, an OpenAPI document generated from the same declaration, so it can never describe a door that does not open. - The assistant — Claudia can list, read and (where allowed) write the same resources, under the asking person's own rights.
All three doors ask one gate. A right granted once is granted everywhere; a right refused once is refused everywhere.
Back office → Configuration → API hub.
Publishing a resource
A resource names what is exposed, by which methods, and to whom:
- Address segment — the URL name, e.g.
products→/api/hub/v1/products. Unique within your firm; another firm may use the same name for its own data. - Kind and target — a content type (
content.article) offers the full set: list, get, create, update, delete. A saved list (a view's machine name) offerslistonly — its filters, columns and permission come from the view itself, exactly as on screen. - Methods — tick what the resource offers. Every caller is further narrowed by their own rights; the resource sets the ceiling.
- Callers — three kinds, each with its own floor:
| Caller | What decides their rights |
|---|---|
| Signed-in people | their existing permissions on the underlying thing, in the firm they have open — no second permission model |
| API keys | the key's grants ∩ what the resource allows; the grant is the permission |
| Anonymous | read only, and never more than the public site itself shows — published records of public types |
Removing or disabling a resource closes every door at once.
API keys
A key is a firm's credential for a foreign system — a customer's e-shop, a script, another ERP.
- Issued once, shown once. The secret is displayed at issue and never again; what is stored is a hash. Copy it immediately.
- Scoped. A key is granted named resources and methods; everything
else answers
403with the reason spelled out. - Rate-limited. Requests per minute, per key; over the limit the
answer is
429withRetry-After. - Revocable in one click. The integration stops on its next call and hears revoked, not not found.
- Audited. Every key call is recorded — resource, method, outcome, time — so an integration can be traced and a leaked key's history read.
A caller presents the key as the X-Api-Key header (or
Authorization: Bearer fek_…). A presented key that is unknown, revoked
or expired is refused outright — it never falls through to anonymous
data, because a broken integration must hear that it is broken.
Reading and writing
GET /api/hub/v1/products list (page, page_size)
GET /api/hub/v1/products/<id> one record
POST /api/hub/v1/products create {label, values, published}
PATCH /api/hub/v1/products/<id> update
DELETE /api/hub/v1/products/<id> delete
A saved-list resource takes its view's exposed filters as f_<name>
query parameters.
Writes go through the same domain services the screens use — validation, numbering, revisions and the activity trail behave identically, whichever door the change came through.
Refusals always say which of the three failures it is: the caller is
not known (401), the caller may not do this (403), or the thing is
not there (404). A record of another firm is not found — its
existence does not cross the firm boundary.
The description
/api/hub/v1/openapi.json is generated for the caller reading it: a
key sees the operations it was granted, a signed-in person sees what
their permissions open, an anonymous reader sees the anonymous resources.
An integrator can build a read integration from this document alone.
Claudia
Ask the assistant "what API resources can I reach?", "list products", "create an article titled Hello". She goes through the same gate as the routes — under your rights, in your open firm — and a resource disabled on this screen disappears for her in the same moment.