Event payloads

What each event means and what it carries.

Every delivery uses the same envelope; only type and data.object differ. created is a Unix timestamp in seconds.

{ "id": "evt_9f1c2ab34d5e6f70", "object": "event", "type": "checkout.session.completed",
  "environment": "live", "installation": "3f0c…-uuid", "created": 1755423672,
  "data": { "object": { … } } }

Checkout session payload

All checkout.session.* events carry the same base object, plus a few event-specific fields.

{
  "id": "b6b1…-uuid",
  "object": "checkout.session",
  "status": "complete",
  "mode": "live",
  "amount": 2500,
  "currency": "eur",
  "reference": "cs_2f81c0",
  "metadata": { "order_id": "1042" },
  "payment_intent": "pi_3Nk91x…",
  "setup_intent": null,
  "subscription": null,
  "charge": "ch_3Nk91x…"
}
Field Meaning
id spuke checkout session ID (UUID). Your order key.
status open, complete, expired, failed, canceled.
mode live or test — same meaning as the envelope environment.
amount Total in minor units (2500 = €25.00).
currency Lowercase ISO-4217.
reference Short human-readable session reference shown to the shopper.
metadata Key/value map set when the session was created — your safest link to your own order.
payment_intent Payment reference at the processor, null for setup-only sessions.
setup_intent Set instead of payment_intent when the session only saved a payment method.
subscription Subscription ID when the session started a recurring plan.
charge Charge reference once money moved; needed to match refunds/disputes.

Event-specific extras

Event Extra fields
checkout.session.async_payment_pending payment_status: "processing", status: "open"
checkout.session.async_payment_failed failure_code, failure_message
checkout.session.canceled cancellation_reason
checkout.session.refunded amount_refunded (minor units), fully_refunded (boolean)
{ "type": "checkout.session.refunded",
  "data": { "object": { "id": "b6b1…", "object": "checkout.session", "status": "complete",
    "amount": 2500, "currency": "eur", "amount_refunded": 500, "fully_refunded": false } } }

Payment intent payloads

payment_intent.succeeded

{ "id": "pi_3Nk91x", "amount": 2500, "amount_received": 2500, "currency": "eur",
  "status": "succeeded", "customer": "cus_8f21", "latest_charge": "ch_3Nk91x",
  "payment_method_types": ["card"], "metadata": { "order_id": "1042" } }
Field Meaning
amount Amount requested, minor units.
amount_received Amount actually captured — compare both for partial captures.
status Processor status, e.g. succeeded, requires_action, canceled.
customer Processor customer reference, may be null for guest checkout.
latest_charge The charge that carries the money; use it to match refunds and disputes.
payment_method_types Methods that were allowed on this payment.
metadata Whatever the merchant/app set at creation.

payment_intent.payment_failed replaces amount_received/latest_charge with:

{ "id": "pi_3Nk91x", "amount": 2500, "currency": "eur", "status": "requires_payment_method",
  "customer": null, "failure_code": "card_declined", "decline_code": "insufficient_funds",
  "failure_message": "Your card has insufficient funds.", "metadata": {} }
Field Meaning
failure_code Coarse reason (card_declined, expired_card, …). Branch on this.
decline_code Issuer's detailed reason. Show it to the merchant, not the shopper.
failure_message Human-readable text, already customer-safe.

payment_intent.requires_action and payment_intent.canceled carry the same base fields (id, amount, currency, status, customer, metadata).


Billing payloads

invoice.payment_failed and customer.subscription.deleted carry the processor invoice/subscription object. Always read status before changing entitlements, and treat unknown fields as additive.


Delivery guarantees

At-least-once and unordered. Deduplicate on the event id; when order matters, compare created or re-fetch the object from the App API.