Skip to main content

API Keys

API keys provide a static credential alternative to OAuth client credentials for server-to-server access. They're appropriate when:

  • You need to call a ZewstID-integrated API from a build script, a webhook handler in a third-party platform, or any other context that can't easily complete an OAuth token exchange.
  • You want a long-lived credential without an access-token refresh loop.

OAuth Client Credentials is still the recommended path for production-grade machine-to-machine; API keys are best treated as a convenience for internal tooling and integrations that can't manage tokens.


Creating an API key

  1. Open the developer portal → API KeysCreate API Key.
  2. Choose:
    • Application — the OAuth application this key belongs to (used for usage attribution + audit logging).
    • Scopes — the permissions granted. Same scope catalog as service accounts (see Scopes).
    • Expiration — optional. Keys can be set to never expire, or to expire on a specific date.
  3. The generated key is shown once. Copy it into your secrets manager immediately — there's no way to retrieve it again.

Key format

zml_a1B2c3D4e5F6g7H8i9J0k1L2m3N4o5P6q7R8s9T0u1V2w3X4y5Z6 └┬┘ └────────────────────────────────────────────────────┘ │ random secret └─ namespace prefix (zml = "ZewstID Mail Lib", others vary by application)

The 12-character prefix is the public key identifier (logged, used for usage stats, safe to print). The remainder is the secret — treat it the same way as a password.


Using an API key

Send it in the

Authorization
header with the
Bearer
scheme, the same way you'd send an access token:

curl https://api.zewst.email/v1/messages \ -H "Authorization: Bearer zml_a1B2c3D4e5F6..."

The receiving service authenticates the key, looks up its scopes, and checks the requested action against them. Every request increments the

request_count
and updates
last_used_at
on the key record.


Rotation

API keys are designed to be rotated periodically. The recommended pattern:

  1. Create a new key with the same scopes as the old one.
  2. Deploy the new key to your application — most platforms accept either of two values during rotation, or you can do a brief overlap window.
  3. Verify the new key is being used (check
    last_used_at
    in the developer portal).
  4. Revoke the old key.

There's no automatic key rotation — schedule it as part of your security review (every 90 days is a reasonable cadence for production keys; longer is fine for low-traffic tooling).


Revocation

Hit Revoke on the key's row in the developer portal. Revocation is immediate — the next request with that key returns

401 Unauthorized
within seconds.

If you suspect a key was leaked: revoke first, audit second. Revocation is reversible only by issuing a new key, but a leaked active key is a much bigger problem than a brief outage.


Storage

Treat API keys as you would any secret:

  • Store in a secrets manager (AWS Secrets Manager, HashiCorp Vault, GitHub Actions / GitLab CI secrets, Doppler, etc.) — never in source control.
  • For local development, use
    .env
    files that are gitignored.
  • Don't log API keys, even prefixes-only. The first 12 characters are public-safe but logging discipline is hard to enforce — easier to never log them.
  • Don't pass keys in URL query strings — they end up in server logs and browser history.

API keys vs. OAuth Client Credentials — which to use

Choose API keys if…Choose Client Credentials if…
You need a single static credentialYou can refresh tokens reliably
The caller is a non-programmable integration (Zapier, n8n, a webhook handler in a third-party platform)The caller is your own production service
You want minimal moving partsYou want short-lived credentials with automatic rotation
You're prototypingYou're shipping to production

Both go through the same scope and authorization model. The difference is purely operational.


See also

Was this page helpful?

Let us know how we can improve our documentation