Skip to content

REST API overview

Everything the dashboard does is available under /api/v1, and the Agent, the plugins and the reporting scripts use the same API. This page covers the conventions that apply to every call; the interactive reference lists each route.

Where the API lives

Host Serves Typical caller
Your workspace address - https://<slug>.app.certin.tel or your own vanity domain - plus /api/v1 The whole API and the dashboard. Browser sessions, integration keys, scripts that read the inventory.
The ingest host https://api.certin.tel Only the routes an Agent or reporting script needs: POST /api/v1/renewals, /checkins, /internal-certs, /agents/heartbeat, /agents/capabilities, /agents/workflow-assignments and …/{id}/status, /agents/unregister, /internal-endpoints/claim and …/{id}/result, /crl-monitors/report, /private-cas/{id}/issue, the …/agent/all listings, /install-tokens/exchange, /dns-delegations/{id}/txt, /acme-dns/update, /api/v1/auth/me, /api/v1/releases, /api/v1/meta, /api/v1/version and the public /pki/ publication paths. No dashboard, no sign-in, no inventory reads. Agents, ACME clients and scanners that must keep working even when the dashboard sits behind an IP allowlist.

The ingest host is never filtered by the workspace IP allowlist; the workspace address is, unless Settings → Security allows ingest from any IP. Use the exact base URL shown on the Install Tokens, API Keys or Delegated DNS-01 page rather than deriving one.

Interactive reference

Sign in to your workspace and open API docs from the account menu, or go to /api/v1/docs (Swagger UI) or /api/v1/redoc; the schema is at /api/v1/openapi.json. The reference is generated from the running platform, so it always matches the deployed version. Demo accounts are redirected away from it. GET /api/v1/meta (no authentication) returns the product version, build, deployment mode and capability flags; GET /api/v1/version adds the database schema status.

Authentication

  • API keys are presented as <prefix>.<secret> in either the X-Api-Key header or Authorization: Bearer <prefix>.<secret>. What a key may do is decided by its kind, its API role and its organization binding; see API keys & authentication. A wrong, revoked or expired key always gets the same 401. A read-only key (the API read-only role, or a custom API role that holds only read permissions) may only send GET requests under /api/v1; anything else answers 403.
  • Browser sessions from the dashboard can call the API too (the API docs page relies on this). POST /api/v1/auth/login starts a session for a local account and is throttled like the sign-in page (10 attempts per minute per address and email, 30 per address, and a 15-minute lockout after eight consecutive failures); a spent limit answers 429 with Retry-After. Single sign-on users sign in through the dashboard.
  • POST /api/v1/auth/change-password refuses a new password equal to the current one (400). Wrong current passwords have their own limit (eight per account in 15 minutes, then 429 with Retry-After) and do not count toward the sign-in lockout. For an account with two-factor sign-in, the answer has mfa_required: true and the session can only call POST /api/v1/auth/mfa/verify (with code or recovery_code), GET /api/v1/auth/me and POST /api/v1/auth/logout until the code is verified; every other call answers 403 with mfa-required.
  • GET /api/v1/auth/me describes the current principal: the tenant, the organizations it can act in, its permissions, and for a reporting key the reporting_organization_id its submissions land in. It is the quickest way to check a new key.
curl https://<slug>.app.certin.tel/api/v1/auth/me \
  -H "X-Api-Key: cik_<prefix>.<secret>"

Pagination

List routes use keyset pagination:

Query parameter Meaning
limit Rows per page, 1–200, default 50.
cursor The opaque meta.next_cursor from the previous page; omit for the first page. It is signed - do not construct or decode it.
order asc or desc (default desc).

Responses carry the rows in items and a meta object with limit, next_cursor and has_more; stop when has_more is false. A list refuses a query parameter it does not take with 422 (Unknown query parameter; this list takes: …) instead of answering an unfiltered list; there is no sort parameter. The interactive reference lists each route's filters.

Errors

Every error is an RFC 9457 problem document with Content-Type: application/problem+json:

{
  "type": "https://certin.tel/problems/not-found",
  "title": "Not Found",
  "status": 404,
  "detail": "…",
  "request_id": "…",
  "errors": [{"field": "…", "message": "…"}]
}

