Authentication

How API keys work, key lifecycle, and rate limits.

Every Public API endpoint requires a Bearer key in the Authorization header:

Authorization: Bearer ck_live_a1b2c3d4...

Key format

Keys look like:

ck_live_<32 hex characters>
  • 128 bits of entropy. Effectively unguessable.
  • The 8 hex chars right after ck_live_ are stored plaintext (the "prefix") so Coachbot can look up the key cheaply on every request.
  • The full key is hashed with SHA-256 for storage. Coachbot compares hashes in constant time.

Key lifecycle

  • Create — Settings → API keys → New API key. Give it an operator-friendly name (e.g. production-site). Coachbot returns the plaintext key exactly once in a one-time-reveal panel. Copy it immediately into your secrets manager. There is no way to recover it later.
  • Use — pass it as Authorization: Bearer <key> from your backend.
  • Monitor — Settings → API keys shows when each key was last used. If a key has been silent for weeks but you expect traffic, the key was probably leaked + rotated by someone else, or your client is misconfigured.
  • Revoke — click Revoke on the row. Soft delete (revoked_at stamp). Subsequent calls with that key get 401 invalid_or_revoked.

Best practices

  • One key per environment. Production, staging, the partner's website — each gets its own key. Easier to revoke without affecting the others.
  • Never embed in client JS. The key would be visible to anyone with browser devtools. Use a server-side proxy.
  • Rotate periodically. Generate a new key, deploy with the new key, revoke the old one. Coachbot doesn't enforce a rotation interval — it's your policy.
  • Don't share between operators. Each operator on your team should have their own way to read keys from your secrets manager, not paste them in Slack.

Rate limits

Per-key limits, currently:

WindowLimitWhat it stops
60 seconds5 requestsRunaway scripts, double-submitted forms.
60 minutes100 requestsSustained abuse, accidental loops.

Exceeding either returns 429 rate_limit_exceeded with a Retry-After header. Both windows are keyed on the api_key_id, not the workspace, so multiple keys for the same workspace each get their own budget.

If you legitimately need higher limits, file an issue — these defaults err on the side of safety.

Statuserror valueMeans
401"Missing Authorization header."No Authorization header at all.
401"Authorization header must use the `Bearer <api key>` scheme."Header present but not Bearer-formatted.
401"API key is invalid or revoked."Bearer present but the key isn't recognised or has been revoked.
429"Rate limit exceeded. Wait a minute before retrying."Per-minute burst limit.
429"Hourly rate limit exceeded."Per-hour limit.