Webhooks
Full reference for the delivery envelope, headers, and the catalog of events Paytami can send you. For how to register an endpoint and verify the signature, see the webhooks guide.
The event envelope
Every delivery is a POST with this body:
{
"id": "evt_7c1a2b3d4e5f60718293a4b5",
"type": "payment.succeeded",
"created_at": "2026-08-28T15:10:00.000Z",
"data": { "...": "the resource matching this event type" }
}| Field | Description |
|---|---|
id | Unique event identifier, evt_ prefix. Use it to deduplicate. |
type | One of the values in the event catalog. |
created_at | ISO 8601, UTC. |
data | The affected resource, in the same shape the public API returns. |
Headers on every delivery
| Header | Description |
|---|---|
Paytami-Signature | t=<unix>,v1=<hmac_hex> — see signature verification. |
Paytami-Event-Id | Same id as the body (evt_...), to deduplicate without parsing the JSON first. |
User-Agent | Paytami-Webhooks/1.0. |
Event catalog
| Event | Fires when |
|---|---|
payment.succeeded | A charge completed successfully. |
payment.failed | A charge attempt failed. |
payment.canceled | A charge was canceled before completing. |
refund.succeeded | A refund processed successfully. |
chargeback.opened | A chargeback was opened on a payment. |
chargeback.won | A chargeback resolved in the merchant's favor. |
payout.completed | A payout landed in the merchant's bank account. |
payout.failed | A payout failed. |
You can subscribe to any subset of these events when registering your endpoint, or leave it empty to receive all of them.
payment.succeeded / payment.failed / payment.canceled
data is the same Payment object returned by GET /v1/payments/{id}:
{
"id": "pay_8f2c1a9d4e6b7c0a1d2e3f40",
"status": "captured",
"currency": "GTQ",
"amount": "15000",
"paytami_fee": "435",
"net_amount": "14565",
"checkout_url": "https://app.paytami.com/api/v1/checkout/pay_8f2c1a9d4e6b7c0a1d2e3f40",
"created_at": "2026-08-28T15:04:00.000Z"
}refund.succeeded
{
"id": "refund_4a1f0c2b3d4e5f60718293a4",
"payment_id": "pay_8f2c1a9d4e6b7c0a1d2e3f40",
"amount": "5000",
"currency": "GTQ",
"reason": "requested_by_customer",
"status": "succeeded"
}reason is one of: requested_by_customer, duplicate_charge, product_not_received, product_unacceptable, merchant_error, fraudulent, other.
chargeback.opened / chargeback.won
{
"id": "chb_9a1b2c3d4e5f60718293a4b5",
"payment_id": "pay_8f2c1a9d4e6b7c0a1d2e3f40",
"amount": "15000",
"currency": "GTQ",
"status": "opened"
}status is opened or won depending on the event. The chargeback reason isn't included: it's sensitive information handled directly between Paytami and the card issuer during the dispute process.
payout.completed / payout.failed
{
"id": "payout_c7e5b1a2d3e4f5061728394a",
"currency": "GTQ",
"amount": "142000",
"status": "completed",
"bank_account_id": "ba_2d6a9f1e2c3b4a5061728394",
"bank_account_masked": "••••4321",
"requested_at": "2026-08-27T10:00:00.000Z",
"processing_at": "2026-08-27T10:05:00.000Z",
"sent_to_bank_at": "2026-08-27T14:00:00.000Z",
"completed_at": "2026-08-28T09:00:00.000Z",
"failed_at": null,
"canceled_at": null,
"failure_reason": null
}On payout.failed, failure_reason carries the reason and completed_at stays null.

