Skip to content
Talk to our solutions team

API conventions

Every block’s HTTP API shares the conventions on this page. A block’s own API reference documents what is specific to it — its routes, bodies and error codes — and assumes everything here.

Runtime HTTP paths carry no version segment. There is no /v1/, and a documentation URL under /1.1.6/ does not imply one on the service.

/data/rest/... not /data/v1/rest/...
/config/... not /config/v1/...

Versioning is a property of the release you deployed, not of the URL. See version applicability on any API page for the release it describes.

Every request is scoped by a CPET — customer, product, environment, tenant. It is carried in four headers:

HeaderNames
X-CustomerThe customer
X-ProductThe product
X-EnvThe environment
X-TenantThe tenant

A service runs in one of three tenancy modes, which decides whether those headers are required:

ModeBehaviour
multiAll four are required. This is the normal deployment
singleThe service is pinned to one CPET; the headers are not read
noneThe service is not tenant-scoped

A bearer token also establishes the CPET, so a request carrying one may not need to send the headers separately — which of the two applies is per service, and each block’s API page says so.

Most routes require a bearer token:

Authorization: Bearer <token>

Some services additionally accept API keys, and some expose deliberately anonymous routes. Both are per service — the block’s API page lists which of its routes are anonymous, authenticated, administrative or superadmin-only.

Tokens come from IAM. See IAM for how to obtain and refresh one.

Not every service uses bearer tokens. vault.svc authenticates workloads by mTLS client certificate and config.svc accepts an API key, a bearer token or mTLS. Check the block’s own API page rather than assuming.

Handler and service errors use one shape:

{
"error": {
"code": "config-key-not-found",
"message": "the requested key does not exist",
"context": null,
"meta": null
}
}
FieldMeaning
codeA stable string to branch on. Empty on many errors — see the caution below
messageHuman-readable. Not stable; do not match on it
contextInternal detail. Often {} or null
metaExtra structured detail when the handler supplies it

When tracing is enabled, trace_id, span_id, request_id and correlation_id appear alongside them, and those are the handles to quote in a support request.

Every service exposes two unauthenticated probes:

RouteAnswers
GET /<service>/healthWhether the process is alive, with dependency status
GET /<service>/readyWhether it is ready to serve
{
"healthy": true,
"dependencies": {},
"version": ""
}

/ready reporting true does not always mean the service can do useful work — a service may register its routes before it has loaded the configuration or rule sets it serves. Where that gap exists, the block’s operations page says so.

Rate-limited responses carry their own shape rather than the envelope above:

{"error": "rate_limited", "profile": "<profile>", "retry_after_seconds": 30}

Honour retry_after_seconds.

  • Blocks — the capability map
  • IAM — tokens, API keys, roles
  • Data API — the most fully specified example of these conventions
  • Glossary — CPET, tenant, product and the rest of the vocabulary