# Receive messages

> Receive your customers' messages by webhook, reply within the 24-hour window and find them in the history.

When a customer writes to one of your numbers, Bref Point Inbox stores the message and sends a **`message.received`** event to your webhook endpoints. Declare one first (see [Webhooks](/docs/guides/webhooks)).

## The event

```json title="message.received"
{
  "id": "8dc9eca4-2eff-46de-80aa-0ac9674dd1ae",
  "type": "message.received",
  "createdAt": "2026-11-12T06:09:17.388Z",
  "data": {
    "messageId": "4f21edc3-047e-4f75-819a-1e69953f40a3",
    "waMessageId": "wamid.HBgM…",
    "phoneNumberId": "fb10613a-8a2c-4340-87ff-192082ffaf1f",
    "from": "237611111111",
    "type": "text",
    "content": { "text": { "body": "Hello, I'd like to reschedule my appointment" } },
    "contactName": "Awa",
    "occurredAt": "2026-11-12T06:09:17.402Z"
  }
}
```

| `data` field | Description |
|---|---|
| `messageId` | The message's identifier at Bref Point Inbox. |
| `waMessageId` | The message's identifier at WhatsApp. |
| `phoneNumberId` | The number that received the message (the number's `id`, as when sending). |
| `from` | The sender's number, without the "+". |
| `type` | `text`, `image`, `document`, `audio`, `video`, `location`, `sticker`, `button`… as declared by Meta. |
| `content` | The content, under a key named after the type: `{ "text": { "body": … } }`, `{ "image": { "id": …, "caption": … } }`… The exact shape is Meta's. |
| `contactName` | The sender's WhatsApp profile name, if known. |

<Callout type="note" title="Received media">
For received media, `content` contains the media's identifier at Meta. Downloading the file through the API is not yet available.
</Callout>

## Reply

A received message **opens the 24-hour window** for this number and this sender: you can reply with a free-form message.

```bash
curl -X POST "$INBOX_API/messages" \
  -H "Authorization: Bearer $INBOX_KEY" -H "Content-Type: application/json" \
  -d '{ "phoneNumberId": "<data.phoneNumberId>", "to": "+<data.from>", "type": "text",
        "text": { "body": "Of course, which time slot would suit you?" } }'
```

The window is calculated **per sender and per number**: a message from another customer doesn't open this one's window.

## Avoid processing twice

Events can arrive **more than once** (retry after a timeout, manual replay, resend by Meta). Bref Point Inbox deduplicates received messages when storing them, but **your receiver** must also be tolerant: the event `id` (and `data.messageId`) is stable, so ignore what you've already processed.

## Find received messages

<ApiExample method="GET" path="/messages" />

Add `?direction=inbound` to see only received messages.

## Test without a phone

The [sandbox](/docs/guides/sandbox) makes a message "arrive" on demand and triggers your real webhook:

<ApiExample method="POST" path="/sandbox/simulate/inbound-message" />
