Skip to main content
Webhooks notify your application when events happen in your account. When an event occurs, we send an HTTP POST request to each configured endpoint with a JSON payload describing the event.

Payload Structure

Every webhook event follows this structure:
{
  "id": "evt_1abc2def3ghi",
  "object": "event",
  "type": "payment_intent.succeeded",
  "created": 1709942400,
  "livemode": false,
  "data": {
    "object": { }
  }
}

Verifying Webhook Signatures

Every webhook request includes an X-Signature header that you should use to verify the payload originated from our servers. The header format is:
X-Signature: t=<timestamp>,v1=<signature>
The signature is computed as:
HMAC-SHA256(webhook_secret, "v1=" + timestamp + "." + payload)
Where:
  • webhook_secret is the signing secret from your webhook endpoint configuration.
  • timestamp is the Unix timestamp from the t= portion of the header.
  • payload is the raw JSON request body.

Verification Example

import hmac
import hashlib

def verify_signature(payload: bytes, header: str, secret: str) -> bool:
    parts = dict(item.split("=", 1) for item in header.split(","))
    timestamp = parts["t"]
    expected_sig = parts["v1"]

    signed_payload = f"v1={timestamp}.{payload.decode('utf-8')}"
    computed_sig = hmac.new(
        secret.encode("utf-8"),
        signed_payload.encode("utf-8"),
        hashlib.sha256
    ).hexdigest()

    return hmac.compare_digest(computed_sig, expected_sig)
Always verify webhook signatures before processing the event. Reject any request where the signature does not match.

Payment Intent Events

payment_intent.created

Occurs when a new PaymentIntent is created.
{
  "id": "evt_1abc2def3ghi",
  "object": "event",
  "type": "payment_intent.created",
  "created": 1709942400,
  "livemode": false,
  "data": {
    "object": {
      "id": "pi_3abc4def5ghi",
      "object": "payment_intent",
      "amount": 2000,
      "currency": "usd",
      "status": "requires_payment_method",
      "customer": "cus_9abc0def1ghi",
      "description": "Order #1234",
      "metadata": {},
      "created": 1709942400,
      "livemode": false
    }
  }
}

payment_intent.succeeded

Occurs when a PaymentIntent completes successfully and the payment is confirmed.
{
  "id": "evt_2bcd3efg4hij",
  "object": "event",
  "type": "payment_intent.succeeded",
  "created": 1709942460,
  "livemode": false,
  "data": {
    "object": {
      "id": "pi_3abc4def5ghi",
      "object": "payment_intent",
      "amount": 2000,
      "currency": "usd",
      "status": "succeeded",
      "customer": "cus_9abc0def1ghi",
      "payment_method": "pm_card_visa",
      "description": "Order #1234",
      "metadata": {},
      "created": 1709942400,
      "livemode": false
    }
  }
}

payment_intent.payment_failed

Occurs when a payment attempt on a PaymentIntent fails.
{
  "id": "evt_3cde4fgh5ijk",
  "object": "event",
  "type": "payment_intent.payment_failed",
  "created": 1709942520,
  "livemode": false,
  "data": {
    "object": {
      "id": "pi_3abc4def5ghi",
      "object": "payment_intent",
      "amount": 2000,
      "currency": "usd",
      "status": "requires_payment_method",
      "customer": "cus_9abc0def1ghi",
      "last_payment_error": {
        "type": "payment_error",
        "code": "card_declined",
        "message": "Your card was declined."
      },
      "metadata": {},
      "created": 1709942400,
      "livemode": false
    }
  }
}

payment_intent.canceled

Occurs when a PaymentIntent is canceled.
{
  "id": "evt_4def5ghi6jkl",
  "object": "event",
  "type": "payment_intent.canceled",
  "created": 1709942580,
  "livemode": false,
  "data": {
    "object": {
      "id": "pi_3abc4def5ghi",
      "object": "payment_intent",
      "amount": 2000,
      "currency": "usd",
      "status": "canceled",
      "cancellation_reason": "requested_by_customer",
      "customer": "cus_9abc0def1ghi",
      "metadata": {},
      "created": 1709942400,
      "livemode": false
    }
  }
}

payment_intent.requires_action

Occurs when a PaymentIntent requires additional action such as 3D Secure authentication.
{
  "id": "evt_5efg6hij7klm",
  "object": "event",
  "type": "payment_intent.requires_action",
  "created": 1709942640,
  "livemode": false,
  "data": {
    "object": {
      "id": "pi_3abc4def5ghi",
      "object": "payment_intent",
      "amount": 2000,
      "currency": "usd",
      "status": "requires_action",
      "customer": "cus_9abc0def1ghi",
      "next_action": {
        "type": "redirect_to_url",
        "redirect_to_url": {
          "url": "https://hooks.example.com/3ds/authenticate?pi=pi_3abc4def5ghi",
          "return_url": "https://shop.example.com/order/complete"
        }
      },
      "metadata": {},
      "created": 1709942400,
      "livemode": false
    }
  }
}

Charge Events

charge.succeeded

