Repository navigation
Using the REST API
Documentation for the image tag 1.0.0-rc1. See Versions for the documentation of a release.
Everything the web UI and qca do goes through the REST API of the apiservice, by default on port 8082. All routes are under /v1, for example http://<QERTUM_HOST>:8082/v1/certificate-requests. Requests and responses are JSON.
The interactive OpenAPI page is only available on development builds, so this page is the reference for a deployed system.
The API accepts a bearer token (a JWT) issued by your identity provider and validated locally against its published keys. Qertum does not issue API tokens itself.
| Caller | How it gets a token |
|---|---|
| A person | Signs in through the web UI, or uses qca auth login (device authorization flow) |
| A script or another system | The OAuth client credentials grant with a client defined in your identity provider |
With the built-in identity provider, the token endpoint is http://<QERTUM_HOST>:8081/connect/token. An automation client is an entry in its clients.json with the client_credentials grant and the roles its tokens should carry; edit the file on the identity volume and restart the identity service. With another OpenID Connect provider, create a client there. Details and per-provider notes are in the identity provider documentation shipped with the release.
TOKEN=$(curl -s -u "$CLIENT_ID:$CLIENT_SECRET" \
-d grant_type=client_credentials -d scope=qertum-api \
http://qertum.example.org:8081/connect/token | jq -r .access_token)
curl -s -H "Authorization: Bearer $TOKEN" http://qertum.example.org:8082/v1/me/accessKeep token lifetimes short. A token that was revoked stays valid until it expires. A machine token carries no interactive sign-in, so it is refused for operations that require step-up authentication unless your identity provider stamps the required claims.
-
Authorization. Each route needs a permission (see Using the Web UI). Without it you get
403; without a valid token,401. -
Errors are
application/problem+json:titleis the category,detailthe reason,traceIdthe correlation id. The same id is in theX-Correlation-Idresponse header on every response, so quote it when you report a problem. -
Paging. List routes take
page(from 1) andpageSize, and return{ items, totalCount, page, ... }. -
Rate limit. Routes under
/v1/certificate-requestsare limited per caller (100 requests per 60 seconds by default); excess requests get429. -
Asynchronous work. Approving and revoking return immediately; issuance and revocation finish in the background. While a request is in progress, responses carry
Retry-After: 2; pollGET /v1/certificate-requests/{id}until the status is final (Issued,RejectedorRevoked). - Private keys are never part of a response body. Only the two key download routes below return a key, and each is audited.
- IDs are GUIDs.
API=http://qertum.example.org:8082/v1
H="Authorization: Bearer $TOKEN"
# 1. file a request: it is created Pending
ID=$(curl -s -H "$H" -H 'Content-Type: application/json' -d '{
"commonName": "www.example.com",
"type": "WebServer",
"keyAlgorithm": "ECDSA-P256",
"validityDays": 90,
"propertiesJson": "{\"dnsNames\":[\"www.example.com\"]}"
}' $API/certificate-requests | jq -r .id)
# 2. approve it (needs certificates.manage)
curl -s -X POST -H "$H" $API/certificate-requests/$ID/approve
# 3. wait until issued
until [ "$(curl -s -H "$H" $API/certificate-requests/$ID | jq -r .status)" = Issued ]; do sleep 2; done
# 4. download the certificate
curl -s -H "$H" "$API/certificate-requests/$ID/certificate?format=pem" -o www.example.com.pem
# revoke later
curl -s -X POST -H "$H" -H 'Content-Type: application/json' -d '{"reason":"key compromise"}' \
$API/certificate-requests/$ID/revokeTo ask whether policy would accept a request without creating it, POST /v1/certificate-requests/preview takes the same body. The requester is always taken from your token; any name in the body is ignored.
P: shows the permission needed. "Signed in" means any valid token; "admin" means the admin role.
| Route | P: | Purpose |
|---|---|---|
GET /v1/certificate-requests |
view | List requests (paged) |
GET /v1/certificate-requests/status-counts |
view | Counts by status |
GET /v1/certificate-requests/summary |
view | Summary figures |
GET /v1/certificate-requests/issued |
view | Issued certificates |
GET /v1/certificate-requests/issued/validity-counts |
view | Issued, grouped by remaining validity |
GET /v1/certificate-requests/rejected |
view | Rejected requests |
GET /v1/certificate-requests/revoked |
view | Revoked certificates |
GET /v1/certificate-requests/expired |
view | Expired certificates |
GET /v1/certificate-requests/{id} |
view | One request |
GET /v1/certificate-requests/{id}/timeline |
view | Lifecycle history |
POST /v1/certificate-requests |
create | File a request (starts Pending) |
POST /v1/certificate-requests/preview |
create | Check a request against policy |
PUT /v1/certificate-requests/{id} |
manage | Edit a request |
DELETE /v1/certificate-requests/{id} |
manage | Delete a request |
POST /v1/certificate-requests/{id}/approve |
manage | Approve |
GET /v1/certificate-requests/{id}/approval-preview |
manage | Would approval pass policy |
POST /v1/certificate-requests/{id}/reject |
manage | Reject |
POST /v1/certificate-requests/{id}/revoke |
manage | Revoke, body { "reason": ... }
|
POST /v1/certificate-requests/{id}/renew |
create | Renew |
PUT /v1/certificate-requests/{id}/metadata |
owner or manage | Set owner team, contact, purpose and so on |
GET /v1/certificate-requests/{id}/certificate |
view | Download certificate, `format=pem |
GET /v1/certificate-requests/{id}/private-key |
owner or admin | Download the key (audited, may need step-up) |
POST /v1/certificate-requests/{id}/pfx |
owner or admin | Download a password-protected PFX (audited, may need step-up) |
POST /v1/certificate-requests/{id}/notes |
view | Add a note |
PUT /v1/certificate-requests/{id}/notes/{noteId} |
author | Edit a note |
DELETE /v1/certificate-requests/{id}/notes/{noteId} |
author | Delete a note |
GET /v1/certificate-inventory |
view | Every issued certificate with its real key, signature, chain status and expiry |
GET /v1/notices |
view | Expiry and stalled-renewal notices |
GET /v1/pqc/migration-report |
view | Post-quantum migration report |
GET /v1/dashboard/attention |
signed in | What needs attention |
GET /v1/me/access |
signed in | Your roles and permissions |
GET /v1/enrollment/options |
create | Enrollment options |
| Route | P: | Purpose |
|---|---|---|
GET /v1/certificate-templates |
view | List templates |
GET /v1/certificate-templates/{id} |
view | One template |
POST /v1/certificate-templates |
settings | Create |
PUT /v1/certificate-templates/{id} |
settings | Update |
DELETE /v1/certificate-templates/{id} |
settings | Delete |
PUT /v1/certificate-templates/{id}/issuance-policy |
policies.publish | Link a policy |
PUT /v1/certificate-templates/{id}/issuer |
settings | Choose the issuer |
PUT /v1/certificate-templates/{id}/pqc-stage |
admin | Set the post-quantum stage for one template |
GET /v1/issuance-policies |
view | List policies |
GET /v1/issuance-policies/{id} |
view | One policy |
GET /v1/issuance-policies/{id}/versions |
view | Versions |
POST /v1/issuance-policies |
settings | Create |
PUT /v1/issuance-policies/{id} |
settings | Rename |
PUT /v1/issuance-policies/{id}/draft |
settings | Replace the draft rules |
DELETE /v1/issuance-policies/{id}/draft |
settings | Discard the draft |
POST /v1/issuance-policies/{id}/publish |
policies.publish | Enforce the draft |
POST /v1/issuance-policies/{id}/archive |
settings | Archive |
POST /v1/issuance-policies/{id}/unarchive |
settings | Unarchive |
DELETE /v1/issuance-policies/{id} |
settings | Delete |
GET /v1/pqc-exceptions |
admin | List exceptions |
POST /v1/pqc-exceptions |
admin | Grant an exception |
POST /v1/pqc-exceptions/{id}/revoke |
admin | End an exception |
| Route | P: | Purpose |
|---|---|---|
GET /v1/ca/status |
signed in | CA state |
GET /v1/ca/certificate |
signed in | The CA certificate |
POST /v1/ca/generate |
settings | Generate a root CA |
POST /v1/ca/import |
settings | Import a CA |
GET /v1/issuers |
view | List issuers |
GET /v1/issuers/{id} |
view | One issuer |
GET /v1/issuers/{id}/certificate |
none | Issuer certificate, format=der for DER |
GET /v1/issuers/{id}/chain |
none | Chain to the root |
GET /v1/issuers/trust-bundle |
none | Roots of every active or retired issuer |
POST /v1/issuers/intermediates |
admin | Create an intermediate |
GET /v1/issuers/{id}/request |
admin | Request file of a pending intermediate |
POST /v1/issuers/{id}/certificate |
admin | Install the signed certificate |
POST /v1/issuers/{id}/crl |
admin | Upload an offline issuer's CRL |
POST /v1/issuers/{id}/make-default |
admin | Make the default issuer |
POST /v1/issuers/{id}/retire |
admin | Stop signing |
POST /v1/issuers/{id}/archive |
admin | Archive |
DELETE /v1/issuers/{id} |
admin | Abandon a pending intermediate |
GET /v1/issuers/{id}/private-key |
admin | Export the CA key (audited, step-up) |
POST /v1/issuers/{id}/pfx |
admin | Export a CA PFX (audited, step-up) |
POST /v1/crl/reset-base |
settings | Reset the CRL base |
| Route | P: | Purpose |
|---|---|---|
POST /v1/bulk-operations/preview |
by kind | Preview a bulk revoke or renew |
POST /v1/bulk-operations/{id}/execute |
by kind | Run a previewed operation |
POST /v1/bulk-operations/{id}/cancel |
by kind | Cancel a preview |
GET /v1/bulk-operations |
signed in | List bulk operations |
GET /v1/bulk-operations/{id} |
signed in | One operation |
GET /v1/bulk-operations/{id}/items |
signed in | Its items |
GET /v1/settings |
settings | CA settings |
PUT /v1/settings |
settings | Change settings |
PUT /v1/settings/pqc-stage |
admin | Post-quantum enforcement stage |
PUT /v1/settings/ca-approval |
admin | Who approves CA-capable requests |
PUT /v1/settings/issuer-strength |
admin | Off, Warn or Enforce: a key may not claim a higher post-quantum level than its issuer |
PUT /v1/settings/two-person-approval |
admin | Switch two-person approval |
POST /v1/approvals |
signed in | Ask a second administrator to approve |
POST /v1/approvals/{id}/approve |
signed in | Approve (a different administrator than the requester) |
POST /v1/approvals/{id}/deny |
signed in | Deny (an administrator) |
GET /v1/approvals |
signed in | List approvals |
GET /v1/permissions |
admin | Role permissions |
PUT /v1/permissions/{role} |
admin | Replace a role's permissions |
GET /v1/webhooks |
settings | List subscriptions |
POST /v1/webhooks |
settings | Create |
PUT /v1/webhooks/{id} |
settings | Update |
DELETE /v1/webhooks/{id} |
settings | Delete |
GET /v1/webhook-destinations |
admin | Allowed destinations |
GET /v1/acme/orders |
settings | ACME orders |
GET /v1/acme/external-account-keys |
settings | ACME external account bindings |
POST /v1/acme/external-account-keys |
settings | Create one (the key is shown once) |
GET /v1/est/enrollment-credentials |
settings | EST credentials |
POST /v1/est/enrollment-credentials |
settings | Create one (the password is shown once) |
GET /v1/audit-log |
admin | Audit log, newest first |
GET /v1/audit-log/checkpoint |
admin | Head of each audit hash chain |
Some groups have more routes than listed here (editing and deleting ACME and EST credentials, webhook destination rules, bulk operation details). The qca <group> --help output of the release you run lists the matching commands, and each calls exactly one of these routes.
The CRL and OCSP responder follow their own protocol formats rather than the JSON conventions above. Point relying parties at /v1/crl and /v1/ocsp on the API port, or at the CRL and OCSP URLs embedded in the certificates themselves. ACME is served under /acme/ on its own port and EST under /.well-known/est/; see Architecture.
Qertum
Deploy
Use
Operate
- Configuration Reference
- Backup and Restore
- Identity Providers
- Issuer Compromise Recovery
- Upgrading
- Troubleshooting
Releases