Webhook Events
Events pushed to your endpoint when a transaction changes status, and how to verify them.
Register an HTTPS endpoint under Developer › Webhooks and Payonclick sends an event when a transaction you created through the API changes status, usually within 15 seconds. That includes changes made after your call returned: a bill payment the status check settles later, or a transfer an operator completes hours afterwards.
| Event | Sent when | Payload fields |
|---|---|---|
bill.pending | A BBPS payment made through the API is waiting for biller confirmation | reference_id, client_reference, status, amount, biller_id, biller_name, category, customer_reference, bbps_txn_id, approval_ref, response_code, message, refunded, created_at, updated_at |
bill.success | The biller confirmed a BBPS payment | reference_id, client_reference, status, amount, biller_id, biller_name, category, customer_reference, bbps_txn_id, approval_ref, response_code, message, refunded, created_at, updated_at |
bill.failed | A BBPS payment failed; the wallet debit was reversed | reference_id, client_reference, status, amount, biller_id, biller_name, category, customer_reference, bbps_txn_id, approval_ref, response_code, message, refunded, created_at, updated_at |
bill.refunded | A BBPS payment was reversed and refunded after review | reference_id, client_reference, status, amount, biller_id, biller_name, category, customer_reference, bbps_txn_id, approval_ref, response_code, message, refunded, created_at, updated_at |
transfer.pending | A DMT transfer made through the API is waiting for a transfer operator | request_id, client_reference, status, amount, charge_amount, total_debit, utr_number, failure_reason, refund_amount, beneficiary_name, beneficiary_bank_name, beneficiary_account_masked, beneficiary_ifsc, created_at, completed_at, refunded_at |
transfer.success | A transfer was completed; utr_number is set | request_id, client_reference, status, amount, charge_amount, total_debit, utr_number, failure_reason, refund_amount, beneficiary_name, beneficiary_bank_name, beneficiary_account_masked, beneficiary_ifsc, created_at, completed_at, refunded_at |
transfer.failed | A transfer failed; the held amount is released to your wallet | request_id, client_reference, status, amount, charge_amount, total_debit, utr_number, failure_reason, refund_amount, beneficiary_name, beneficiary_bank_name, beneficiary_account_masked, beneficiary_ifsc, created_at, completed_at, refunded_at |
transfer.refunded | A transfer amount was refunded to your wallet | request_id, client_reference, status, amount, charge_amount, total_debit, utr_number, failure_reason, refund_amount, beneficiary_name, beneficiary_bank_name, beneficiary_account_masked, beneficiary_ifsc, created_at, completed_at, refunded_at |
recharge.pending | A mobile/DTH recharge made through the API is with the operator | reference_id, client_reference, status, service, operator_id, operator_name, number, amount, total_debit, operator_ref, message, failure_code, refunded, created_at, updated_at |
recharge.success | The operator confirmed a recharge; operator_ref is set | reference_id, client_reference, status, service, operator_id, operator_name, number, amount, total_debit, operator_ref, message, failure_code, refunded, created_at, updated_at |
recharge.failed | A recharge failed; the wallet debit is released back to you | reference_id, client_reference, status, service, operator_id, operator_name, number, amount, total_debit, operator_ref, message, failure_code, refunded, created_at, updated_at |
aeps.pending | An AEPS cash withdrawal, Aadhaar Pay or cash deposit is awaiting bank confirmation | reference_id, client_reference, merchant_ref, service, status, amount, aadhaar, bank_iin, bank_name, bank_rrn, account_balance, charge, commission, wallet_impact, failure_code, message, refunded (CD), created_at |
aeps.success | An AEPS transaction succeeded; bank_rrn is set and your AEPS wallet is settled | reference_id, client_reference, merchant_ref, service, status, amount, aadhaar, bank_iin, bank_name, bank_rrn, account_balance, charge, commission, wallet_impact, failure_code, message, refunded (CD), created_at |
aeps.failed | An AEPS transaction failed; a cash deposit is refunded to your AEPS wallet | reference_id, client_reference, merchant_ref, service, status, amount, aadhaar, bank_iin, bank_name, bank_rrn, account_balance, charge, commission, wallet_impact, failure_code, message, refunded (CD), created_at |
upicw.success | The customer paid a UPI Cash QR; hand over the cash — your AEPS wallet is credited | reference_id, client_reference, merchant_ref, status, amount, customer_mobile, payer_vpa (masked), payer_name, bank_rrn, charge, commission, wallet_impact, failure_code, message, created_at, updated_at |
upicw.failed | A UPI Cash QR was not paid (expired or declined by the payer's bank) | reference_id, client_reference, merchant_ref, status, amount, customer_mobile, payer_vpa (masked), payer_name, bank_rrn, charge, commission, wallet_impact, failure_code, message, created_at, updated_at |
matm.success | The bank network confirmed a Micro ATM transaction; a cash withdrawal is credited to your AEPS wallet | reference_id, client_reference, merchant_ref, service, status, amount, card (masked), card_type, bank_name, bank_rrn, account_balance, mini_statement, charge, commission, wallet_impact, confirmed_by_bank_network, failure_code, message, created_at, updated_at |
matm.failed | A Micro ATM transaction failed or was declined; nothing is credited | reference_id, client_reference, merchant_ref, service, status, amount, card (masked), card_type, bank_name, bank_rrn, account_balance, mini_statement, charge, commission, wallet_impact, confirmed_by_bank_network, failure_code, message, created_at, updated_at |
beneficiary.added | A beneficiary was added through the API | beneficiary_id, bene_name, account_masked, bank_name, ifsc_code, is_verified |
beneficiary.deleted | A beneficiary was removed through the API | beneficiary_id |
Delivery
Each delivery is a POST with the JSON body {"event", "webhook_id", "delivery_id", "timestamp", "data"} and the headers X-POC-Event, X-POC-Delivery-Id, X-POC-Attempt and X-POC-Signature. Reply with any 2xx status within 10 seconds; redirects are not followed.
A failed delivery is retried after 1 min, 5 min, 15 min, 1 h, 3 h and 6 h, with the same X-POC-Delivery-Id, so the same event can arrive more than once: de-duplicate on the delivery id. Every failed attempt raises the failure count of the webhook and a success resets it. A webhook announces a change; call the status endpoint when you need the current state of a transaction.
Verifying a delivery
Deliveries are signed with your webhook secret in the X-POC-Signature header as sha256=<hmac>, computed over the raw body. Verify it before trusting the payload.
import hmac, hashlib
def verify(raw_body: bytes, header: str, secret: str) -> bool:
expected = hmac.new(secret.encode(), raw_body, hashlib.sha256).hexdigest()
return hmac.compare_digest("sha256=" + expected, header)
The callback URL must use HTTPS and resolve to a public address; private, loopback and link-local addresses are refused. Acknowledge the delivery first and process it afterwards, so a slow job never causes a timeout.