Occurs when a charge succeeds.
{
  "id": "evt_6fgh7ijk8lmn",
  "object": "event",
  "type": "charge.succeeded",
  "created": 1709942700,
  "livemode": false,
  "data": {
    "object": {
      "id": "ch_1abc2def3ghi",
      "object": "charge",
      "amount": 2000,
      "currency": "usd",
      "status": "succeeded",
      "paid": true,
      "payment_intent": "pi_3abc4def5ghi",
      "customer": "cus_9abc0def1ghi",
      "payment_method": "pm_card_visa",
      "created": 1709942700,
      "livemode": false
    }
  }
}

charge.failed

Occurs when a charge attempt fails.
{
  "id": "evt_7ghi8jkl9mno",
  "object": "event",
  "type": "charge.failed",
  "created": 1709942760,
  "livemode": false,
  "data": {
    "object": {
      "id": "ch_2bcd3efg4hij",
      "object": "charge",
      "amount": 2000,
      "currency": "usd",
      "status": "failed",
      "paid": false,
      "failure_code": "card_declined",
      "failure_message": "Your card was declined.",
      "payment_intent": "pi_3abc4def5ghi",
      "customer": "cus_9abc0def1ghi",
      "created": 1709942760,
      "livemode": false
    }
  }
}

charge.refunded

Occurs when a charge is fully or partially refunded.
{
  "id": "evt_8hij9klm0nop",
  "object": "event",
  "type": "charge.refunded",
  "created": 1709942820,
  "livemode": false,
  "data": {
    "object": {
      "id": "ch_1abc2def3ghi",
      "object": "charge",
      "amount": 2000,
      "amount_refunded": 2000,
      "currency": "usd",
      "status": "succeeded",
      "refunded": true,
      "payment_intent": "pi_3abc4def5ghi",
      "customer": "cus_9abc0def1ghi",
      "created": 1709942700,
      "livemode": false
    }
  }
}

Customer Events

customer.created

Occurs when a new customer is created.
{
  "id": "evt_9ijk0lmn1opq",
  "object": "event",
  "type": "customer.created",
  "created": 1709942880,
  "livemode": false,
  "data": {
    "object": {
      "id": "cus_9abc0def1ghi",
      "object": "customer",
      "name": "Jane Doe",
      "email": "jane@example.com",
      "phone": null,
      "description": null,
      "metadata": {},
      "created": 1709942880,
      "livemode": false
    }
  }
}

customer.updated

Occurs when a customer record is updated.
{
  "id": "evt_0jkl1mno2pqr",
  "object": "event",
  "type": "customer.updated",
  "created": 1709942940,
  "livemode": false,
  "data": {
    "object": {
      "id": "cus_9abc0def1ghi",
      "object": "customer",
      "name": "Jane Doe",
      "email": "jane.doe@example.com",
      "phone": "+15551234567",
      "description": "Updated customer",
      "metadata": {
        "tier": "premium"
      },
      "created": 1709942880,
      "livemode": false
    }
  }
}

Refund Events

refund.created

Occurs when a refund is created.
{
  "id": "evt_1klm2nop3qrs",
  "object": "event",
  "type": "refund.created",
  "created": 1709943000,
  "livemode": false,
  "data": {
    "object": {
      "id": "re_1abc2def3ghi",
      "object": "refund",
      "amount": 1000,
      "currency": "usd",
      "status": "pending",
      "payment_intent": "pi_3abc4def5ghi",
      "charge": "ch_1abc2def3ghi",
      "reason": "requested_by_customer",
      "metadata": {},
      "created": 1709943000
    }
  }
}

refund.updated

Occurs when a refund’s status changes (e.g., from pending to succeeded or failed).
{
  "id": "evt_2lmn3opq4rst",
  "object": "event",
  "type": "refund.updated",
  "created": 1709943060,
  "livemode": false,
  "data": {
    "object": {
      "id": "re_1abc2def3ghi",
      "object": "refund",
      "amount": 1000,
      "currency": "usd",
      "status": "succeeded",
      "payment_intent": "pi_3abc4def5ghi",
      "charge": "ch_1abc2def3ghi",
      "reason": "requested_by_customer",
      "metadata": {},
      "created": 1709943000
    }
  }
}

Dispute Events

dispute.created

Occurs when a customer disputes a charge (chargeback).
{
  "id": "evt_3mno4pqr5stu",
  "object": "event",
  "type": "dispute.created",
  "created": 1709943120,
  "livemode": false,
  "data": {
    "object": {
      "id": "dp_1abc2def3ghi",
      "object": "dispute",
      "amount": 2000,
      "currency": "usd",
      "status": "needs_response",
      "charge": "ch_1abc2def3ghi",
      "payment_intent": "pi_3abc4def5ghi",
      "reason": "fraudulent",
      "evidence_due_by": 1710547200,
      "created": 1709943120,
      "livemode": false
    }
  }
}

Best Practices

Verify signatures

Always verify the X-Signature header before processing any webhook event.

Return 2xx quickly

Respond with a 200 status code within 5 seconds. Process events asynchronously if needed.

Handle duplicates

Use the event id to deduplicate. We may send the same event more than once.

Use event type filtering

Only subscribe to the event types you need to reduce unnecessary traffic.