WhatsApp Payments
Collect payments inside WhatsApp using Meta interactive order_details (Review and Pay) with a linked payment gateway (PayU, Razorpay, BillDesk, or Zaakpay). ChatYug proxies Graph with your WABA token — you do not need a separate Meta token.
Prerequisites
- Link a payment partner account to the WABA in Meta WhatsApp Manager (payment configuration name, TEST and/or LIVE).
- Optionally save that
configuration_nameon the WABA in ChatYug (portal Payment Configuration) so the API can auto-fill it. - Confirm with
GET /api/external/commerce/payment-configurations.
Session rules (24h window)
| Path | When | Endpoint |
|---|---|---|
Interactive order_details |
Inside the 24h customer-care window only | POST /api/external/messages/order-details |
| ORDER_DETAILS template | Works outside 24h (approved UTILITY / marketing template with ORDER_DETAILS button) | POST /api/external/send-message with type: template + orderDetails |
Interactive order_status |
After capture / fulfilment (same session rules as other interactive messages) | POST /api/external/messages/order-status |
If interactive send returns OUTSIDE_SESSION_WINDOW (or Meta 131047), send an approved UTILITY opener or an ORDER_DETAILS template first — do not call Meta Graph with your own token.
List payment configurations
Auth: Authorization: Bearer ck_<api_key>
Returns Meta payment configurations for the API key WABA plus savedPaymentConfigurationId from ChatYug.
Send interactive order_details
Auth: Authorization: Bearer ck_<api_key>
Request parameters
| Field | Required | Description |
|---|---|---|
phoneNumberId | Yes | Send-from phone number ID |
to | Yes | Customer WhatsApp number |
bodyText | Yes | Message body (max 1024) |
reference_id | Yes | Unique id (1–35 chars: letters, numbers, _ - .) |
type | No | physical-goods or digital-goods (default physical-goods) |
currency | Yes* | INR |
total_amount | Yes | { value, offset: 100 } in paise |
order | Yes | items, subtotal, tax, optional shipping/discount/catalog_id |
payment_configuration | Yes* | Meta configuration_name; falls back to WABA saved value |
payment_gateway | Yes* | { type, configuration_name, payu? } — type: payu | razorpay | billdesk | zaakpay |
payu | No | Optional UDFs: udf1…udf4 (max 255 each) |
* Or provide nested payment_gateway / saved WABA config so ChatYug can resolve configuration_name.
PayU example
curl -X POST https://chatyug.com/api/external/messages/order-details \
-H "Authorization: Bearer ck_your_api_key_here" \
-H "Content-Type: application/json" \
-d '{
"phoneNumberId": "1304520529417376",
"to": "919876543210",
"bodyText": "Please review and pay for your order.",
"reference_id": "AMUL-10042",
"type": "physical-goods",
"currency": "INR",
"total_amount": { "value": 11000, "offset": 100 },
"order": {
"items": [
{
"name": "Amul Butter 500g",
"quantity": 1,
"amount": { "value": 10000, "offset": 100 },
"country_of_origin": "India",
"importer_name": "GCMMF",
"importer_address": {
"address_line1": "Anand",
"city": "Anand",
"zone_code": "GJ",
"postal_code": "388001",
"country_code": "IN"
}
}
],
"subtotal": { "value": 10000, "offset": 100 },
"tax": { "value": 1000, "offset": 100, "description": "GST" }
},
"payment_gateway": {
"type": "payu",
"configuration_name": "payu_live_config",
"payu": { "udf1": "merchant_order_10042" }
}
}'Razorpay example (gateway object)
"payment_gateway": {
"type": "razorpay",
"configuration_name": "razorpay_live",
"razorpay": {
"receipt": "rcpt_10042",
"notes": { "channel": "whatsapp" }
}
}Send ORDER_DETAILS template (outside 24h)
Use an approved template that includes an ORDER_DETAILS button. Pass the same commerce fields under orderDetails. ChatYug builds the button action parameter (including payment_configuration from the WABA if omitted).
{
"phoneNumberId": "1304520529417376",
"to": "919876543210",
"type": "template",
"templateName": "order_payment_request",
"templateLanguage": "en",
"templateVariables": ["Rahul", "AMUL-10042"],
"orderDetails": {
"currency": "INR",
"reference_id": "AMUL-10042",
"type": "physical-goods",
"total_amount": { "value": 11000, "offset": 100 },
"payment_configuration": "payu_live_config",
"order": {
"items": [{ "name": "Amul Butter 500g", "quantity": 1, "amount": { "value": 10000, "offset": 100 } }],
"subtotal": { "value": 10000, "offset": 100 },
"tax": { "value": 1000, "offset": 100 }
}
}
}Payment status webhook
Meta delivers payment updates as statuses[] with type: "payment". ChatYug forwards them as eventType: "payment" with the same HMAC as other webhooks (X-Chatyug-Signature) and a stable eventId:
payment:{reference_id}:{transaction.id}:{status}
See Event Reference for the full payload. Always reconcile with your payment gateway using reference_id; do not rely on webhooks alone.
Send order_status (post-pay)
Auth: Authorization: Bearer ck_<api_key>
Allowed status values: processing, partially_shipped, shipped, completed, canceled. Must match the reference_id from the original order_details.
curl -X POST https://chatyug.com/api/external/messages/order-status \
-H "Authorization: Bearer ck_your_api_key_here" \
-H "Content-Type: application/json" \
-d '{
"phoneNumberId": "1304520529417376",
"to": "919876543210",
"bodyText": "Your payment was received. We are preparing your order.",
"reference_id": "AMUL-10042",
"status": "processing"
}'MCP tools
list_payment_configurationssend_order_details_messagesend_order_status_message
Typical flow
- Customer places a cart order (or you already know the bill) → your backend builds line items.
- Inside 24h:
POST /messages/order-details. Outside 24h: ORDER_DETAILS template viasend-message. - Customer pays in WhatsApp → you receive
eventType: payment(statuscaptured/ transactionsuccess). - Confirm with your PG, then
POST /messages/order-statuswithprocessing→shipped→completed.