Skip to main content
ai-cmo.dev currently exposes one inbound webhook, used by Stripe billing.

Stripe webhook

POST /api/v1/webhooks/stripe Public route. Stripe sends events to this endpoint after checkout sessions complete or expire.

Signature verification

The server verifies the Stripe signature against STRIPE_WEBHOOK_SECRET:
  1. It reads the stripe-signature header from the request.
  2. It calls stripe.webhooks.constructEvent(rawBody, signature, webhookSecret) (or the mock equivalent in local mode).
  3. If verification fails, it returns 400 invalid_signature.
The endpoint fails closed when STRIPE_WEBHOOK_SECRET is unset, returning 503 billing_unavailable.

Events handled

Idempotency

Each checkout session is fulfilled at most once. The webhook handler checks the receipt status and the credit_entries unique constraint on (workspace, idem_scope, idempotency_key). Replayed events never double-credit.

Stripe verification in local mode

When STRIPE_MOCK_SENTINEL=enabled, the server uses a deterministic mock client that verifies signatures with HMAC-SHA256 over the raw body using STRIPE_WEBHOOK_SECRET as the key. This mirrors Stripe’s verification closely enough that a tampered body or wrong secret fails identically to production.

Rate limits

The billing checkout endpoint is rate-limited to 12 requests per 60 seconds per workspace.