Events & payloads
The envelope
Every webhook is the same JSON envelope. The event-specific data is in data:
{
"id": "0191...e7",
"tenant_id": "550e8400-e29b-41d4-a716-446655440000",
"event_type": "order.paid",
"created_at": "2026-06-10T14:30:45.123Z",
"data": { "order_id": "0191...a1" }
}| Field | Meaning |
|---|---|
id | The delivery id (UUID). Matches the X-Orchard-Delivery header. Your idempotency key. |
tenant_id | Your tenant. |
event_type | One of the events below. Matches the X-Orchard-Event header. |
created_at | ISO-8601 timestamp the envelope was built. |
data | Event-specific payload (see each event below). |
Headers
Every POST carries:
| Header | Value |
|---|---|
Content-Type | application/json |
X-Orchard-Event | the event_type |
X-Orchard-Delivery | the delivery id (idempotency key) |
X-Orchard-Signature | t=<unix_seconds>,v1=<hex_hmac> — see Verifying signatures |
Event catalog
Payloads are intentionally thin — they identify the entity; fetch the full object from the API when you need detail. All ids are UUIDs unless noted.
| Event | When | data |
|---|---|---|
order.paid | An order’s payment is captured | { order_id } |
order.refunded | A refund is recorded against an order | { order_id, refund_id, amount_cents, currency } |
subscription.created | A subscription is created | { stripe_subscription_id, status } |
subscription.updated | A subscription changes (plan, status, pause, period) | { stripe_subscription_id, status } |
subscription.canceled | A subscription is canceled | { stripe_subscription_id, status } |
webhook.ping | You clicked Test in the admin | { message, endpoint_id, sent_at } |
Notes
amount_centsis an integer in the smallest currency unit (e.g.4200= $42.00);currencyis a lowercase ISO code (e.g."usd").- Subscription events key on
stripe_subscription_id(sub_…) and carry the currentstatus(active,past_due,paused,canceled, …). Treat them as a state snapshot — act on the latest, not on event ordering. order.canceledis a reserved event type but is not currently emitted (there is no cancellation trigger wired yet). Don’t rely on receiving it.
Fetching detail
A thin payload gives you the id; resolve the rest through the API. For example,
after order.paid:
curl https://api.theorchard.dev/api/v1/orders/<order_id> \
-H "Authorization: Bearer sk_live_your_key"See the API Reference for the order, refund, and subscription shapes.