# whatsapp.message.received

> A customer sent a WhatsApp message to one of your numbers.

## When it fires

A customer sent a message to one of your project's WhatsApp numbers: text, media, a location, contacts, a button tap, a list choice, a reaction, or another message type. It fires once per message.

A message with a file fires once the file is stored, so the file's `status` is `ready` and you can [download it](/docs/api/messaging/media) at once. If WhatsApp no longer has the file, or it can't be downloaded after retries for up to 24 hours, the event fires with the status `unavailable` instead. Every received message fires the event.

## Example payload

Example identifiers are shown below. The customer tapped a quick-reply button of your template:

```json
{
  "id": "00000000-0000-4000-8000-000000000001",
  "type": "whatsapp.message.received",
  "schema_version": 1,
  "data": {
    "id": "msg_example",
    "sender": "+213555123456",
    "recipient": "+213555000111",
    "type": "button",
    "reply_to": "msg_example_sent",
    "contact": {
      "name": "Amina"
    },
    "occurred_at": "2026-10-14T10:02:03.000Z",
    "button": {
      "text": "Confirm",
      "payload": "confirm-A-1234"
    }
  },
  "created_at": "2026-10-14T10:02:05.412Z"
}
```

A photo, once it is stored:

```json
{
  "id": "00000000-0000-4000-8000-000000000002",
  "type": "whatsapp.message.received",
  "schema_version": 1,
  "data": {
    "id": "msg_example",
    "sender": "+213555123456",
    "recipient": "+213555000111",
    "type": "image",
    "reply_to": null,
    "contact": {
      "name": "Amina"
    },
    "occurred_at": "2026-10-14T10:05:41.000Z",
    "image": {
      "status": "ready",
      "file_id": "fas_example",
      "mime_type": "image/jpeg",
      "size_bytes": 48213,
      "filename": null,
      "caption": "The box arrived damaged",
      "link": null
    }
  },
  "created_at": "2026-10-14T10:05:44.120Z"
}
```

## Event fields

| Field | Type | Description |
| --- | --- | --- |
| `data.id` | string | Message ID, starting with `msg_`. Use it to [retrieve](/docs/api/messaging/retrieve), [mark as read](/docs/api/messaging/read), or reply to the message. |
| `data.sender` | string | The customer, in E.164 format, or WhatsApp's user ID for the customer when WhatsApp doesn't share their number. |
| `data.recipient` | string | Your number that received the message, in E.164 format. |
| `data.type` | string | `text`, `image`, `video`, `audio`, `document`, `sticker`, `location`, `contacts`, `interactive`, `button`, `reaction`, or `unsupported`. The message's content is in the field of the same name. |
| `data.reply_to` | string or null | ID of the message the customer replied to, or `null`. Also `null` when that message was deleted after 30 days. A reaction names its message in `reaction.message_id` instead. |
| `data.contact` | object | The customer's WhatsApp profile: `name`, or `null` when WhatsApp didn't share it. |
| `data.occurred_at` | string | ISO 8601 time the customer sent the message, as reported by WhatsApp. |
| `data.referral` | object | Only on a message sent from a Click-to-WhatsApp ad or post: the ad or post the customer came from. |

The content field, such as `data.text` or `data.image`, has the same shape as in [the message object](/docs/api/messaging/retrieve#message-type-objects). Files are described, never linked: download them with [Get message media](/docs/api/messaging/media).

## Handle this event

Store the message, then act on it: answer the customer, route the conversation, or record the button or list choice. A received message opens the [customer service window](/docs/api/messaging/send#customer-service-window) for 24 hours from `data.occurred_at`, so you can reply with any message type, quoting it with `reply_to`.

Message content is personal data. Reading it later with the API needs a key with `whatsapp.full_access`, and Nexiom Connect keeps it, and its files, for 30 days: download what you need to keep.

[Verify the signature](/docs/webhooks/verify-webhooks-requests) before reading the payload. Delivery is at least once: deduplicate by the envelope `id`. Messages can arrive out of order; sort them by `data.occurred_at`.

---

Source: https://connect.nxiom.com/docs/webhooks/whatsapp/received
