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.

Not the same as Checkout Flow: The commerce checkout Flow “UPI / Card” dropdown is only a preference / text field for address collection. It is not gateway payment. Use the APIs on this page for true in-WhatsApp PG checkout.

Prerequisites

  1. Link a payment partner account to the WABA in Meta WhatsApp Manager (payment configuration name, TEST and/or LIVE).
  2. Optionally save that configuration_name on the WABA in ChatYug (portal Payment Configuration) so the API can auto-fill it.
  3. Confirm with GET /api/external/commerce/payment-configurations.

Session rules (24h window)

PathWhenEndpoint
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

GET /api/external/commerce/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

POST /api/external/messages/order-details

Auth: Authorization: Bearer ck_<api_key>

Request parameters

FieldRequiredDescription
phoneNumberIdYesSend-from phone number ID
toYesCustomer WhatsApp number
bodyTextYesMessage body (max 1024)
reference_idYesUnique id (1–35 chars: letters, numbers, _ - .)
typeNophysical-goods or digital-goods (default physical-goods)
currencyYes*INR
total_amountYes{ value, offset: 100 } in paise
orderYesitems, subtotal, tax, optional shipping/discount/catalog_id
payment_configurationYes*Meta configuration_name; falls back to WABA saved value
payment_gatewayYes*{ type, configuration_name, payu? } — type: payu | razorpay | billdesk | zaakpay
payuNoOptional 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)

POST /api/external/send-message

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)

POST /api/external/messages/order-status

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_configurations
  • send_order_details_message
  • send_order_status_message

Typical flow

  1. Customer places a cart order (or you already know the bill) → your backend builds line items.
  2. Inside 24h: POST /messages/order-details. Outside 24h: ORDER_DETAILS template via send-message.
  3. Customer pays in WhatsApp → you receive eventType: payment (status captured / transaction success).
  4. Confirm with your PG, then POST /messages/order-status with processing → shipped → completed.