The Control Plane exposes a single versioned API under /api/v1. Three trust boundaries, three different credentials — never mix them.
Edge channel — Bearer <edge api_key> + tenant_id
Used by edge nodes. The API key is issued at bootstrap claim and rotated on every re-claim; the Control Plane stores only its SHA-256 hash. Every authenticated call also updates the fleet heartbeat (last_poll_at).
| Method | Path | Purpose |
|---|---|---|
POST |
/api/v1/sync/ingest |
CDC outbox drain: batched business events, idempotent on event id |
GET |
/api/v1/sync/manifest |
Latest active manifest + Ed25519 signature |
GET |
/api/v1/sync/licenses |
Plugin licenses + tenant contract license (signed) |
Errors use stable codes (LICENSE_SUSPENDED, EDGE_CAP_EXCEEDED, DRAINING…). A 503 with code: DRAINING means the node is shutting down — retry later, do not alert.
Public endpoints — no credentials
| Method | Path | Purpose |
|---|---|---|
POST |
/api/v1/bootstrap/claim |
Exchange a single-use bt_* token for tenant_id + API key. Rate-limited, atomic, rotates the tenant key |
POST |
/api/v1/waitlist |
Public waitlist signup (CORS-scoped via WAITLIST_ALLOWED_ORIGIN) |
POST |
/api/v1/webhooks/stripe |
Stripe events — signature verified byte-per-byte, deduplicated on event.id |
GET |
/api/v1/live /ready /health |
Liveness / readiness probes |
GET |
/metrics |
Prometheus exposition |
Admin — Bearer <admin-session>
Sessions come from POST /api/v1/admin/login (rate-limited, bcrypt passwords, expiry enforced). Every mutating admin call is recorded in cp_admin_audit.
| Method | Path | Purpose |
|---|---|---|
POST |
/api/v1/admin/login /logout |
Session lifecycle |
GET |
/api/v1/admin/fleet |
All tenants + edge health, contract status, heartbeat |
POST |
/api/v1/admin/tenants |
Create a tenant |
GET POST |
/api/v1/admin/tenants/:id/bootstrap-tokens |
Issue single-use provisioning tokens |
GET POST |
/api/v1/admin/tenants/:id/manifests |
Active manifest / publish a new signed version |
GET POST DELETE |
/api/v1/admin/tenants/:id/licenses |
Plugin license management (Ed25519-signed) |
GET PATCH |
/api/v1/admin/tenants/:id/subscription |
Contract state, caps, metering vs. plan |
GET |
/api/v1/admin/tenants/:id/events /aggregates |
Synced data inspection |
GET POST |
/api/v1/admin/notifications /…/:id/retry |
Email outbox inspection + dead-letter retry |
GET |
/api/v1/admin/waitlist |
Waitlist leads |
GET POST DELETE |
/api/v1/admin/users |
Multi-user admin management + self password change |
GET |
/api/v1/admin/audit |
Append-only admin action log |
Stripe webhook — Stripe-Signature verified
Handled event types: checkout.session.completed (self-service tenant provisioning + bootstrap token + welcome email), customer.subscription.* (contract state machine), invoice.paid / invoice.payment_failed (reactivation / dunning + grace). Unsigned endpoint → 503 when STRIPE_WEBHOOK_SECRET is unset — fail-closed.
Conventions
requestIdon every response for edge ↔ cloud correlation; include it in support reports.- Idempotency: ingest dedups on event
id; safe to retry any sync call. - Rate limits: global ceiling plus per-route buckets on public endpoints —
429means back off, not retry-storm.