Skip to content

HTTP API

Docs path: Reference / HTTP API

JSON signing routes use a per-client pairing bearer scoped to one key label. Admin routes use admin_token_file.

The machine-readable API source of truth is the committed openapi/openkms.v1.json spec. CI regenerates it from Rust code and fails when it drifts.

MethodPathAuthPurpose
GET/healthnoneHealth check and HSM probe state.
GET/keysnoneKey pool capacity summary (same as /pair/pool).
GET/pair/poolnonePool counts per chain (no addresses by default).
POST/pair/requestnoneRequest labeled or auto pairing.
GET/policypairing bearerPolicy for the paired label only.
GET/policy/{label}pairing bearer or ?request_id=Read policy (label must match token). While a pairing request is pending, poll with ?request_id=<id> (no bearer): {"status":"pending",…}. After operator approve, the next poll returns {"status":"approved","token":"okms_…","policy":{…}} once; then use the bearer on later calls.
POST/sign/solanapairing bearerSign a Solana VersionedMessage.
POST/sign/cosmospairing bearerSign a Cosmos SDK SignDoc.
GET/admin/pair/pendingadminPending pairing requests.
GET/admin/pairadminActive pairings.
GET/admin/pair/pooladminFull pool with addresses.
POST/admin/pair/{id}/approveadminApprove; returns bearer token once.
POST/admin/pair/{id}/rejectadminReject pending request.
DELETE/admin/pair/{id}adminRevoke pairing (frees allocatable slot).
GET/admin/policyadminList policies with baseline and overlay metadata.
GET/admin/keys/{label}/policyadminRead one key policy with admin metadata.
PATCH/admin/keys/{label}/policyadminPersist a partial per-key policy overlay.
DELETE/admin/keys/{label}/policyadminClear a policy overlay.
POST/admin/keys/{label}/enableadminEnable a configured key.
POST/admin/keys/{label}/disableadminDisable a configured key.
GET/metricsnonePrometheus text exposition.

Labeled request (client knows the key):

{ "client_id": "pay-laptop", "label": "solana-hot-0" }

Labeled request with client-generated bearer (recommended for laptop clients):

{
"client_id": "pay-laptop",
"label": "solana-hot-0",
"bearer": "okms_<64 hex chars>"
}

Generate on the client (okms_$(openssl rand -hex 32)), save to a mode-0600 file, then include the same string in bearer. openKMS stores only a SHA-256 hash until the operator approves. Use TLS on untrusted networks — the bearer crosses the wire in the request body.

If bearer is omitted, the server mints a token on approve (legacy path).

Auto request (assign an unused allocatable key):

{
"client_id": "pay-laptop",
"chain": "solana",
"pick": "least",
"asset": { "kind": "native" }
}

pick is most, least, or random. most/least require [pairing.balance] RPC URLs in config.

Operator approval:

Terminal window
openkms pair list
openkms pair approve <request_id>

The approve response includes bearer_source (server or client). When server, a token field is present (shown once). When client, the bearer was submitted on POST /pair/request and is not repeated — use the value already saved on the device. Server-mint pairings may also deliver the token once via GET /policy/{label}?request_id=… poll after approval. Store bearer files at mode 0600 and pass Authorization: Bearer … on /policy and /sign/*.

Terminal window
curl -sS \
-H "Authorization: Bearer $(cat openkms.token)" \
http://pi.local:9443/policy/solana-hot-0

See the OpenAPI spec for request/response schemas and admin policy overlay details.