Mooov Docs

Webhook event catalog

Audience: anyone receiving webhooks from Mooov. Platforms on Mooov Connect and merchants with their own webhook destination receive slightly different envelopes — both are documented here.

Signature verification, retry schedule, and dedupe guidance live in §6 of the Connect protocol and apply to both audiences unchanged: X-Mooov-Signature: t=<unix>,v1=<hex> where the HMAC-SHA256 input is <t>.<raw body>, retries on non-2xx with exponential backoff (1s, 5s, 30s, 5m, 30m, 2h, 12h), dedupe on X-Mooov-Delivery or event.id.

1. Two envelopes

Connect platforms

{
  "id": "evt_01HXX…",
  "type": "payment.succeeded",
  "created": "2026-06-10T12:34:56.000Z",
  "merchant": { "id": "merch_lodge_001", "entity_id": "mooov3" },
  "data": { … }
}

created is RFC3339 UTC with exactly three fractional-second digits. The merchant is identified by a nested merchant object — one endpoint receives events for all your connected tenants.

Merchant destinations

{
  "id": "evt_01HXX…",
  "type": "payment.captured",
  "occurred_at": "2026-06-10T12:34:56Z",
  "merchant_id": "merch_lodge_001",
  "data": { … }
}

Note the two deliberate differences: merchant webhooks use the internal event names (payment.captured) and a flat merchant_id + occurred_at, while Connect webhooks use the mapped public names (payment.succeeded) and merchant + created. The data payload is the same in both lanes.

2. Event name mapping

Merchant destinations (internal) Connect platforms (public)
payment.captured payment.succeeded
payment.failed payment.failed
payment.refunded payment.refunded
payment.partially_refunded payment.partially_refunded
payment.disputed payment.disputed
payment.authorized — (not delivered to Connect)
payment.voided — (not delivered to Connect)
subscription.activated subscription.activated
subscription.updated subscription.updated
subscription.canceled subscription.canceled
subscription.invoice_paid subscription.invoice_paid
subscription.invoice_failed subscription.invoice_failed
grant.revoked (Connect-only; fired on integrator- and operator-initiated grant revokes)

3. Payment events

All payment events share a data payload shaped like this. Fields are omitted when empty, never emitted as null:

"data": {
  "payment_id":        "pay_…",
  "state":             "captured",
  "amount":            4200,
  "currency":          "GBP",
  "metadata":          { "your_key": "your_value" },
  "customer_ref":      "mbr_…",
  "payment_method_id": "pm_…"
}
Event (public name) Fires when Extra data fields
payment.succeeded A payment is captured — synchronous server-flow confirm, async hosted-checkout completion, or a subscription cycle's invoice payment
payment.failed A charge attempt fails terminally failure_reason, failure_code, failure_category
payment.refunded The full captured amount has been refunded
payment.partially_refunded A partial refund leaves a remaining balance
payment.disputed The cardholder opened a dispute/chargeback

failure_code is the typed code your integration should branch on — e.g. insufficient_funds, card_declined, account_invalid (the merchant's PSP connection broke; see §5.2 of the Connect protocol for the repair flow).

Merchant-destination extras: payment.voided includes void_reason in data; payment.authorized fires when a delayed-capture payment authorizes. Neither is fanned out to Connect platforms.

4. Subscription events

Fired when a connected account runs Stripe Subscriptions. The five types, the dual-emit contract (each paid cycle also produces a payment.succeeded with its own refundable payment_id), and the full subscription.invoice_paid payload example are documented in §6 of the Connect protocol.

Event Fires when
subscription.activated First customer.subscription.created on the account
subscription.updated Subscription changed (excluding transitions to canceled)
subscription.canceled Subscription deleted or its status became canceled
subscription.invoice_paid A billing cycle's invoice was paid (dual-emitted with payment.succeeded)
subscription.invoice_failed A billing cycle's invoice failed (dual-emitted with payment.failed)

5. Handler checklist

Test all of this against the sandbox before going live.