ShiftxPay
Webhooks

Event catalog

Every event you can subscribe to.

An event is emitted when a payment changes state and then fanned out to every active endpoint that subscribed to that event type. The catalog of subscribable types is served by the API, so it is always authoritative:

curl https://api.lite.shiftxpay.com/v1/merchants/me/event-types \
  -H "Authorization: Bearer $SHIFTXPAY_API_KEY"
{
  "data": [
    { "code": "payment.succeeded", "label": "Payment Succeeded", "category": "payment" },
    { "code": "payment.refunded",  "label": "Payment Refunded",  "category": "payment" }
  ]
}

Events the gateway emits today

EventFires when
payment.succeededA payment reaches a terminal authorized/captured state — on synchronous confirm and again from the PSP's signed webhook (Peach).
payment.failedThe PSP reports the charge failed.
payment.refundedA refund is created or settles. status reflects the new payment state (refunded or partially_refunded).
payment.disputedThe PSP opens a dispute / chargeback against a payment.
test.pingYou pressed Test on an endpoint (POST /v1/merchants/me/webhooks/{id}/test). Carries no payment.

The full catalog returned by GET /v1/merchants/me/event-types may list additional payment.* and dispute.* codes that are reserved for future use. Subscribe to them if you like, but only the events in the table above are delivered by the current gateway.

Payload shape

Payment events share one compact shape. Amounts and other payment detail are not inlined — treat the webhook as a signal and fetch the authoritative record with GET /v1/payments/{id} using the payment_id.

payment.succeeded

{
  "type": "payment.succeeded",
  "payment_id": "pay_3kP9c2Xa...",
  "status": "succeeded"
}

payment.refunded

{
  "type": "payment.refunded",
  "payment_id": "pay_3kP9c2Xa...",
  "status": "refunded"
}

payment.failed and payment.disputed follow the same three fields, with status carrying failed and the disputed payment's status respectively.

The type field always equals the ShiftxPay-Event header, so you can branch on either. The body is the exact byte sequence the signature is computed over — see Outbound webhooks.

Monetary values, wherever they appear in the API, are integer minor units (e.g. 1050 is Rs 10.50). Never parse them as decimals.

On this page