Webhook
Webhook notifications allow you to receive real-time updates about payment transaction status changes. When a payment's status changes (e.g., from pending to authorised, or from authorised to waiting), Hello Clever will send a POST request to your specified webhook endpoint.
Webhook Object
When a payment status changes, you'll receive a webhook notification with the following object structure:
| Field | Type | Description |
|---|---|---|
uuid | string | Unique identifier for the payment transaction |
expires_at | string | Expiration time (ISO 8601 UTC) of the payment link |
payment_url | string | URL of the payment |
payin_method_code | string | Code of the selected payment method |
amount | number | Original payment amount |
description | string | Description of the payment transaction |
redirect_url | object | URLs for different payment outcomes |
└─ success | string | Redirect URL for success |
webhook_notification | object | Webhook configuration details |
└─ authorization_header | string | Authorization header for webhook |
└─ endpoint_url | string | URL where webhooks will be sent |
sender_info | object | Information about the sender |
└─ email | string | Customer's email. |
└─ first_name | string | Customer's first name. |
└─ last_name | string | Customer's last name. |
└─ gender | string | Gender of the customer. |
└─ contact_type | string | Optional contact type. |
└─ dob | string | Date of birth. |
└─ reg_no | string | Registration number. |
└─ state | string | State/Province. |
└─ user_id | string | User ID from the merchant system. |
└─ upi_id | string | UPI ID. |
└─ user_name | string | User name from the merchant system. |
└─ phone | string | Customer's phone number. |
└─ country_code | string | ISO 2-letter country code. |
└─ address | string | Full street address. |
└─ city | string | City. |
└─ postal_code | string | Postal/ZIP code. |
└─ account_name | string | Account name from the merchant system. |
└─ account_number | string | Mobile money account number. |
└─ bank_code | string | Bank code for the charge. |
└─ document_type | string | Type of document for the charge. |
└─ document_number | string | Document number for the charge. |
└─ state_code | string | State code. |
metadata | object | Optional key-value pairs to attach as custom information for the transaction |
└─ custom_note | string | Custom fields |
└─ external_id | string | Custom fields |
transaction_info | object | Information about the transaction |
└─ uuid | string | Transaction UUID |
└─ currency | string | Currency code for the transaction (3-letter code, e.g., USD, EUR, VND) |
└─ amount | number | Original payment amount |
└─ paid_amount | number | The actual amount successfully paid by the customer |
└─ status | string | The current status of the payment |
└─ status_text | string | Detailed explanation of the current status |
Example:
{
"uuid": "7AMCEF7H",
"expires_at": "2025-10-02T19:05:03.971Z",
"payment_url": "https://paylink.cleverhub.co/N0FNQ0VGNAD",
"payin_method_code": "vn_vietqr_vnd",
"amount": 3000,
"description": "Test payin",
"redirect_url": {
"success": "https://example.com/success"
},
"webhook_notification": {
"authorization_header": "****",
"endpoint_url": "https://example.com/webhook"
},
"sender_info": {
"email": "email@gmail.com",
"first_name": "John",
"last_name": "Doe",
"gender": "male",
"contact_type": "individual",
"dob": "1990-01-01",
"reg_no": "A1234567",
"state": "Ho Chi Minh",
"user_id": "user_12345",
"upi_id": "johndoe@upi",
"user_name": "john_doe123",
"phone": "0123456789",
"country_code": "VN",
"address": "123 abc",
"city": "Ho Chi Minh City",
"postal_code": "700000",
"account_name": "John Doe",
"account_number": "233240000000",
"bank_code": "VCB",
"document_type": "passport",
"document_number": "P123456789",
"state_code": "SG"
},
"metadata": {
"custom_note": "Priority customer",
"external_id": "1HUJMW34"
},
"transaction_info": {
"uuid": "3D8G9WJJ",
"currency": "VND",
"amount": 3000.0,
"paid_amount": 0.0,
"status": "pending",
"status_text": "Customer started a new payment but hasn't proceeded yet."
}
}
Setting Up Webhooks
You can do this by including the webhook_notification object in your payment link creation request here
Status Changes
Webhook notifications are sent when a payment's status changes to any of the following:
pending: Customer started a new payment but hasn't proceeded yet.authorised: Payment has been authorised, ready to be captured.waiting: Payment has been approved, awaiting funds to settle.received: Funds have been received.expired: Payment session expired before completion.return_pending: Refund request initiated, awaiting processing.return_expired: The refund request has expired. Expiration time is set to be 10 days.partially_refunded: Partial refund has been issued to the customer.return_received: Full amount has been refunded to the customer.return_rejected: Refund request was denied. The system will not retry again.failed: Payment failed due to an error or decline.in_dispute: Customer has raised a dispute, under review.dispute_lost: Dispute has been resolved in customer's favour The disputed amount is not returned to the merchant.
Best Practices
- Always verify the webhook signature or authorization header to ensure the request is legitimate
- Implement idempotency in your webhook handler to prevent duplicate processing
- Respond with a 200 OK status code as soon as you receive the webhook
- Process the webhook data asynchronously to avoid timeout issues
- Keep your webhook endpoint URL secure and private
Testing Webhooks
You can test webhook notifications using tools like webhook.site or by setting up a local endpoint using tools like ngrok.
Error Handling
If the target endpoint does not return HTTP 200, Hello Clever will retry the webhook call 3 times with 15 minutes delay per call.