Skip to content

API

Most of what the dashboard does, it does through an API you can use too - certificates and agents are read-only there, and users are managed rather than created.

The GraphQL APINothing leaves the page - the responses are canned.DemoNothing you change here is saved
POST /api/graphql
Text
Run the query to see what this deployment would answer.

/api/graphql serves every resource: proxy hosts, L4 hosts, certificates, access lists, users, groups, agents, settings, the audit log, and a Caddy apply.

Terminal window
curl -sX POST https://cpm.example.com/api/graphql \
-H "Authorization: Bearer $CPM_TOKEN" \
-H 'content-type: application/json' \
-d '{"query":"{ proxyHosts { id name domains enabled } }"}'

The schema is introspectable by any authenticated GraphQL client, so your tooling can discover it rather than being told about it.

Stable, queryable things are fields: ids, names, domains, timestamps, foreign keys. Configuration that the model layer owns - load balancing, WAF and geoblock overrides, location rules, mTLS - travels as a JSON scalar: readable through config on a host, and passed back as input on a mutation.

That split is deliberate. Those shapes change with the product and are already validated by code that exists; restating them in the schema would be thousands of lines that can drift out of step with the validator while looking authoritative.

bulkProxyHosts and bulkL4ProxyHosts take { action, ids } and return how many hosts changed. Proxy hosts accept enable, disable, delete, maintenanceOn, maintenanceOff, setCertificate (with certificateId, null for automatic) and setAccessList (with accessListId, null for none); L4 hosts the first three. Up to 500 ids per call.

mutation {
bulkProxyHosts(input: { action: "disable", ids: [4, 7, 9] })
}

A batch is all or nothing: an unknown id, or a change one host cannot take, fails the call and writes nothing. Each host is audited on its own, and Caddy is applied once. The REST equivalents are POST /api/v1/proxy-hosts/bulk and POST /api/v1/l4-proxy-hosts/bulk.

Bearer tokens, created from Profile → API Tokens in an authenticated dashboard session with an optional expiry. That restriction is deliberate: an existing token cannot mint replacement credentials, so a leaked one cannot extend its own life.

A token carries its owner’s role. The management fields are admin-only, including for an operator - a group grant delegates the dashboard, not the API. Managing your own tokens is the exception, and open to every signed-in role.

/api/v1/ still works exactly as it did, with the same Bearer tokens and interactive OpenAPI 3.1.0 documentation at /api-docs. It is no longer the documented path and will be removed in a later release.

Nothing in the field breaks in the meantime: both APIs call the same model functions, so they cannot disagree about what a write does.

/api/health is public and unauthenticated - it is what the container health check probes. It also answers the dashboard host reachability probe when asked with a nonce. Its boot field is a random id that changes each time the process starts, which is how setup tells a restart that finished between two checks from one that never happened.