KMS.API exposes a minimal JSON API for backend KMS clients.
This API is an admin/backend surface. Do not expose it directly to browsers or the public internet.
Most applications should use KMS.Client.Remote instead of hand-writing HTTP calls.
Authentication
Health endpoints do not require a token.
All /api/* endpoints require:
Authorization: Bearer <KMS_API_TOKEN>If config :kms, :api has no :api_token, API routes fail closed:
{"error":"api_token_required"}Common request shape
Most POST bodies are JSON objects.
Operations that accept options use an opts object:
{
"alias": "owner:alice",
"cleartext": "secret",
"opts": {"aad": "document:123/body"}
}opts.session may carry a KMS session secret for principal-scoped authorization.
Common responses
Success returns 200 with an operation-specific JSON key.
Errors return JSON:
{"error":"not_found"}Validation errors return:
{"error":"invalid_changeset","details":{}}Common statuses:
| Status | Meaning |
|---|---|
| 200 | Success |
| 400 | Invalid JSON/body shape |
| 401 | Missing or wrong API token |
| 404 | Not found |
| 422 | Invalid changeset |
| 503 | API token missing or readiness failed |
Health
| Method | Path | Auth | Description |
|---|---|---|---|
| GET | /health | no | Cheap compatibility check. |
| GET | /health/live | no | Liveness check. |
| GET | /health/ready | no | Readiness check for DB, RMK access, and API token config. |
Encryption
| Method | Path | Body | Response |
|---|---|---|---|
| POST | /api/encrypt | alias, cleartext, opts | encrypted |
| POST | /api/decrypt | alias, encrypted, opts | cleartext or cleartexts |
| POST | /api/rmk_pdk/encrypt | cleartext, secret, opts | encrypted |
| POST | /api/rmk_pdk/decrypt | encrypted, secret, opts | cleartext |
Example:
curl -fsS \
-H "authorization: Bearer $KMS_API_TOKEN" \
-H "content-type: application/json" \
-d '{"alias":"owner:alice","cleartext":"secret","opts":{"aad":"document:123/body"}}' \
https://kms.internal.example.com/api/encrypt
KEKs
| Method | Path | Body | Response |
|---|---|---|---|
| POST | /api/keks/create | alias, opts | kek |
| POST | /api/keks/tags | alias, opts | tags |
| POST | /api/keks/aliases_by_tag | tag, opts | aliases |
| POST | /api/keks/add_tags | alias, tags, opts | tags |
| POST | /api/keks/remove_tags | alias, tags, opts | tags |
| POST | /api/keks/rewrap_for_principal | alias, target_kind, target_ref, opts | ok |
| POST | /api/keks/rewrap_for_passphrase | alias, passphrase, opts | wrapping_id |
| POST | /api/keks/revoke_passphrase | alias, wrapping_id, opts | ok |
KEK metadata includes protection: "rmk" | "session", never key material. New aliases created with opts.session are session-protected. Passphrase sharing/revocation requires the principal's active session, kek.rewrap permission, and a usable recipient envelope. See Factor-bound aliases for the complete flow and compatibility limits.
Principals
| Method | Path | Body | Response |
|---|---|---|---|
| POST | /api/principals/get | kind, ref, opts | principal |
| POST | /api/principals/list | opts | principals |
| POST | /api/principals/create | attrs, opts | principal |
| POST | /api/principals/update | kind, ref, attrs, opts | principal |
| POST | /api/principals/delete | kind, ref | principal |
When opts.session is supplied to principal creation, it must authorize principal.create against the new principal's reference/tags. Omitting it remains trusted bootstrap/admin execution; a malformed supplied session is not treated as absent.
Principal factors
| Method | Path | Body | Response |
|---|---|---|---|
| POST | /api/principal_factors/get | id | principal_factor |
| POST | /api/principal_factors/list | kind, ref | principal_factors |
| POST | /api/principal_factors/create | kind, ref, attrs | principal_factor |
| POST | /api/principal_factors/update | id, attrs | principal_factor |
| POST | /api/principal_factors/delete | id | principal_factor |
Bindings
| Method | Path | Body | Response |
|---|---|---|---|
| POST | /api/bindings/get | id | binding |
| POST | /api/bindings/list | principal_id | bindings |
| POST | /api/bindings/create | principal_id, attrs | binding |
| POST | /api/bindings/update | id, attrs | binding |
| POST | /api/bindings/delete | id | binding |
Fallback recovery
Fallback operations are absent from the compiled HTTP router. This includes public-key registry, envelope metadata, and private-key operations. Use trusted local Elixir calls or a controlled remote shell on the KMS host. See Fallback recovery.
Sessions
| Method | Path | Body | Response |
|---|---|---|---|
| POST | /api/sessions/get | secret | session |
| POST | /api/sessions/active | secret | session |
| POST | /api/sessions/list | kind, ref | sessions |
| POST | /api/sessions/create | kind, ref, attrs, opts | session |
| POST | /api/sessions/passphrase | attrs | session |
| POST | /api/sessions/advance | secret, attrs | session |
| POST | /api/sessions/nudge | secret, opts | session |
| POST | /api/sessions/delete | secret | session |
| POST | /api/sessions/delete_all | kind, ref, opts | sessions |
| POST | /api/sessions/refresh | secret, opts | session |
Session response JSON redacts bearer secrets in inspect-like contexts, but HTTP session creation returns the session secret because callers need it. Treat it like a password.
WebAuthn
| Method | Path | Body | Response |
|---|---|---|---|
| POST | /api/webauthn/registration/begin | kind, ref, opts | challenge |
| POST | /api/webauthn/registration/finish | challenge_id, response, opts | credential |
| POST | /api/webauthn/authentication/begin | kind, ref, opts | challenge |
| POST | /api/webauthn/authentication/finish | challenge_id, response, opts | session |
See WebAuthn.
Security rules
- Use TLS or trusted private networking.
- Keep API tokens high entropy.
- Do not log request or response bodies.
- Do not log bearer tokens, plaintext, ciphertext payloads, passwords, factor codes, or RMK material.
- Put authorization in your application and/or use KMS sessions/bindings.