API Reference

API authentication

API keys, scopes, and the headers every request needs.

Authentication

Kestrel uses bearer API keys over HTTPS. There are no OAuth flows and no session cookies.

curl https://api.kestrel.dev/v1/events \
  -H "Authorization: Bearer sk_live_4eC39HqLyjWDarjtT1zdp7dc"

Key types

PrefixNameCan readCan publishSafe in a browser
pk_PublishableMetadata onlyNoYes
sk_SecretEverythingYesNo
rk_RestrictedPer-scopePer-scopeNo

Test-mode keys carry an extra segment — sk_test_… — and operate on an isolated dataset. Events published with a test key are never delivered to production subscriptions.

A secret key grants full account access. If one leaks, roll it from Settings → API keys immediately; rolling takes effect within 30 seconds.

Restricted keys

Restricted keys carry an explicit scope list. Requesting an endpoint outside the scope returns 403 insufficient_scope.

scopespathstring[]required

Any of events:read, events:write, subscriptions:read, subscriptions:write, deliveries:read, deliveries:replay.

apiVersionpathstringdefault: 2026-06-01

Pins every response and every delivered payload to a version. See Migrating to v2.

expiresAtpathstring

RFC 3339 timestamp. Omit for a key that never expires. Maximum lifetime is 365 days.

Required headers

Authorizationheaderstringrequired

Bearer <key>. Basic auth is not supported.

Content-Typeheaderstringrequired

application/json on any request with a body.

Idempotency-Keyheaderstring

Optional on POST. A UUID you generate. Repeating a request with the same key inside 48 hours returns the original response instead of publishing twice.

Errors

StatusCodeMeaning
401missing_api_keyNo Authorization header.
401invalid_api_keyKey is malformed, rolled, or expired.
403insufficient_scopeRestricted key lacks the scope.
429rate_limitedSee Limits and quotas.

Errors share one envelope:

{
  "error": {
    "code": "invalid_api_key",
    "message": "The API key provided has been rolled.",
    "requestId": "req_01HZXA7C4M"
  }
}

Log requestId on every failure. Support can trace a request end-to-end from it.