Skip to main content
This walkthrough implements a production-grade webhook receiver for Orgo events. It covers subscription, idempotent handling, fast responses, and replay. Who is this for: any integration that needs to react to changes in Orgo in near-real-time (CRM sync, member onboarding automation, payment reconciliation, contract-signed notifications).

Available events

Eighteen event types, across six entity families. Subscribe to any subset.

Step 1 — Subscribe

Pick the events you care about and an HTTPS endpoint you control.
The secret is yours to choose — a 32-byte random string is standard. Orgo uses it to sign each delivery so you can verify the payload came from Orgo. Response includes the subscription ID — store it; you’ll need it for delivery-log lookups.

Step 2 — Receive the delivery

Each event is delivered as an HTTPS POST with a JSON body and these headers: Body shape (Stripe-inspired):
For *.updated events, previous_attributes carries the diff — fields not mentioned didn’t change. This is enough to detect specific transitions (“user just unsubscribed”, “payment just succeeded”) without comparing to a stored snapshot.

Step 3 — Be idempotent

Orgo may deliver the same event twice — retries on transient failures, network races on at-least-once delivery. Your handler must be safe to call repeatedly with the same payload. The simplest pattern: a processed_deliveries table keyed by id (the top-level event ID, e.g. wh_evt_67aa128c2f4a):
Insert the row inside the same transaction as the side effect, so a crash mid-way doesn’t leave the row inserted without the effect. If the effect is in a different system (CRM API call), insert the row only after the effect succeeds.

Step 4 — Respond fast

Orgo waits up to 30 seconds for a response before treating the delivery as failed. Long-running work (sending a follow-up email, querying a slow downstream API) should go into a background queue. The webhook handler’s job is to acknowledge receipt and durably queue the work — not perform it.
Return any 2xx; Orgo doesn’t care about the body.

Step 5 — Test before going live

The test endpoint fires a synthetic event of your chosen type to the subscription URL:
The synthetic payload uses fixture data (not real user data) but carries the same headers and shape your handler will see in production. Use it in CI to validate end-to-end delivery.

Step 6 — Replay failed deliveries

Every delivery attempt — success or failure — is logged. To list:
For each failed delivery, the response includes the original payload — you can re-process it locally without needing Orgo to re-deliver. Logs are retained for ~90 days.

Retry behavior

The subscription itself is not automatically deactivated on repeated failures — your monitoring should watch for high failure rates and either auto-pause or page on-call.

Common gotchas

Orgo doesn’t guarantee delivery order across event types. The created timestamp on each event lets you reconstruct order — sort by created before processing if order matters. For per-resource ordering (“two updates to the same user”), use previous_attributes to detect skipped transitions.
Always route by tenant_id in the payload, not by the subscription ID. If a single CRM serves multiple Orgo tenants, each tenant should create its own subscription, and your receiver should route incoming events to the right CRM tenant based on payload['tenant_id'].
Not currently — list explicit event types in the events array. The full list is in the Webhooks concept page. Subscribing to events that don’t yet exist is harmless but won’t catch new types if Orgo adds them — patch your subscription when new events ship.

What to do next