Docs / Developers

Inbound webhooks

Stripe today; Tyro reserved. Signature-verified, idempotent, per-tenant.

halopos has exactly one inbound webhook surface today:

POST /api/billing/stripe-webhook

Policy

  • Raw body ingress — the Stripe SDK computes an HMAC over the body,

which doesn't survive JSON parsing.

  • Stripe-Signature header verified against

HALOPOS_STRIPE_WEBHOOK_SECRET (webhooks.constructEvent).

  • Poison events return 4xx so Stripe stops retrying.
  • Transient errors return 5xx; our applier is idempotent so retries

are safe.

Tenant resolution

We stash tenantId in the subscription's metadata at checkout time. The webhook handler reads it from the subscription payload, never from a JOIN.

See docs/architecture/api/inbound-webhooks.md in-repo for the canonical contract.