errors appears only on validation failures (422). Text containing the NUL character (U+0000) or an unpaired UTF-16 surrogate - in the path, a query parameter, a JSON body or a form field - is refused before any route runs with a 422 whose error has "type": "invalid_character" and names the field (Text cannot contain the NUL character (U+0000) or an unpaired UTF-16 surrogate.). Quote the request_id when you report a problem; every 5xx answer carries one, in the body and the X-Request-Id header. A resource that exists in another tenant or organization answers 404, never 403, so an id cannot reveal what exists elsewhere; see troubleshooting. When a workspace accepts agents only on its own address (Only accept agent submissions on our workspace address under Settings → Security), an agent route called with that workspace's credential on any other address, such as the shared ingest host, answers 404 with the type …/problems/workspace-address-required and a detail naming the workspace address: This workspace accepts agents only on its own address, https://…. Enrol the agent again with that address, or turn off "Only accept agent submissions on our workspace address" on the workspace's Security page. Only a caller that already authenticated as that workspace gets this answer; see troubleshooting. A 429 (…/problems/rate-limited) carries a Retry-After header: the seconds left in the limit's window, rounded up (at least 1, never more than the window). Wait that long before retrying; a request sent after exactly that wait falls in the next window. Besides sign-in and ingest, the actions started by hand that send or probe something are limited: a destination's test (3 per destination and 10 per person a minute), a report's send and re-send (3 per report and 10 per person an hour) and an endpoint's check (3 per endpoint and 30 per person a minute). The person's limit is counted first and the detail says which limit refused the request; see Alerts & notifications.

Resource families

