API keys & authentication¶
Every non-interactive call to CertIntel - a reporting script, an agent, a CI job - authenticates with an API key in a single header:
(Authorization: Bearer cik_<prefix>.<secret> also works, for tooling that only
speaks bearer tokens.)
A key's secret is shown exactly once, at creation - CertIntel stores only its hash. If you lose it, rotate the key for a new secret; there is no way to recover the original.
Two-factor sign-in does not apply to API keys: a key never asks for a code, even in a workspace that requires two-factor sign-in for its users. Protect keys accordingly.
Kinds of key¶
| Kind | Created by | What it may do |
|---|---|---|
| Ingest key | On the API Keys page, Kind: Ingest key (submits data, reads nothing) | Submits renewal events, check-ins and internal certificate scans. Reads nothing back. For reporting scripts. |
| Agent key | Exchanging an install token - the organization's long-lived token or a one-time token (see Install tokens & enrollment) | What an Agent needs: its reports, and the identity, policy and assignment routes that go with them. One key per device. |
| A key with an API role | On the API Keys page, Kind: A key with an API role, then the API role | What the role's permissions allow. For a custom script, CI pipeline or third-party integration that reads or manages. |
An ingest key and an agent key hold no role and cannot be given one. An agent key is created pending and does nothing until an administrator approves it on the Agents page - see Install tokens & enrollment for what that means and how to review a newly-enrolled device before it starts reporting.
API roles¶
A role is either a user role, granted to people, or an API role, given
to API keys. The kind is fixed when the role is created: a user role cannot be
given to a key, and an API role cannot be given to a user or an
identity-provider mapping (422, with the reason). The Roles page has a
tab for each, User roles (/roles) and API roles (/roles?tab=api),
with the same editor; an API role shows used by N keys and the keys you may
see.
A key with an API role can do what the role's permissions allow, in its own organization, or in the whole workspace when it is not confined to one. Workspace-level permissions (Roles, Security, Tenant appearance) count only on a key that is not confined to an organization.
Built-in API roles¶
The three built-in API roles cannot be edited:
| API role | Scope | What its keys may do |
|---|---|---|
| API read-only | read_only |
Reads what API operator reads, through the API only: monitoring data, agents, organizations, the names of keys and install tokens, and the activity log. Changes nothing. |
| API operator | dashboard |
The built-in Operator role plus the activity log: reads monitoring data and makes day-to-day changes - adds and edits endpoints, internal endpoints, certificate templates, CRL monitors and CT-watched domains, approves agents, proposes workflows and agent updates, acknowledges certificates and manages DNS delegations. It deletes only CT-watched domains, DNS delegations and scheduled agent updates. No user, role, API key or settings management. |
| API administrator | admin |
The built-in Administrator role in the key's organization, deletes and user management included. A key that is not confined to an organization is a workspace administrator. |
Custom API roles¶
Create an API role on the API roles tab defines your own: a name, the permissions, and Usable by - keys in any organization, or only keys in the organizations you tick. A custom API role can hold any permission a custom user role can, except these nine:
users.create,users.update,users.deleteroles.create,roles.update,roles.deleteidentity_providers.create,identity_providers.update,identity_providers.delete
So a key with a custom role cannot make people, change what people may do, or
change who can sign in. It can hold users.read, roles.read and
identity_providers.read. Like a custom user role, it never holds platform
permissions, backups, observability or releases.
- Editing an API role changes every key that uses it at once. The activity log names the keys. Where the edit gives a key something, you must hold everything that key will then hold; where it takes something away, you must hold everything that key held. Renaming is always allowed.
- A role limited to some organizations can only be used by a key confined to one of them, and its limit cannot be changed to leave out a key that uses it.
- A role that keys use cannot be deleted; the refusal gives the number of keys. Give them another role, or delete them, first.
Read-only keys¶
A key whose role holds only read permissions is read-only, whether the role is
API read-only or a custom one. Every request that is not a GET under
/api/v1 is refused with 403, whatever it asks for, and the refusal is
written to the activity log; the dashboard does not open for it either. Add
one write permission to the role and its keys stop being read-only at once.
Revealing an install token (install_tokens.reveal) and requesting or
downloading a certificate from a private CA (private_ca.issue) are not
reads: a role that holds either is not read-only. A read-only key confined to
an organization reads only that organization.
Scopes¶
Every key has a scope in the API. For a key with an API role the scope
follows from the role and is never chosen apart from it:
scope |
The key is |
|---|---|
write |
An ingest key or an agent key. The key form shows it as write (ingest only). |
read_only |
A key with the API read-only role. |
dashboard |
A key with the API operator role. It is not read-only. |
admin |
A key with the API administrator role. |
role |
A key with a custom API role. |
releases |
A key of CertIntel's own release-publishing tooling. Only a platform administrator can create it; it is not used by customers. |
POST /api/v1/api-keys takes an optional role, the id or key of an API
role (GET /api/v1/roles?kind=api lists them); scope can then be left out.
Sending scope read_only, dashboard or admin without a role creates a
key with the built-in role of that scope. PATCH /api/v1/api-keys/{id} with
{"role": "…"} gives a key another API role, and a key reads back with
role, role_id and role_name. For an API key, GET /api/v1/auth/me
returns api_key_scope and api_key_scope_description; its permissions
list is the exact set.
Who can manage keys¶
Among the built-in roles only Administrator (and tenant administrators)
creates, rotates, revokes, re-enables or deletes API keys and agent
credentials, or changes a key's role. A custom user role may hold
api_keys.create, update, delete or admin. A key never carries more
than the person who hands it out holds:
- To create, rotate or re-enable a key, or to change its role, you must
hold everything the key holds, in the key's organization - across the whole
workspace for a key that is not confined to one. Otherwise the request
answers
403naming what is missing. Rotating and re-enabling are checked because whoever learns the new secret inherits the key's authority. - Changing a key's role also needs everything the key will hold. Only a key that has an API role can be given another one; an ingest or agent key keeps its kind. What the key may do changes at once.
- A key with the API administrator role needs
api_keys.admin, and one that is not confined to an organization can only be handed out by a tenant administrator. On the platform console's key page, where every new key is unconfined, only a platform administrator can mint, rotate, edit or revoke an unconfined administrator orreleaseskey, because such a key carries platform-administrator authority. - A session switched into one client creates only keys confined to that client, and cannot create, edit or delete API roles.
Creating, editing and deleting API roles needs roles.create, roles.update
and roles.delete across the whole workspace, as for user roles. Approving a
freshly enrolled agent is the separate
agents.create permission (Operator and Administrator have it), and
re-registering one is agents.update. See
Delegation is bounded.
Narrowing a write key to specific resources¶
An ingest key (the write scope) can be narrowed at creation to a subset of
renewals / checkins / internal_certs, so a given script can only ever submit
one kind of data even if its secret leaks. Leave it unnarrowed for a script that
legitimately needs to post more than one (e.g. the bundled ACME wrapper scripts,
which post check-ins and renewal events).
Allowing a key to request Private CA certificates¶
Requesting certificates from a CertIntel Private CA is a
separate, opt-in switch on a key, not a write resource: enrolling an Agent
never lets it mint certificates by itself. A user holding private_ca.update
in the key's organization turns it on from the Agents page (Allow private
CA / Forbid private CA), from the CA page under Who may request
certificates, or with
POST /api/v1/api-keys/{key_id}/private-ca-issuance and {"enabled": true}.
Only an organization-confined write key (an Agent or an ingest key) can
be allowed; the switch is refused for a key with an API role and for
workspace-wide keys (Only an organization-confined write key (an agent) can be allowed to
request certificates.), and a revoked key must be reactivated first. An
allowed key can list the organization's active CAs and submit CSRs, and nothing
else: it cannot see issued certificates, revoke, export keys or configure a CA.
Each switch is recorded in the activity log.
Organization scope¶
A key is bound to one child organization, or left Workspace-wide (all organizations) by a caller with workspace-wide authority. The organization selected in the top bar is pre-selected in the form, and so is the only organization you can choose when Workspace-wide is not offered. Creating a credential cannot broaden the issuer's scope: an organization-confined caller cannot mint a workspace-wide key (Only a tenant administrator can create a tenant-wide key.). Check the Organization selection before creating it.
An organization-bound key reports to that organization. A tenant-wide reporting
key resolves to the tenant's default organization, or its only organization; if
neither is unambiguous, reporting returns a conflict instead of guessing. The
GET /api/v1/auth/me response exposes reporting_organization_id. Do not assume
an ingest payload can redirect an organization-bound key's reports elsewhere.
Expiry, rotation, and revocation¶
- Keys can optionally be given an expiry when created.
- Rotate issues a new secret for the same key - the old secret stops working immediately, but the key's identity, history, and any grants tied to it (e.g. Delegated DNS-01 access) are unchanged. Rotating an agent key also clears its unregistered flag, so the key works again (subject to the plan's agents limit).
- Revoke disables the key without deleting it - its reporting history stays in place. A revoked key can be reactivated later.
- Revoking or deleting a key needs
api_keys.delete(api_keys.adminfor a key with the API administrator role) in the key's own organization - workspace-wide for a key that is not confined to one - and every permission the key holds there, on the API and the dashboard alike. - Delete removes the key permanently: it can no longer authenticate and cannot be reactivated (Deleted keys cannot be reactivated. Create a new key.). Reporting history it produced is preserved. A deleted agent must enrol again with a fresh install-token exchange.
The Last used column updates for every authenticated request, including reads, at most once a minute.
Bad requests are opaque, on purpose¶
A wrong secret, a revoked key, and an expired key all produce the exact same
401 Unauthorized - there's no way to distinguish "this key doesn't exist" from
"this key is disabled" from the outside, so a leaked prefix can't be used to probe
a key's state. The one deliberate exception is a pending agent key, which
returns a distinguishable 428 Precondition Required - see
Install tokens & enrollment for why that one case is
different.
Browser sessions cannot be used from another website: the API does not allow credentialed cross-origin requests, so a browser-based integration on a different origin must use an API key.