Pay
Receive notifications about outgoing Pix payments
After you create a payment with payToPixKey, kamiPay keeps you updated on its progress through webhooks. You don't need to poll the status endpoint from your backend.
Handling Webhook Responses
You receive one webhook per state change. Every webhook has the same top-level fields:
| Field | Description |
|---|---|
status | processing, done or failed. |
transaction_hash | Always null. Payouts don't have an on-chain transaction. |
data | Payment details. Its content depends on status (see below). |
type | Always pay. |
timestamp | When the notification was generated, formatted as YYYY-MM-DD HH:MM:SS.ffffff+0000. |
external_id | The external_id you sent when creating the payment, or null. |
kamipay_id | kamiPay identifier of the payment (txc_...). |
service_type | Always prepaid. |
Processing
The bank received the payment and started settling it. It can still end in done or failed. If it succeeds, the receiver usually sees the money a few seconds later.
{
"status": "processing",
"transaction_hash": null,
"data": {
"operation_id": "txc_01m2710frffc488sxp08mg0qzx",
"address_in": "0xca4xxxxxxxxxxxxxxx1f2fc",
"usdt_amount": "9.780595",
"brl_amount": "50.00",
"bank_txid": "E54811417202609110123BGdlB7HYojX",
"pix_key": "info@kamipay.io",
"name": "Kamipay AR Servicos Digitais Ltda",
"recipient_document": null,
"recipient_ispb": null,
"recipient_bank_name": "unknown"
},
"type": "pay",
"timestamp": "2026-09-11 01:23:46.083563+0000",
"external_id": "aaa-11112",
"kamipay_id": "txc_01m2710frffc488sxp08mg0qzx",
"service_type": "prepaid"
}Done
The payment was successful. At this point the settlement is final and both the sender's and the receiver's banks confirmed it. Use bank_txid (the Pix End-to-End ID) as proof of payment for the receiver.
{
"status": "done",
"transaction_hash": null,
"data": {
"operation_id": "txc_01m2arg0d8f1r9y3cjzh44f894",
"address_in": "0xca4xxxxxxxxxxxxxxx1f2fc",
"usdt_amount": "59.826162",
"brl_amount": "307.94",
"bank_txid": "E27084098202609121211e4MQ09RFuyC",
"pix_key": "info@kamipay.io",
"name": "Kamipay AR Servicos Digitais Ltda",
"recipient_document": "**.309.606/****-**",
"recipient_ispb": "01027058",
"recipient_bank_name": "Cielo S.A."
},
"type": "pay",
"timestamp": "2026-09-12 12:12:00.261509+0000",
"external_id": "aaa-11112",
"kamipay_id": "txc_01m2arg0d8f1r9y3cjzh44f894",
"service_type": "prepaid"
}data fields (processing and done)
| Field | Description |
|---|---|
operation_id | Identifier of the payment at the settling bank. |
address_in | Your active vault address. It can be null. |
usdt_amount | USDT amount debited, as a string with 6 decimals. |
brl_amount | BRL amount paid, as a string with 2 decimals. |
bank_txid | Pix End-to-End ID. It can be null or empty in processing. |
pix_key | Destination Pix key. |
name | Name of the Pix key owner. |
recipient_document | Receiver's CPF/CNPJ, obfuscated BACEN-style (***.456.789-** for CPF, **.345.678/****-** for CNPJ). It can be null, usually in processing. |
recipient_ispb | 8-digit ISPB of the receiver's bank, or null. |
recipient_bank_name | Name of the receiver's bank, or "unknown" when it can't be resolved. |
Failed
The payment failed. It can fail for several reasons, for example because the QR code expired or the receiving bank rejected it. In every case the funds are returned to your balance.
data only carries the normalized failure reason. See Payout Failure Reasons for the list of codes and how to react to each category.
{
"status": "failed",
"transaction_hash": null,
"data": {
"error_code": "PAYOUT_TEMPORARY_ERROR",
"error_message": "A temporary error occurred. Please try again later.",
"error_category": "internal"
},
"type": "pay",
"timestamp": "2026-09-13 23:15:26.761384+0000",
"external_id": "aaa-11112",
"kamipay_id": "txc_01m2egvkt0fbbryev4z2whz7ga",
"service_type": "prepaid"
}If a completed payout is later refunded (for example, through a MED), you receive a Refund webhook, not a new Pay webhook.
If external_id is not provided, all webhooks will come with null value for that field. We strongly recommend all users to pass an external_id to this endpoint for better tracking and monitoring.