API Keys
API keys are how every server-to-server Demo Pay request authenticates. This page is for dashboard/admin users managing keys for their account — if you just need to use a key, see Getting Started.
#Key format
dm_live_<24-byte-base64url> ← production
dm_test_<24-byte-base64url> ← sandbox / test- The cleartext is shown exactly once, at issuance time.
- Server-side we keep only the SHA-256 fingerprint and a 12-character prefix (e.g.
dm_live_xyz) for display in the dashboard. - Lost a key? You can't recover it — rotate to issue a new one.
#Auth — these endpoints use JWT, not apikey
All /v1/api-keys/* endpoints are JWT-authenticated (the same dashboard login token returned by POST /v1/auth/login). They are not gated by Kong's apikey plugin — that would be a chicken-and-egg.
Authorization: Bearer <dashboard JWT>The JWT's account claim scopes every operation — you can only manage your own account's keys.
#Endpoints
#Issue a key
POST /v1/api-keyscurl -X POST https://demo.zentry.cloud/v1/api-keys \
-H "Authorization: Bearer $JWT" \
-H "Content-Type: application/json" \
-d '{ "label": "production-backend", "test": false }'| Field | Type | Required | Description |
|---|---|---|---|
label | string | no | Free-form, ≤ 64 chars. Shown in dashboard for humans. |
test | boolean | no | true issues a dm_test_… key. Default false. |
Response 201 Created
{
"id": "5b3a9c1d-...",
"apiKey": "dm_live_F8A2K7M3N9PQRSTUVWXYZAB",
"fingerprint": "9a3f7e1c5d8b2a40",
"prefix": "dm_live_F8A",
"label": "production-backend",
"createdAt": "2026-04-25T18:32:11.000Z"
}
apiKeyis shown only here. Store it in a secret manager immediately. The dashboard does not display it on subsequent loads.
#List your keys
GET /v1/api-keysReturns metadata only — no cleartext.
{
"data": [
{
"id": "5b3a9c1d-...",
"prefix": "dm_live_F8A",
"label": "production-backend",
"createdAt": "2026-04-25T18:32:11.000Z"
},
{
"id": "7f1c4e9a-...",
"prefix": "dm_test_QRX",
"label": "ci-tests",
"createdAt": "2026-04-12T09:14:08.000Z"
}
]
}#Rotate a key
POST /v1/api-keys/{id}/rotateAtomically revokes the named key and issues a fresh one. Use this on a regular cadence (every 90 days is reasonable) or whenever you suspect compromise.
curl -X POST https://demo.zentry.cloud/v1/api-keys/5b3a9c1d-.../rotate \
-H "Authorization: Bearer $JWT" \
-H "Content-Type: application/json" \
-d '{ "label": "production-backend (rotated 2026-04-25)" }'Response shape is identical to Issue a key — including the new cleartext.
Operational note: the old key stops working the moment this call completes. Deploy the new key to your servers BEFORE calling rotate, or schedule a brief overlap by issuing a parallel key first and revoking the old one once the new one is in place.
#Revoke a key
DELETE /v1/api-keys/{id}Permanent — there is no undo.
curl -X DELETE https://demo.zentry.cloud/v1/api-keys/5b3a9c1d-... \
-H "Authorization: Bearer $JWT"Response 200 OK
{ "revoked": true }#Security checklist
- Treat
dm_live_…like a password — never commit, never log, never paste into Slack. - Store in a secret manager (1Password, Vault, AWS Secrets Manager, GitHub Actions secrets, etc.).
- Different keys per environment (
dm_live_…for prod,dm_test_…for staging/CI). - One key per service / one key per developer machine — easier to revoke a single key when something leaks.
- Rotate on a schedule. Quarterly minimum; monthly for high-sensitivity workloads.
- Revoke immediately when an employee leaves.
- Set up alerting on the dashboard's "key issued" / "key rotated" audit events.
#What's stored where
| Storage | What's there |
|---|---|
Kong (key-auth plugin) | The cleartext key — used to authenticate inbound requests. |
| Demo Pay database (merchant record) | kongConsumerUsername — the merchant slug, for reverse lookup. Never the cleartext. |
| Audit log | Issue / rotate / revoke events, with the issuing user's id and the key's fingerprint. |
| Dashboard | Prefix + label only. |
#CLI alternative
For ops/onboarding from a workstation, the same operations are available through an internal provisioning CLI (ops-only tooling; not part of the public API or SDK). The CLI talks to the Kong Admin API directly, and keys it issues are interchangeable with HTTP-issued keys.
#FAQ
Q: Can I have multiple live keys at once? A: Yes — useful for zero-downtime rotation and per-service isolation. No hard limit.
Q: I lost the cleartext immediately after creation. A: It's gone. Rotate (or revoke + re-issue) — there is no recovery path by design.
Q: How do I tell which key is making which request?
A: The dashboard's request logs show the key fingerprint on every call. Filter by apiKeyFingerprint to attribute traffic.
Q: Can I restrict a key to certain endpoints / methods? A: Not yet. Per-key scopes are on the Phase 2 roadmap. Today, every key has full account access.