Webhooks
Crypto2Pay sends webhook notifications to your server when transaction statuses change. You provide the webhook URL when creating a charge or payment.
How It Works
- A transaction status changes (e.g., charge is paid)
- Crypto2Pay sends a
POSTrequest to your webhook URL - Your server must respond with 200 OK within 5 seconds
- If your server doesn't respond in time, we retry automatically
Retry Policy
| Attempt | Delay |
|---|---|
| 1st retry | 1 minute |
| 2nd retry | 5 minutes |
| 3rd retry | 15 minutes |
| 4th retry | 1 hour |
| 5th retry | 6 hours |
After 5 failed retries, the webhook is abandoned.
Cash-In Events
| Status | Description |
|---|---|
1 | Charge paid |
3 | Charge expired |
4 | Charge refunded |
Paid Payload Example (status 1)
{
"id": 59276,
"transaction_id": "12345678933",
"type": "transaction",
"method": "pix",
"status": 1,
"currency": "BRL",
"amount": 145,
"name": "John Doe",
"document_number": "12345678900",
"email": "john@example.com",
"phone_number": "5547999999999",
"payer": {
"name": "John Doe",
"document_number": "12345678900",
"bank_name": "NU PAGAMENTOS - IP",
"ispb": "18236120"
},
"e2eId": "E20018183202603051309eFsMqKfpFkv",
"first_deposit": true,
"created_at": "2026-11-26T15:02:55.000Z",
"paid_at": "2026-11-26T15:10:16.000Z"
}
Expired Payload Example (status 3)
{
"id": 59301,
"transaction_id": "12345678950",
"type": "transaction",
"method": "pix",
"status": 3,
"currency": "BRL",
"amount": 250,
"name": "Ana Oliveira",
"document_number": "98765432100",
"email": "ana@example.com",
"phone_number": "5511977778888",
"payer": null,
"e2eId": null,
"first_deposit": false,
"created_at": "2026-11-27T08:30:00.000Z",
"paid_at": null
}
Refunded Payload Example (status 4)
{
"id": 59276,
"transaction_id": "12345678933",
"type": "transaction",
"method": "pix",
"status": 4,
"currency": "BRL",
"amount": 145,
"name": "John Doe",
"document_number": "12345678900",
"email": "john@example.com",
"phone_number": "5547999999999",
"payer": {
"name": "John Doe",
"document_number": "12345678900",
"bank_name": "NU PAGAMENTOS - IP",
"ispb": "18236120"
},
"e2eId": "E20018183202603051309eFsMqKfpFkv",
"first_deposit": true,
"created_at": "2026-11-26T15:02:55.000Z",
"paid_at": "2026-11-26T15:10:16.000Z"
}
Cash-In Specific Fields
| Field | Description |
|---|---|
type | Always "transaction" |
method | Always "pix" |
payer.name | Name of the payer |
payer.document_number | CPF/CNPJ of the payer |
payer.bank_name | Name of the payer's bank |
payer.ispb | ISPB code of the payer's bank |
e2eId | End-to-end identifier from the Pix transaction |
first_deposit | Whether this is the payer's first deposit |
Cash-Out Events
| Status | Description |
|---|---|
1 | Payment approved/completed |
2 | Payment rejected |
3 | Payment reversed (by customer or bank) |
Approved Payload Example (status 1)
{
"id": 685,
"transaction_id": "12345678911",
"type": "withdrawal",
"method": "payout_pix",
"status": 1,
"currency": "BRL",
"amount": 300,
"name": "John Doe",
"document_number": "12345678900",
"email": "john@example.com",
"phone_number": "5547999999999",
"manual_withdrawal": false,
"cancel_reason": null,
"cancel_details": null,
"created_at": "2026-12-01T14:48:03.000Z",
"paid_at": "2026-12-01T14:48:08.000Z"
}
Rejected Payload Example (status 2)
{
"id": 702,
"transaction_id": "f4a2b8c1-9d3e-4f5a-b6c7-d8e9f0a1b2c3",
"type": "withdrawal",
"method": "payout_pix",
"status": 2,
"currency": "BRL",
"amount": 500,
"name": "Carlos Mendes",
"document_number": "98765432100",
"email": "carlos@example.com",
"phone_number": "5511988887777",
"manual_withdrawal": false,
"cancel_reason": "ACCOUNT_CLOSED",
"cancel_details": "Beneficiary account is closed or inactive at the receiving institution.",
"created_at": "2026-12-03T09:22:10.000Z",
"paid_at": null
}
Reversed Payload Example (status 3)
{
"id": 718,
"transaction_id": "b7c8d9e0-f1a2-3b4c-5d6e-7f8a9b0c1d2e",
"type": "withdrawal",
"method": "payout_pix",
"status": 3,
"currency": "BRL",
"amount": 1200,
"name": "Fernanda Lima",
"document_number": "11223344556",
"email": "fernanda@example.com",
"phone_number": "5521966665555",
"manual_withdrawal": false,
"cancel_reason": "REVERSED",
"cancel_details": "Payment was completed but subsequently reversed by the customer or receiving institution.",
"created_at": "2026-12-05T11:15:42.000Z",
"paid_at": "2026-12-05T11:15:50.000Z"
}
Cash-Out Specific Fields
| Field | Description |
|---|---|
type | Always "withdrawal" |
method | Always "payout_pix" |
manual_withdrawal | Whether the withdrawal was processed manually |
cancel_reason | Reason for cancellation, if applicable |
cancel_details | Additional cancellation details, if applicable |
Security Recommendations
- Validate the origin — Check the request source IP
- Validate the data — Verify amounts and statuses match your records
- Idempotency — Handle duplicate webhooks gracefully (use
transaction_idas a key) - Confirm critical events — For important status changes, query the API directly to confirm before taking action
Confirming a Cash-In event
After receiving a webhook for a paid charge, verify with the API before crediting the user:
curl -X GET "https://api-pix.crypto2pay.app/v2/transactions?transaction_id=12345678933" \
-H "Authorization: YOUR_API_KEY"
Check that status is 1 (Paid) and amount matches your records before proceeding.
Confirming a Cash-Out event
After receiving a webhook for an approved payout, verify with the API before updating your ledger:
curl -X GET "https://api-pix.crypto2pay.app/v2/withdrawals?transaction_id=9233a90c-1b2a-4c3d-8e5f-6a7b8c9d0e1f" \
-H "Authorization: YOUR_API_KEY"
Check that status is 1 (Approved) and amount matches before marking the payout as complete.