API Keys
Create, scope, rotate and revoke API keys for server-to-server integrations with the ZapAPI REST API.
API keys are the primary way your backend talks to ZapAPI. They are
bearer tokens sent in the Authorization header, scoped to a project,
and prefixed by environment (zap_live_ / zap_test_).
This page covers the operational side of API keys. For the broader authentication model, see Authentication. For the endpoint-level reference, see API Keys endpoints.
Anatomy of a key
zap_live_51H7a9f3Kj2mNpQrStUvWxYz
└──┬──┘ └──┬─────────────────────────┘
│ └─ 32+ random characters (secret)
└───────── environment prefix: live | test- The prefix tells you the environment at a glance.
- The secret is shown once at creation time and stored only as a bcrypt hash on our side — we can never recover it for you.
- Keys are scoped to a single project and can carry any subset of scopes
(
invoices:write,webhooks:read, …).
Creating a key
From the dashboard: Settings → API Keys → Create key. Programmatically:
curl -X POST https://api.zapapi.com/api/v1/api-keys \
-H "Authorization: Bearer <dashboard-jwt>" \
-H "Content-Type: application/json" \
-d '{
"name": "Production backend",
"projectId": "proj_…",
"scopes": ["invoices:write", "webhooks:write"],
"expiresInDays": 90
}'Response (plaintext key shown once):
{
"data": {
"id": "key_…",
"name": "Production backend",
"prefix": "zap_live_",
"key": "zap_live_51H7a9f3Kj2mNpQrStUvWxYz",
"scopes": ["invoices:write", "webhooks:write"],
"expiresAt": "2027-01-23T00:00:00.000Z",
"createdAt": "2026-10-25T00:00:00.000Z"
}
}Listing and inspecting keys
curl https://api.zapapi.com/api/v1/api-keys?projectId=proj_… \
-H "Authorization: Bearer <dashboard-jwt>"You can see the prefix, scopes, last used at, last used IP and expiration, but never the secret itself.
Rotating keys
Rotate on a schedule (quarterly is a good default) and immediately on any suspicion of leakage:
Create the replacement
Issue a new key with the same scopes as the old one.
Deploy
Roll the new key out to your service via your secrets manager. Because keys are independent, the old key keeps working during the rollout — zero downtime.
Revoke the old key
DELETE /api/v1/api-keys/:id. Revocation is immediate; in-flight requests with
the old key will fail with 401.
Revoking a key
curl -X DELETE https://api.zapapi.com/api/v1/api-keys/key_… \
-H "Authorization: Bearer <dashboard-jwt>"Revocation is immediate and permanent. There is no "undo" — you must create a new key.
Expiration
Keys can be created with an optional expiresInDays. Expired keys return
401 Unauthorized with a key_expired code. Set a reminder a week before
expiry so you have time to rotate.
Auditing usage
Every authenticated request is logged with the key id, IP, user agent and endpoint. From the dashboard (Settings → API Keys → key → Activity) you can:
- See the last 30 days of usage per key.
- Spot keys that haven't been used in 90+ days (candidates for revocation).
- Detect unexpected IPs or user agents.
Common pitfalls
Keys in client-side code
If a key ever appears in a browser bundle, mobile app, or public repo, revoke it immediately. Treat any exposure as a compromise.
- 401 after rotation — the old key is still in an env var somewhere. Grep your infra for the old prefix.
- 403 on a new key — the key is missing a scope. Re-create with the scope (scopes cannot be edited in place).
- Keys shared across services — makes rotation painful. Use one key per service so you can rotate independently.