Skip to main content

Event Payload Examples

EasyConfirm fires webhooks for orders created via the Public API (POST /api/v1/orders). Below are example payloads for each event.

order.created

Fired after a new order is created and the WhatsApp template message is sent to the customer successfully.

{
"event": "order.created",
"timestamp": "2026-01-15T10:00:00.000Z",
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"externalOrderId": "EO-12345",
"status": "pending",
"customerAction": null,
"deliveryStatus": null,
"customerName": "Ahmed Mohamed",
"customerPhone": "201234567890",
"customerAddress": "15 Tahrir St, Cairo",
"subtotal": 150,
"shippingCost": 25,
"totalCost": 175,
"currency": "EGP",
"failureReason": null,
"errorCode": null,
"items": [
{
"id": "item-uuid-1",
"productName": "iPhone Case",
"variantName": "Black / Large",
"quantity": 2,
"unitPrice": 75,
"totalPrice": 150
}
],
"createdAt": "2026-01-15T10:00:00.000Z",
"updatedAt": "2026-01-15T10:00:00.000Z"
}
}

order.confirmed

Fired when the customer taps the Approve button on the WhatsApp confirmation message.

{
"event": "order.confirmed",
"timestamp": "2026-01-15T10:05:30.000Z",
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"externalOrderId": "EO-12345",
"status": "confirmed",
"customerAction": "approved",
"deliveryStatus": "read",
"customerName": "Ahmed Mohamed",
"customerPhone": "201234567890",
"customerAddress": "15 Tahrir St, Cairo",
"subtotal": 150,
"shippingCost": 25,
"totalCost": 175,
"currency": "EGP",
"failureReason": null,
"errorCode": null,
"items": [
{
"id": "item-uuid-1",
"productName": "iPhone Case",
"variantName": "Black / Large",
"quantity": 2,
"unitPrice": 75,
"totalPrice": 150
}
],
"createdAt": "2026-01-15T10:00:00.000Z",
"updatedAt": "2026-01-15T10:05:30.000Z"
}
}

order.canceled

Fired when the customer taps the Cancel button on WhatsApp, or the order is canceled via the API.

{
"event": "order.canceled",
"timestamp": "2026-01-15T10:05:30.000Z",
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"externalOrderId": "EO-12345",
"status": "canceled",
"customerAction": "canceled",
"deliveryStatus": "read",
"customerName": "Ahmed Mohamed",
"customerPhone": "201234567890",
"customerAddress": "15 Tahrir St, Cairo",
"subtotal": 150,
"shippingCost": 25,
"totalCost": 175,
"currency": "EGP",
"failureReason": null,
"errorCode": null,
"items": [
{
"id": "item-uuid-1",
"productName": "iPhone Case",
"variantName": "Black / Large",
"quantity": 2,
"unitPrice": 75,
"totalPrice": 150
}
],
"createdAt": "2026-01-15T10:00:00.000Z",
"updatedAt": "2026-01-15T10:05:30.000Z"
}
}

order.failed

Fired when the WhatsApp message delivery fails asynchronously — i.e., the order was created successfully, Meta accepted the send request, but the message later failed to be delivered (e.g., the recipient's device is offline for an extended period, or Meta reports a delivery failure via webhook callback).

:::warning When this event fires (and when it does NOT) This event fires only for asynchronous delivery failures reported by Meta after the order was successfully created.

It does NOT fire when Meta synchronously rejects the send during the API call itself (e.g., recipient not in test allowlist, template paused, template not approved). In that case POST /api/v1/orders returns a 400 response containing errorCode and failureReason directly — there is no webhook callback for that scenario, because the caller already received the failure in the API response.

Failure typeHow you learn about it
Meta rejects the send synchronouslyPOST /api/v1/orders400 with errorCode + failureReason
Meta accepts the send, then delivery fails laterorder.failed webhook with errorCode + failureReason

In both cases the order is persisted with status: failed and the same failureReason + errorCode, so GET /orders/:id returns the full failure context regardless of which path failed. :::

{
"event": "order.failed",
"timestamp": "2026-01-15T10:01:00.000Z",
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"externalOrderId": "EO-12345",
"status": "failed",
"customerAction": null,
"deliveryStatus": "failed",
"customerName": "Ahmed Mohamed",
"customerPhone": "201234567890",
"customerAddress": "15 Tahrir St, Cairo",
"subtotal": 150,
"shippingCost": 25,
"totalCost": 175,
"currency": "EGP",
"failureReason": "Recipient phone number not in allowed list",
"errorCode": 131030,
"items": [
{
"id": "item-uuid-1",
"productName": "iPhone Case",
"variantName": "Black / Large",
"quantity": 2,
"unitPrice": 75,
"totalPrice": 150
}
],
"createdAt": "2026-01-15T10:00:00.000Z",
"updatedAt": "2026-01-15T10:01:00.000Z"
}
}

Understanding failureReason and errorCode

Both fields are populated directly from Meta's WhatsApp Cloud API error payload — EasyConfirm does not define its own enum of failure values. This means:

  • errorCode (integer, nullable) — the numeric error code from Meta. Use this for programmatic handling. It is stable and documented by Meta. May be null if the failure occurred before reaching Meta (e.g. internal validation) or for orders that failed before this field was introduced.
  • failureReason (string, nullable) — the human-readable error text from Meta (errors[0].message, falling back to errors[0].title, then "Unknown failure"). Do not match on the text — Meta may change the wording without notice, and it can be returned in different languages. Use it for display only.

Common Meta error codes

The full, authoritative list is maintained by Meta: 👉 Meta WhatsApp Cloud API — Error Codes Reference

Codes you are most likely to encounter on order.failed:

CodeMeaningSuggested handling
131026Message undeliverable (recipient not on WhatsApp, device offline)Mark order for phone-call follow-up
131030Recipient phone number not in the allowed list (test mode only)Add recipient to allowed list, or move the WABA out of test mode
131042Business eligibility / payment issue (e.g., PAYG funding)Check WhatsApp Business billing in Meta Business Suite
131045Template not approved by MetaRe-submit the template or pick an approved one
131047Re-engagement window expired (24h customer service window closed)Use a pre-approved template message
131048Spam rate limit reachedThrottle outgoing sends; review opt-in compliance
131049User has stopped marketing messagesSuppress this recipient from marketing campaigns
131056Pair rate limit (too many messages to the same recipient)Back off and retry later
132000Template parameter count mismatchVerify your template variable bindings
132001Template does not exist (deleted or wrong language)Re-create the template or correct the language code
132005Translated text too longShorten the rendered template
132007Template format character policy violatedRemove disallowed characters
132012Template parameter format mismatchMatch Meta's required format for that variable
132015Template paused due to quality dropImprove template quality; wait for un-pausing
132016Template disabledChoose another template
133010Phone number not registeredRe-register the WABA phone number

:::note Key Differences Between Events

  • order.created: status is pending, customerAction and deliveryStatus are null
  • order.confirmed: status is confirmed, customerAction is approved
  • order.canceled: status is canceled, customerAction is canceled
  • order.failed: status is failed, failureReason contains the error text and errorCode contains Meta's numeric error code :::