Skip to main content
API keys authenticate requests to the /api/v1/* endpoints. Keys are scoped to a tenant and can be configured with rate limits, allowed CORS origins, and (in v1.1) per-scope restrictions.
These endpoints use dashboard (JWT) authentication, not API keys. Your Supabase session must have the api_keys:manage permission.

Issue a key

curl -X POST https://api.yotel.in/api/v1/keys \
  -H "Authorization: Bearer SUPABASE_JWT" \
  -H "Content-Type: application/json" \
  -d '{
    "label": "Production backend",
    "environment": "live",
    "rate_limit_per_min": 600
  }'
Auth: Supabase JWT + api_keys:manage  |  Status: 201 Created

Request body

FieldTypeDefaultDescription
labelstringDisplay label for the key (1–200 chars, required)
environmentstring"live""live" (production, real PSTN) or "test" (sandbox, no PSTN)
scopesarray[]Reserved for v1.1 per-scope enforcement
rate_limit_per_mininteger600Requests per minute (1–100,000)
allowed_originsarray[]CORS origin allowlist (empty = no CORS restriction)

Response

{
  "id": "key_abc123",
  "tenant_id": "tenant_xyz",
  "label": "Production backend",
  "environment": "live",
  "key": "yt_live_a1b2c3d4e5f6...",
  "key_prefix": "yt_live_",
  "last_four": "f6g7",
  "rate_limit_per_min": 600,
  "created_at": "2026-05-18T10:00:00Z"
}
The key field is shown only once. We store only a hash — if you lose the key, you’ll need to issue a new one.

List keys

Returns all keys for the tenant. The full key secret is never included.
curl https://api.yotel.in/api/v1/keys \
  -H "Authorization: Bearer SUPABASE_JWT"
Auth: Supabase JWT + api_keys:manage  |  Status: 200 OK Query parameter: include_revoked (boolean, default false) — set to true to include revoked keys.

Response fields

FieldTypeDescription
idstringKey UUID
labelstringDisplay label
environmentstring"live" or "test"
key_prefixstringKey format prefix (e.g., "yt_live_")
last_fourstringLast four characters of the key
scopesarrayConfigured scopes
rate_limit_per_minintegerRequests per minute
allowed_originsarrayCORS origins
is_activebooleanWhether the key is active (false if revoked)
last_used_atstring | nullLast time the key was used
created_atstringISO 8601
revoked_atstring | nullWhen revoked (null if active)

Rotate a key

Atomically issues a new key and revokes the old one. The response contains the new key secret (shown once).
curl -X POST https://api.yotel.in/api/v1/keys/{key_id}/rotate \
  -H "Authorization: Bearer SUPABASE_JWT" \
  -H "Content-Type: application/json" \
  -d '{
    "label": "Production backend (rotated)",
    "rate_limit_per_min": 600
  }'
Auth: Supabase JWT + api_keys:manage  |  Status: 201 Created The old key is immediately revoked — there is no grace period. Deploy the new key before rotating.

Revoke a key

Soft-revokes a key. Takes effect immediately.
curl -X DELETE https://api.yotel.in/api/v1/keys/{key_id} \
  -H "Authorization: Bearer SUPABASE_JWT" \
  -H "Content-Type: application/json" \
  -d '{"reason": "Compromised — rotated to new key"}'
Auth: Supabase JWT + api_keys:manage  |  Status: 204 No Content The optional reason field (max 500 chars) is stored for audit. If omitted, defaults to "revoked via dashboard".

Key formats

EnvironmentPrefixExample
Productionyt_live_yt_live_a1b2c3d4e5f6...
Sandboxyt_test_yt_test_x9y8z7w6v5u4...
Test keys create real database rows but do not place PSTN calls. See Environments for the full behavior difference.

Errors

StatusCondition
403Missing api_keys:manage permission
404Key not found or belongs to another tenant