Prefix What it covers Guide
/auth Session login/logout, password change, me, and the second sign-in step POST /auth/mfa/verify. this page, Two-factor sign-in
/caa-check GET /api/v1/caa-check?name=<name>&name=<name>&ca=<key> (or directory=<ACME directory URL> instead of ca): whether each name's CAA records allow that CA to issue, with status allowed, refused (with fix and the record to add), check or not_applicable per name and a summary. CA keys: letsencrypt, zerossl, google, digicert, sectigo, sslcom, globalsign, actalis, amazon; an unknown directory is answered check. At most 20 names, 30 checks a minute per user or key (429 with Retry-After); needs targets.read, workflow_assignments.read or dns_delegations.read. CAA records
/organizations, /users, /roles, /permissions Organization tree, users, built-in and custom roles, the permission catalogue (/roles and /permissions need roles.read workspace-wide, or users.read for user roles, or api_keys.create, api_keys.update or api_keys.admin for API roles). A role has a kind, user or api: POST /roles takes it (default user), GET /roles?kind=user or ?kind=api narrows the list, an API role carries key_count and keys (the keys that use it), and GET /permissions?kind=api returns what a custom API role may hold. POST /users/{user_id}/mfa/reset removes a user's two-factor sign-in (users.update, 204). Organizations, users & roles, API roles, Two-factor sign-in
/api-keys, /install-tokens Integration and Agent keys, install tokens and the exchange route. POST /api-keys takes an optional role (the id or key of an API role; the scope then follows from the role), PATCH /api-keys/{id} with {"role": "…"} gives a key another API role, and a key reads back with role, role_id and role_name. POST /install-tokens/one-time mints a one-time token (expires_in_minutes 15, 60, 240 or 1440; the 201 answer carries the secret once, with Cache-Control: no-store); token responses include kind (organization / one_time) and used_at, and reveal, rotate and reactivate answer 409 for a one-time token. API keys, Install tokens
/certificates, /ct-findings, /targets The inventory, Certificate Transparency findings, public endpoint monitors. A certificate carries renewal_schedule (planned renewal, basis, ARI window, deployment state) when its managing Agent reports one. A CT finding carries issued_by_certintel, in_inventory and new_name_set. GET/POST /targets/{target_id}/certificate-links and DELETE /targets/{target_id}/certificate-links/{link_id} list, add and remove an endpoint's links to managed certificates (targets.read / targets.update). A target carries a tls block (grade, reasons, versions, cipher, key exchange group, post-quantum badge, chain, assessment time) and a writable probe_legacy_tls, on a platform build that offers TLS grades. Certificates, TLS grade, CT Log Watch
/trusted-cas Trust anchors and the ignore list (ignored.json is public). Trusted CAs
/private-cas and /pki/{ca_id}/… Issuing CAs, issuance, export, revocation and the public CRL publication. Where offered: POST /private-cas/{ca_id}/rotate (Rotate now, private_ca.update, 202), auto_rotate on PATCH, and GET /private-cas/{ca_id}/trust (per-host root trust, private_ca.read). Private CA
/renewals, /checkins, /internal-certs Reporting from ACME clients and scanners. A renewal read carries failure_output (a failed installation step and the redacted end of its output) and deployment_window_override when the Agent reported them. ACME check-ins & renewals, Internal certificate scanners
/agents, /internal-endpoints, /adcs-templates, /crl-monitors Enrolled Agents, platform-assigned endpoint checks, AD CS template and CRL distribution point monitors. GET/POST /internal-endpoints/{id}/certificate-links and DELETE /internal-endpoints/{id}/certificate-links/{link_id} list, add and remove an internal endpoint's links to managed certificates (internal_endpoints.read / internal_endpoints.update). Where offered, GET /agents lists Agents with agent_version, config_locked, outdated, latest_version and (with agent_updates.read) the live update_request (agents.read, ?outdated=true), and POST /agents/{api_key_id}/sealing-key/approve approves the sealing key an Agent reported, the first one or a new one (platform_credentials.update, 204): the body {"key_id": "<16 hex>", "fingerprint": "<SHA-256, optional>"} names the key you checked (422 without key_id), and 409 sealing-key-changed means another key waits now and nothing was approved. Monitors & internal endpoints, CRL monitoring, Install tokens & the Agents page
/agent-updates Update requests for Agents: GET lists them, POST with api_key_ids (up to 500) or all_outdated: true and an optional target_version creates them (201; Agents that cannot take one are listed as skipped), DELETE /agent-updates/{id} cancels a request the Agent has not received yet (agent_updates.read / .create / .delete). The device decides whether to install. Install tokens & the Agents page
/platform-credentials Appliance credentials for remote deployment: GET (list, one), POST (201), PATCH (rename or replace the secret), DELETE (204). Secrets are write-only and never returned (platform_credentials.*). Platform credentials
/msp/organizations MSP mode: per client organization, expiring, expired, renewal_failures_7d, served_mismatches (public and internal endpoints together), offline_agents and ct_new_name_sets (workspace-wide users, Enterprise msp). Organizations, users & roles
/dns-delegations and /acme-dns/update Delegated DNS-01 records and TXT updates. A TXT value is at most 255 ASCII characters (native API 422, acme-dns 400); /acme-dns/register answers 403 on every host that serves /acme-dns/update. Delegated DNS-01
/workflows Certificate workflows from a bundled template, for one Agent or several: list, create, read, edit, offer to the next Agent, start a new round or send again, cancel and delete. See Workflows. workflow_assignments.* permissions. Workflow Assignments
/workflow-assignments The proposals of a workflow, one per Agent it was offered to; every assignment has a workflow_id. POST creates a workflow for one Agent and answers with its assignment; GET lists with cursor pagination and shows the timeline; …/{id}/resend, …/{id}/cancel, DELETE for finished ones. See Workflow assignments. The Agent's own routes are PUT /agents/capabilities, GET /agents/workflow-assignments and POST /agents/workflow-assignments/{id}/status. workflow_assignments.* permissions. Workflow Assignments
/notification-channels, /scheduled-reports, /alert-contacts Alert destinations (an email destination takes up to 50 contact_ids; PUT and PATCH keep what they do not send, secrets included; an organization's destination refuses auth.warning), periodic report emails, and alert contacts (GET/POST /alert-contacts, PATCH/DELETE /alert-contacts/{id}; alert_contacts.read / .update; reads say whether the address unsubscribed). Alerts & notifications
/oidc/providers Identity providers for single sign-on. OIDC / SSO overview
/releases Public release records for the Agent and plugins. Downloads
/activity, /jobs The activity log and background jobs. -

POST /api/v1/notification-channels/destinations/{id}/send-digest sends an alert destination everything that is open for it now, labelled as sent on request (see Send digest now). The destination's scheduled alerts and daily summary are not changed. It answers status sent, failed or nothing_due (nothing was sent), with tier, items, response_status and failure_class. It needs notifications.test and certificates.read in the destination's whole scope, answers 409 for a paused destination, and is limited like a test send (429 with Retry-After).

POST /api/v1/targets takes hostname as a DNS name or IP address only; the port goes in port. A URL is refused with 422, and the message names what to send: hostname must be a DNS name or IP address such as example.com, without https://, a port or a path (the port goes in port). For https://www.example.com:8443/shop, send hostname www.example.com and port 8443. The dashboard's Add a site form takes a pasted URL itself (see What to do first).

Workflows

A workflow is a certificate, the bundled template that installs it, and the Agents allowed to run it: one (the server the certificate is for) or up to 20 of one organization, first preferred. It is what Workflow Assignments in the dashboard lists and what New workflow creates. Errors are problem documents; a workflow or an Agent key outside the organizations the caller can act in answers 404.

Method and path Body Permission in the workflow's organization
GET /api/v1/workflows Query: limit, cursor, order, state, api_key_id workflow_assignments.read
POST /api/v1/workflows (201) The proposal fields, name and api_key_ids workflow_assignments.create and agents.read
GET /api/v1/workflows/{id} - workflow_assignments.read
PUT /api/v1/workflows/{id} As for create workflow_assignments.update, workflow_assignments.create and agents.read
POST /api/v1/workflows/{id}/next - workflow_assignments.update
POST /api/v1/workflows/{id}/restart Optional {"api_key_id": "…"} workflow_assignments.update
POST /api/v1/workflows/{id}/cancel Optional {"remove_from_agent": true\|false} workflow_assignments.update
DELETE /api/v1/workflows/{id} (204) Query: optional remove_from_agent=true\|false workflow_assignments.delete

The built-in roles: Observer and Auditor read; Operator creates, edits, moves and cancels; deleting needs Administrator. A read-only API key reaches the two GET routes only.

The proposal fields are those the workflow form fills in:

Field Value
template id and version of a bundled template the Agent reports.
variables The template's settings. A credential setting is local or platform:<id> (needs platform_credentials.read), never a value.
certificate id (see the certificate id rule), name, domains, key_type, auto_renew. A challenge other than {"type": "dns-01"} is refused with 422. For a Private CA issuer also validity_days, ip_addresses, an optional private_ca_profile, and empty domains with ip_addresses; an IP address in an ACME certificate's domains is 422.
issuer {"kind": "private-ca", "ca_id": "…"} or {"kind": "acme", "account_id": "…"}.
deployment_window Optional; see Deployment windows.
dns_delegations ACME only: [{"domain": "…", "delegation_id": "…"}], the organization's Delegated DNS-01 records that validate the base domains.
issue_now Boolean, default false.
note Optional, at most 500 characters, shown to the person who approves on the device.
expires_in_days 1 to 90, default 30.

name is optional, at most 120 characters; left out, the workflow takes the certificate's name, or its id. api_key_ids lists 1 to 20 Agent keys of one organization, first preferred; a key listed twice is 422. A field the Agent does not report support for is refused with 422.

A workflow reads back with id, organization_id, name, certificate_id, state, api_key_ids, the proposal fields, bound_api_key_id (the Agent that runs it), offered_api_key_id and current_assignment_id (the proposal that is out), round_started_at, created_by, created_at and updated_at.

state Meaning
offering It is being offered to an Agent.
bound An Agent applied the workflow and runs it.
exhausted No Agent took it: every one rejected it, failed it before applying it or let it expire.
cancelled Cancelled.
  • List is paged like the other lists. state filters on one of the four states; api_key_id returns the workflows that name that Agent.
  • Read one adds agents, offers and timeline. Each of agents has api_key_id, name, position, status (offered, running, tried or waiting) and problem: why that Agent cannot take the workflow now, or null. offers are the workflow's assignments, newest first.
  • Create offers the workflow to its first Agent as a pending assignment; nothing is applied by the call. With several Agents, every one must be able to run the workflow now, or the answer is 422 and names each one that cannot. With one Agent the refusal is that Agent's own: 409 when it has sent no capabilities report, its credential cannot take proposals or the certificate id is taken there; 403 for an issuer the key may not use; 422 for the proposal itself.
  • Edit (PUT) replaces the name, the Agents and the proposal. The certificate id cannot change (422). The answer adds outcome:

    outcome What happened
    saved Stored; nothing was sent.
    resent The proposal that is out was sent again with the edit.
    offered The workflow was offered afresh.
    exhausted No Agent can take it now.
    update Sent to the Agent that runs it, as a replacement it applies once approved there (Agent 1.8.2 or later).

    It is refused with 409 while the Agent is applying the workflow, and for a cancelled workflow. - Next withdraws the proposal that is out and offers the workflow to the next Agent that can take it; 409 unless a proposal is waiting. When nobody is left, the state is exhausted. - Restart starts a new round with the first Agent that can take it, or sends the workflow to the Agent named in api_key_id (404 when that key is not one of the workflow's Agents, 422 when it cannot run the workflow now). This is how a proposal the Agent rejected is sent again. A workflow an Agent runs moves to another Agent; the Agent that ran it keeps its copy until a local administrator removes it there. 409 for a cancelled workflow. - Cancel withdraws the proposal that is out. An Agent that already runs the workflow is also asked to remove it (Agent 1.19.0+; see Removing a workflow from the Agent). remove_from_agent omitted: removed from each Agent that can take a removal; an older Agent keeps it until a local administrator removes it there. true: 422 Requires Agent 1.19.0 or later on when the Agent is older. false: the Agent keeps it. - Delete is refused with 409 while a proposal is out; a removal that is out does not block it. remove_from_agent works as for Cancel. The workflow's assignments and activity events are kept. - A removal is listed among the workflow's assignments with request_type retire; other assignments have create or replace.

Workflow assignments

An assignment is one proposal of a workflow to one Agent. Every assignment has workflow_id.

  • POST /api/v1/workflow-assignments takes the proposal fields and one api_key_id. It creates a workflow for that Agent, named after the certificate, and answers with its assignment.
  • POST …/{id}/resend sends a waiting proposal again as a new revision. With a body (the proposal fields) it edits the workflow; the certificate id cannot change. A proposal the Agent rejected is not sent again here (409): restart its workflow with POST /api/v1/workflows/{id}/restart.
  • POST …/{id}/cancel withdraws a waiting proposal. Its workflow goes to the next Agent, or is left exhausted when there is none.
  • DELETE …/{id} removes a finished assignment. Its workflow stays.

Routes used only by the platform console are not part of the published schema.