# Parent inbox

Let staff chat with parents inside your product.

> **In a nutshell:** Store message.received callbacks as conversations, reply with free-form text while the 24-hour window is open, fall back to a template when it is closed, and show ticks from message.status.

## Building blocks

| Step | Use |
|---|---|
| Parent writes | [`message.received`](/docs/api/callbacks/message-received) → store under `data.from` |
| Staff replies | [`POST .../messages`](/docs/api/send-message) `type: text` with a `reference` |
| Window closed | `422 outside_service_window` → offer a template |
| Ticks | [`message.status`](/docs/api/callbacks/message-status) → update the reply |
| Parent replies to a message | `data.message.context.id` is the `wamid` of the message they replied to |

## The window, in your UI

Keep `last_incoming_at` per contact (from `message.received`). If it is older than
24 hours, disable the text box and show "Send a template" instead of waiting for the error.

## Matching the parent

`data.from` is the parent's WhatsApp number without `+` (for example `233241234567`).
Normalise the phone numbers in your own records the same way to find the parent,
their children and classes.

## Statuses in the thread

| Status | Show |
|---|---|
| `queued` | clock |
| `sent` | ✓ |
| `delivered` | ✓✓ |
| `read` | blue ✓✓ |
| `failed` | ⚠ with `error.message`, and a retry button that re-sends with a **new** reference |

> [!NOTE]
> Retrying a *failed* message is a new attempt, so it gets a new reference. Retrying
> after a *timeout* (you do not know the outcome) uses the same reference.
