OpenPhn docs

Authentication

Bearer API keys, scopes, per-number restriction, rotation.

Every request carries a Bearer token:

Authorization: Bearer sk_live_<32-char-suffix>

Key format

  • Prefix: sk_live_. There is no sk_test_ / sandbox-mode key today. All keys hit production — use the verification gate and idempotency keys to iterate safely.
  • Suffix: 32 characters of URL-safe base64 (≈192 bits of entropy).
  • Stored as SHA-256: OpenPhn never persists the full key, only the hash. If you lose a key you must rotate — there's no recovery.

The first 16 characters of the key are stored plaintext to display a recognizable "prefix" in the dashboard (e.g. sk_live_AbC123...).

Creating a key

From the dashboard: Settings → API keys → Create key. You can also use the API:

curl -X POST https://api.openphn.com/auth/api_keys \
  -H "Authorization: Bearer $EXISTING_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name":       "prod-batch-caller",
    "scopes":     ["calls:create", "calls:read", "webhooks:read"],
    "number_ids": ["num_abcd1234"]
  }'

The response contains secretshown once. Save it.

Scopes

Omit scopes for an "all-permissions" key (backwards compatible). Otherwise, restrict to an explicit list:

ScopeEndpoints
calls:createPOST /v1/calls, POST /v1/calls/batch
calls:readGET /v1/calls, GET /v1/calls/{id}, CSV export
webhooks:readGET /v1/webhooks, GET .../deliveries
webhooks:writePOST /v1/webhooks, retry, delete
numbers:writePATCH /v1/numbers/{id}, SMS preview
providers:writeTwilio verify + select-number

Requests that fall outside the key's scopes return 403.

number_ids restriction

A key can be pinned to a list of numbers. Call-creation, number-config, and SMS endpoints then reject anything targeting a different number. This is useful for multi-brand setups where each product line gets its own key.

Rotation

Keys rotate without downtime:

curl -X POST https://api.openphn.com/auth/api_keys/{key_id}/rotate \
  -H "Authorization: Bearer $EXISTING_KEY"

Behavior:

  1. A new secret is returned. Deploy it.
  2. The old key keeps working for a grace period (currently 24h).
  3. Every use of the old key during the grace period is audit-logged — migrate any missed callers.
  4. After the grace period, the old key is revoked.

Session tokens (dashboard only)

POST /auth/login returns a short-lived JWT for the dashboard. These are not accepted on /v1/* endpoints — those require sk_live_*. If you see 401 "use an API key", you're sending a session token to an API route.

On this page