Outbound events

Each app reports to one URL of your product: Apps → the app → Outbound webhook.

Events

session.paida payment went through (also each paid subscription cycle)
session.failedthe payment was declined
session.expiredthe checkout expired unpaid
session.refundedthe payment was refunded
session.disputedthe customer's bank opened a chargeback; data.session.dispute says how much, why and by when to answer
session.dispute_closedthe bank decided the dispute; data.session.dispute.status is won or lost
subscription.activatedfirst payment, or recovered after past_due
subscription.reneweda later cycle was paid
subscription.updateda field changed and the status did not: the period end known after activation, the next period, a cancellation scheduled on the gateway
subscription.past_duea renewal failed; the gateway keeps retrying
subscription.cancelinga cancellation was requested; still active until cancel_at
subscription.resumeda scheduled cancellation was taken back; cancel_at is null again
subscription.canceledthe subscription ended
pingSend test event on the app page

Payload

Every delivery is the same envelope: id (the delivery, also in X-Pay-Event-Id), type, created_at, livemode (false for sandbox gateways) and data. Session events carry data.session, the object GET /api/v1/sessions/:id answers; subscription events carry data.subscription, the one GET /api/v1/subscriptions/:id answers.

session.paid
{
  "id": "0f8e2c4a-6d1b-4c3e-9a7f-2b5d8e1c4a90",
  "type": "session.paid",
  "created_at": "2026-09-25T12:00:00Z",
  "livemode": false,
  "data": {
    "session": {
      "id": "7f3a9c1e-2b4d-4e8f-9a1b-3c5d7e9f0a12",
      "status": "paid",
      "amount": "49.90",
      "refunded_amount": "0.0",
      "currency": "BRL",
      "method": "card",
      "connection_test": false,
      "subscription_id": "7f3a9c1e-2b4d-4e8f-9a1b-3c5d7e9f0a12",
      "gateway": {
        "id": "7f3a9c1e-2b4d-4e8f-9a1b-3c5d7e9f0a12",
        "name": "stripe-br",
        "provider": "stripe",
        "sandbox": true
      },
      "metadata": {
        "plan": "pro",
        "account_id": "acc_42"
      },
      "customer": {
        "id": "7f3a9c1e-2b4d-4e8f-9a1b-3c5d7e9f0a12",
        "external_ref": "user_42",
        "email": "[email protected]",
        "name": "Ana Souza",
        "document": "123.456.789-09",
        "phone": "+55 11 99999-0000",
        "address_line1": "Av. Paulista",
        "address_line2": null,
        "address_number": "1000",
        "neighborhood": "Bela Vista",
        "city": "São Paulo",
        "state": "SP",
        "zipcode": "01310-100",
        "country": "BR"
      },
      "dispute": {
        "id": "dp_1QxYz",
        "status": "needs_response",
        "reason": "fraudulent",
        "amount": "49.90",
        "due_by": "2026-09-25T12:00:00Z",
        "opened_at": "2026-09-25T12:00:00Z",
        "closed_at": "2026-09-25T12:00:00Z"
      },
      "return_to": "https://yourapp.com/billing/callback",
      "expires_at": "2026-09-25T12:00:00Z",
      "created_at": "2026-09-25T12:00:00Z",
      "updated_at": "2026-09-25T12:00:00Z"
    }
  }
}
subscription.activated
{
  "id": "0f8e2c4a-6d1b-4c3e-9a7f-2b5d8e1c4a90",
  "type": "subscription.activated",
  "created_at": "2026-09-25T12:00:00Z",
  "livemode": false,
  "data": {
    "subscription": {
      "id": "7f3a9c1e-2b4d-4e8f-9a1b-3c5d7e9f0a12",
      "status": "active",
      "amount": "49.90",
      "currency": "BRL",
      "interval": "month",
      "description": "Pro plan",
      "gateway": {
        "id": "7f3a9c1e-2b4d-4e8f-9a1b-3c5d7e9f0a12",
        "name": "stripe-br",
        "provider": "stripe",
        "sandbox": true
      },
      "customer": {
        "id": "7f3a9c1e-2b4d-4e8f-9a1b-3c5d7e9f0a12",
        "external_ref": "user_42",
        "email": "[email protected]",
        "name": "Ana Souza",
        "document": "123.456.789-09",
        "phone": "+55 11 99999-0000",
        "address_line1": "Av. Paulista",
        "address_line2": null,
        "address_number": "1000",
        "neighborhood": "Bela Vista",
        "city": "São Paulo",
        "state": "SP",
        "zipcode": "01310-100",
        "country": "BR"
      },
      "metadata": {
        "plan": "pro",
        "account_id": "acc_42"
      },
      "current_period_end": "2026-09-25T12:00:00Z",
      "cancel_at_period_end": true,
      "cancel_requested_at": "2026-09-25T12:00:00Z",
      "cancel_at": "2026-09-25T12:00:00Z",
      "replaces": "7f3a9c1e-2b4d-4e8f-9a1b-3c5d7e9f0a12",
      "canceled_at": "2026-09-25T12:00:00Z",
      "created_at": "2026-09-25T12:00:00Z",
      "links": {
        "self": "https://example.com"
      }
    }
  }
}

metadata is what your product sent to /connect, echoed back; a subscription's renewal cycles carry it too, plus description and billing_reason. customer.external_ref is your own id. The API reference describes every field.

Delivery

  1. 1Answer 2xx to accept. Anything else, including redirects, is retried with growing waits, 8 attempts in all.
  2. 2Deduplicate on X-Pay-Event-Id: a resend keeps the same id.
  3. 3Custom headers (an Authorization token your app expects, say) are set with the URL, on the app page.
  4. 4Webhooks → Sent lists every delivery with its response and a Resend button.

Next: Verify the signature

Are you sure?

Keyboard shortcuts

⌘ KSearch and navigate⌘ JOpen and close the Workbenchg hHomeg pPaymentsg cCustomersg sSubscriptionsg aAppsg gGateways?This listEscClose