Skip to main content

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:

FieldTypeDescription
uuidstringUnique identifier for the payment transaction
expires_atstringExpiration time (ISO 8601 UTC) of the payment link
payment_urlstringURL of the payment
payin_method_codestringCode of the selected payment method
amountnumberOriginal payment amount
descriptionstringDescription of the payment transaction
redirect_urlobjectURLs for different payment outcomes
└─ successstringRedirect URL for success
webhook_notificationobjectWebhook configuration details
└─ authorization_headerstringAuthorization header for webhook
└─ endpoint_urlstringURL where webhooks will be sent
sender_infoobjectInformation about the sender
└─ emailstringCustomer's email.
└─ first_namestringCustomer's first name.
└─ last_namestringCustomer's last name.
└─ genderstringGender of the customer.
└─ contact_typestringOptional contact type.
└─ dobstringDate of birth.
└─ reg_nostringRegistration number.
└─ statestringState/Province.
└─ user_idstringUser ID from the merchant system.
└─ upi_idstringUPI ID.
└─ user_namestringUser name from the merchant system.
└─ phonestringCustomer's phone number.
└─ country_codestringISO 2-letter country code.
└─ addressstringFull street address.
└─ citystringCity.
└─ postal_codestringPostal/ZIP code.
└─ account_namestringAccount name from the merchant system.
└─ account_numberstringMobile money account number.
└─ bank_codestringBank code for the charge.
└─ document_typestringType of document for the charge.
└─ document_numberstringDocument number for the charge.
└─ state_codestringState code.
metadataobjectOptional key-value pairs to attach as custom information for the transaction
└─ custom_notestringCustom fields
└─ external_idstringCustom fields
transaction_infoobjectInformation about the transaction
└─ uuidstringTransaction UUID
└─ currencystringCurrency code for the transaction (3-letter code, e.g., USD, EUR, VND)
└─ amountnumberOriginal payment amount
└─ paid_amountnumberThe actual amount successfully paid by the customer
└─ statusstringThe current status of the payment
└─ status_textstringDetailed 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

  1. Always verify the webhook signature or authorization header to ensure the request is legitimate
  2. Implement idempotency in your webhook handler to prevent duplicate processing
  3. Respond with a 200 OK status code as soon as you receive the webhook
  4. Process the webhook data asynchronously to avoid timeout issues
  5. 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.