Outbound Webhooks & Events
Event-driven HTTPS notifications from MemberPass to your server, Zapier, or anywhere else that speaks JSON over POST.
Outbound webhooks let any HTTPS endpoint subscribe to a curated list of MemberPass events. When something happens — a subscription activates, a payment fails, a member is banned — MemberPass POSTs a signed JSON envelope to every endpoint subscribed to that event.
Lifecycle
- Create an endpoint —
POST /v1/webhook-endpointswith{name, url, events[]}. Response includes a one-timesecret. - Event fires inside MemberPass — a creator or subscriber action triggers a domain event.
- Fan-out —
WebhookDispatcherlooks up every active endpoint subscribed to the event within the firing team / project and queues aDeliverWebhookJobper endpoint on the Horizonwebhooksqueue. - Delivery — the job POSTs the signed payload.
2xxresponse →delivered.non-2xxor timeout → retry with exponential backoff. - Retry curve — up to 8 attempts over roughly four days:
10s, 30s, 2m, 10m, 1h, 6h, 24h, 72h. - Dead letter — on the eighth failure the delivery is marked
dead. After 20 consecutive failures the endpoint auto-disables until the creator re-enables it.
What lives in every payload
{
"id": "evt_01HX...",
"type": "subscription.created",
"created_at": "2026-05-18T10:05:00Z",
"api_version": "2026-05-01",
"project_id": "prj_...",
"data": { "...event-specific..." }
}id— ULID, unique per delivery. Use it for consumer-side idempotency.type— matches one of the catalog entries.created_at— ISO8601 server time; not the arrival time at your endpoint.api_version— locks the event shape. Breaking-change events will ship under a new version.project_id— null for team-scoped events (e.g.,billing.*).data— event-specific payload.
What lives in every request header
Content-Type: application/jsonUser-Agent: MemberPass-Webhooks/<version>MP-Signature: t=<unix>,v1=<hex>— HMAC-SHA256 over"<t>.<raw_body>". See signature verification.MP-Event-Id: <ulid>— mirrorspayload.idMP-Event-Name: <type>— mirrorspayload.type
Reject any request where |now - t| > 300. The 5-minute tolerance window is the replay-attack
defence. It's the consumer's job to enforce it; MemberPass enforces it in the verify helper for
parity.
Ordering guarantees
- Deliveries are not strictly ordered. A
subscription.expiredmay arrive before its precedingsubscription.cancelledunder retry. - Consumers should be idempotent on
event_idand accept out-of-order delivery. Use the most recent event per resource when reconciling state.
Where to go next
How is this guide?