ZapAPI Docs
Get StartedConceptsAI GatewayGuidesPayment GatewaySDKAPI ReferenceResources

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.

On this page