echorelay.dev

Project API keys

Lifecycle: mint, rotate, revoke

Inbound caller authentication is project-level: one key works on every endpoint in the project. Each key carries a mode (live or test) — that picks the credit pool.

Mint

Plaintext is shown exactly once at creation. Store it before the next call.

POST https://api.echorelay.dev/keys
{ "name": "Production webhook", "mode": "live", "ttlDays": 90 }

Rotate

Mints a linked successor immediately. The predecessor stays valid until its own expiresAt — use Revoke to kill it instantly. Manual rotation returns the new plaintext in the response; you cannot recover it later.

POST https://api.echorelay.dev/keys/<KEY_ID>/rotate

Revoke (hard kill)

No grace period — the next caller request gets a 401 key_revoked.

DELETE https://api.echorelay.dev/keys/<KEY_ID>

Auto-rotation

A scheduler runs daily. Seven days before expiresAt, it mints a linked successor and stores the new plaintext encrypted-at-rest. You reveal it exactly once:

POST https://api.echorelay.dev/keys/<PREDECESSOR_ID>/reveal-successor

Second call returns 410 Gone. If you miss the window, manually rotate the live key.

After expiresAt, the predecessor gets a 24-hour grace window — Framework accepts the request and sets X-Echorelay-Key-Status: expired_grace plus X-Echorelay-Key-Successor-Available: true if a usable successor exists. After the 24 h, it returns 401 key_expired.

Status code summary

CodeReasonHeaders
200accepted, active
200accepted, in graceX-Echorelay-Key-Status: expired_grace
401key_revoked
401key_expired
404unknown key (or no key against a non-public tenant)

Policy

Owner-only project settings that constrain what editors may mint:

  • defaultKeyTtlDays — default lifetime applied to new keys (null = no default expiry)
  • maxKeyTtlDays — hard cap for editors (owners ignore the cap)
  • editorsMayCreateNonExpiringKeys — when false, editors cannot mint a key without an expiry

← Docs index