> ## Documentation Index
> Fetch the complete documentation index at: https://docs.connectly.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Webhook Payload Reference

> Every webhook payload shape Connectly sends — inbound text, referrals, media, button replies, and delivery status events — with full JSON examples 💻

This page covers every type of webhook payload Connectly can POST to your endpoint. Currently, only WhatsApp events are supported.

## Common fields

### `callbackData`

When you set the optional `callbackData` field on an outbound message, Connectly echoes it back at the top level of related webhook events:

* Delivery status events — `sent`, `delivered`, `read`, `delivery_failed`
* Inbound replies that reference the original message — quoted replies, button & list replies, reactions

`callbackData` is only present when it was set on the original outbound message. Plain-text inbound messages that don't quote a prior message will not include it.

### Business-scoped user IDs (BSUID)

On WhatsApp numbers with BSUID support enabled, the customer identifier carries two extra fields: `userId` and `phoneNumber`. For phone-less customers, `id` holds the BSUID and `phoneNumber` is `""`. The customer appears as `sender` on inbound message webhooks and as `recipient` on delivery-status webhooks. See [BSUID](https://docs.connectly.ai/messaging/bsuid) for full details.

***

## Inbound message payloads

### Plain text

```json theme={null}
{
  "timestamp": "1639083206",
  "sender": {
    "id": "+16315555500",
    "channelType": "whatsapp",
    "name": "Customer Name"
  },
  "recipient": {
    "id": "+16044441234",
    "channelType": "whatsapp",
    "name": "connectlyai"
  },
  "message": {
    "text": "Hello!"
  }
}
```

### Message with referral (Click-to-WhatsApp ad)

When a customer messages you directly from a Meta ad, the payload includes a `referral` object with ad attribution data.

```json theme={null}
{
  "timestamp": "1639083206",
  "sender": {
    "id": "+16315555500",
    "channelType": "whatsapp",
    "name": "Customer Name"
  },
  "recipient": {
    "id": "+16044441234",
    "channelType": "whatsapp",
    "name": "connectlyai"
  },
  "message": {
    "text": "Hello!",
    "referral": {
      "ctwaClid": "ARAkLkA8nM...",
      "sourceUrl": "AD_OR_POST_FB_URL",
      "sourceId": "ADID",
      "sourceType": "ad",
      "headline": "AD_TITLE",
      "body": "AD_DESCRIPTION",
      "mediaType": "image",
      "imageUrl": "RAW_IMAGE_URL",
      "videoUrl": "RAW_VIDEO_URL",
      "thumbnailUrl": "RAW_THUMBNAIL_URL"
    }
  }
}
```

| Field          | Description                                              |
| -------------- | -------------------------------------------------------- |
| `ctwaClid`     | Click ID generated by Meta for the click-to-WhatsApp ad. |
| `sourceUrl`    | URL of the Facebook ad or post.                          |
| `sourceId`     | ID of the ad.                                            |
| `sourceType`   | `"ad"` or `"post"`.                                      |
| `headline`     | Title of the ad.                                         |
| `body`         | Description text of the ad.                              |
| `mediaType`    | `"image"` or `"video"`.                                  |
| `imageUrl`     | Raw URL of the ad image.                                 |
| `videoUrl`     | Raw URL of the ad video.                                 |
| `thumbnailUrl` | Raw URL of the video thumbnail.                          |

### Media attachment

When a customer sends an image, video, audio, or document, the payload includes an `attachments` array. Only one attachment is sent per webhook event.

```json theme={null}
{
  "timestamp": "1640204070",
  "sender": {
    "id": "+16315555500",
    "channelType": "whatsapp",
    "name": "Customer Name"
  },
  "recipient": {
    "id": "+16044441234",
    "channelType": "whatsapp",
    "name": "connectlyai"
  },
  "message": {
    "attachments": [
      {
        "type": "audio",
        "url": "https://cdn.connectly.ai/46b6/46b6725c-a821-480c-901b-8a76b990a25c"
      }
    ]
  }
}
```

The `type` field indicates the media type. The file is accessible at `url` — when downloading programmatically, read the MIME type from the response `Content-Type` header.

**Supported media types and MIME types:**

| Type       | Supported MIME types                                                                                                                                                                                             |
| ---------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `image`    | `image/jpeg`, `image/png`                                                                                                                                                                                        |
| `video`    | `video/mp4`, `video/3gpp`*(coming soon)*                                                                                                                                                                         |
| `audio`    | `audio/aac`, `audio/mp4`, `audio/mpeg`, `audio/amr`, `audio/ogg`, `audio/ogg; codecs=opus`                                                                                                                       |
| `document` | `text/plain`, `application/pdf`, `application/msword`, `application/vnd.ms-excel`, `application/vnd.ms-powerpoint`, `application/vnd.openxmlformats-officedocument.*`, `application/vnd.android.package-archive` |

### Button response

When a customer taps an interactive button, the payload includes a `buttonResponse` object and a `context` object referencing the original message. If you set `callbackData` on the original outbound message, it is echoed back here.

```json theme={null}
{
  "timestamp": "1639083206",
  "sender": {
    "id": "+16315555500",
    "channelType": "whatsapp",
    "name": "Customer Name"
  },
  "recipient": {
    "id": "+16044441234",
    "channelType": "whatsapp",
    "name": "connectlyai"
  },
  "context": {
    "replyToId": "018d62f2-2524-10fa-f857-091ab99c14c8"
  },
  "buttonResponse": {
    "text": "Yes",
    "payload": "1"
  },
  "callbackData": {
    "order_id": "12345"
  }
}
```

***

## Delivery status payloads

Delivery status events are sent to your `delivery_status` topic endpoint. The `statusUpdate.id` field matches the message ID returned when you originally sent the message — use it to correlate events back to outbound messages.

### Delivered

```json theme={null}
{
  "topic": "delivery_status",
  "timestamp": "1641513098",
  "sender": {
    "id": "+16044441234",
    "channelType": "whatsapp",
    "name": "connectlyai"
  },
  "recipient": {
    "id": "+16315555500",
    "channelType": "whatsapp",
    "name": "Customer Name"
  },
  "statusUpdate": {
    "id": "01FRRWW2ZAHD9GJ1SWY4VF2GBD",
    "status": "delivered",
    "error": null,
    "metadata": {
      "campaign_name": "my_campaign"
    }
  },
  "callbackData": {
    "order_id": "12345"
  }
}
```

The `status` field progresses through `sent` → `delivered` → `read`. Each transition generates a separate event.

### Delivery failed

When delivery fails, `status` is `delivery_failed` and the `error` object provides details including a `cntTraceId` to share with Connectly support.

```json theme={null}
{
  "topic": "delivery_status",
  "timestamp": "1641512856",
  "sender": {
    "id": "+16044441234",
    "channelType": "whatsapp",
    "name": "connectlyai"
  },
  "recipient": {
    "id": "+16315555500",
    "channelType": "whatsapp",
    "name": "Customer Name"
  },
  "statusUpdate": {
    "id": "01FRRWMSAMKNFZAMBPQ65CA7DD",
    "status": "delivery_failed",
    "error": {
      "message": "Message template inputs invalid",
      "type": "ERROR_TYPE_INVALID_REQUEST",
      "code": "ERROR_CODE_MESSAGE_TEMPLATE_INPUT_INVALID",
      "userTitle": "Message template inputs invalid",
      "userMessage": "Pass along the connectly trace id 'cnct_trace_id' to the team for more information.",
      "cntTraceId": "10827968052975079261",
      "details": {}
    },
    "metadata": {
      "campaign_name": "my_campaign"
    }
  }
}
```

| Error field   | Description                                                                    |
| ------------- | ------------------------------------------------------------------------------ |
| `message`     | Description of the error.                                                      |
| `type`        | High-level error category (e.g. `ERROR_TYPE_INVALID_REQUEST`).                 |
| `code`        | Specific error code (e.g. `ERROR_CODE_MESSAGE_TEMPLATE_INPUT_INVALID`).        |
| `userTitle`   | Short human-readable error title.                                              |
| `userMessage` | Actionable guidance for resolving the error.                                   |
| `cntTraceId`  | Connectly trace ID — provide this to support when reporting delivery failures. |

<Tip>
  Log the `cntTraceId` from every `delivery_failed` event. It's the fastest way to diagnose a delivery failure with Connectly support.
</Tip>

For the full list of error types and codes, see [Error codes](https://docs.connectly.ai/messaging/error-codes).
