# Inbox & Chat

> The shared team inbox for two-way WhatsApp conversations — assignment, tags, notes, and message sending

Source: https://docs.soosh.io/features/inbox/

The Inbox is where your team has day-to-day conversations with customers over WhatsApp. It's a shared, real-time view: incoming messages arrive live over WebSocket, agents reply with text, media, buttons, or approved templates, and each conversation carries its own assignment, tags, and private notes.

## Overview

  **Shared team inbox**

    Every WhatsApp conversation for the organization in one list, ordered by most recent activity.
  
  **Assignment**

    Route a conversation to a specific agent so ownership is clear.
  
  **Tags**

    Colour-coded labels for filtering and triage (e.g. `vip`, `billing`, `lead`).
  
  **Private notes**

    Internal-only annotations on a conversation — never sent to the customer.
  

## The conversation list

The left-hand list is the set of contacts the signed-in user is allowed to see, ordered by `last_message_at` (most recent first, contacts with no messages last). Each row surfaces:

| Field | Meaning |
|---|---|
| **Profile name / phone** | The contact's WhatsApp profile name, falling back to the phone number. Both can be [masked](#phone-masking) org-wide. |
| **Last message preview** | A short preview of the most recent message (`[Image]`, `[Document: …]`, or truncated text). |
| **Unread count** | Number of **incoming** messages that haven't been marked read. |
| **Assigned agent** | The agent the conversation is routed to, if any. |
| **Tags** | The contact's tags. |
| **Service window** | Whether the 24-hour free-form messaging window is open (see below). |

### Search and tag filtering

The list supports server-side search and tag filtering:

- **Search** matches the contact's phone number or profile name (case-insensitive on the profile name).
- **Tag filter** accepts a comma-separated list of tag names and returns contacts that have **any** of them (`?tags=vip,billing`).

These map to the `search` and `tags` query parameters on `GET /api/contacts` — see the [Contacts API](https://docs.soosh.io/reference/api/contacts).

### Unread counts

A conversation's unread count is the number of incoming messages whose status is not yet `read`. Opening the conversation and calling **mark-as-read** clears it (see [Marking messages as read](#marking-messages-as-read)). When the chatbot auto-handles an exchange, it marks the incoming messages read for you so bot-handled chats don't leave a stale unread badge.

## The 24-hour service window

WhatsApp enforces a **24-hour customer service window**. It opens each time the customer sends you a message and lasts 24 hours from that last inbound message. Soosh tracks this per contact as `service_window_open` (true when the last inbound message was less than 24 hours ago).

What the window controls:

| Window state | What you can send |
|---|---|
| **Open** (customer messaged within 24h) | Free-form messages — text, media, interactive buttons, reactions. |
| **Closed** (no inbound in 24h) | **Only pre-approved [message templates](https://docs.soosh.io/features/templates).** Free-form messages will be rejected by Meta. |

> **Note:** This is a WhatsApp Platform rule, not a Soosh limitation. To re-open a conversation after the window closes, send an approved template; once the customer replies, the free-form window opens again.

## Permission-scoped visibility

What a user sees in the inbox depends on their [role's permissions](https://docs.soosh.io/features/roles-permissions):

- **With `chat:read`** — the user can open conversations. Combined with **`contacts:read`**, they see **every** conversation in the organization.
- **Without `contacts:read`** — visibility is narrowed to conversations the user *owns*: contacts **assigned to them** (`assigned_user_id`), plus contacts with an **active agent transfer** to them. This scoping is applied uniformly to listing, reading, messaging, reactions, and notes — an agent cannot read or reply to a conversation they don't own.

Assignment is controlled separately:

- **`chat.assign:write`** and **`contacts:write`** let a user assign or reassign conversations to agents.

> **Tip:** The default **agent** role typically has `chat:read` / `chat:write` but not `contacts:read`, so agents see only their own conversations. Managers and admins have `contacts:read` and see the whole inbox.

## Sending messages

All outbound sends target a contact and resolve a WhatsApp account (the one specified on the request, else the contact's account, else the org's default outgoing account).

### Text

Send a plain text message. Supports replying to an earlier message for threaded context.

```json
POST /api/contacts/{id}/messages
{
  "type": "text",
  "content": { "body": "Hi Sarah, how can we help?" },
  "reply_to_message_id": "…optional…"
}
```

### AI reply suggestions

When your workspace has **AI reply suggestions**, the message box has a **Suggest a reply** button (the sparkles). The AI reads the end of the conversation, your bot's AI instructions and knowledge, and what it knows about the customer, then writes up to 3 drafts. The first shows in the empty message box, in the brand blue (with a blue-to-neon edge) so it can't be mistaken for your own text, with a row under the box to go through them:

- **Tab** (or **Use**) puts the draft in the message box, where you can edit it.
- **↑** and **↓** (or the arrows in the row) show the other drafts.
- **Esc**, **✕** or starting to type dismisses them.

Nothing is sent until you send it, so check it first: AI can be wrong.

- Each set of drafts counts as AI use, like a bot reply, and is charged when the workspace pays for AI.
- If you can see only the current conversation, the drafts come from it alone.
- Whether you sent a draft, and how much you changed it, is recorded to measure how useful the drafts are. A message that keeps less than half of the draft counts as your own.
- If you open another chat before sending a draft you haven't edited, it is taken out of the message box: it was written for the other customer.
- A super admin turns the feature on for a workspace; it also needs AI replies and knowledge.

### AI rewrite

When your workspace has **AI rewrite**, the message box has a **Rewrite** button (the pencil with a spark). Write your reply, then pick how to rewrite it:

- **Fix spelling and grammar** changes nothing else.
- **Make it friendlier**, **Make it more formal** or **Make it shorter** change the tone or length.

The rewrite is asked to keep your language, meaning, names, numbers, links and formatting, but AI can get it wrong. It replaces what you wrote. A row under the box says it was rewritten: **Undo** (or **Ctrl+Z** / **⌘Z** straight away) puts your text back. Undo goes once you change the rewrite, send it or open another chat. If you type while it is being rewritten, your text is kept and the rewrite dropped.

Nothing is sent until you send it, so read it first. Each rewrite counts as AI use and is charged when the workspace pays for AI. A super admin turns the feature on for a workspace; it also needs AI replies and knowledge.

### AI translation

When your workspace has **AI translation**, messages with text have a **Translate** button among the tools that show when you point at a message. The translation appears under the message's own text, in the language you use the app in (English if the app's language isn't one of Soosh's). Click again to hide it.

- Only the message's text (or caption) is translated. Card, account and ID numbers, and codes, PINs and passwords, are removed before it is sent to the AI, and one-time-code messages aren't translated.
- A message already translated into your language in the last 30 days comes back straight away and costs nothing; otherwise each translation counts as AI use.
- If you can see only the current conversation, you can translate only its messages.
- A super admin turns the feature on for a workspace; it also needs AI replies and knowledge.

### AI transfer summaries

When your workspace has **AI transfer summaries**, each time a chat is transferred to agents (by a member, a keyword, a flow or because the bot is off) AI sums up the conversation in a sentence or three: what the customer wants, what they were told, and what is still open. It is written a few seconds after the transfer and shows up on its own:

- **In the chat**, on the strip above the messages (**AI summary · …**) while the transfer is open. When the AI assistant handed the chat over itself, the strip shows its own hand-over note instead (**Handed over by AI · …**), and no summary is written.
- **On the hand-over line** in the conversation, under "Handed to agents", so past transfers keep theirs.
- **In the transfers list**, under the contact's name, in your transfers, the queue and all active transfers.

The AI reads only this conversation, up to the transfer, with codes and card, account and ID numbers removed. It can get things wrong, so check the messages before you act on it. Each summary counts as AI use. A super admin turns the feature on for a workspace; it also needs transfers and AI replies and knowledge.

### Media

Images, video, audio, and documents are sent as `multipart/form-data` with the file, a `type` (`image` / `video` / `audio` / `document`), an optional `caption`, and an optional `whatsapp_account` override.

```
POST /api/messages/media   (multipart/form-data)
file=<binary>  type=image  caption="Your receipt"  contact_id=<uuid>
```

### Interactive messages

The chat send endpoint also sends interactive messages via the `interactive` field:

| Interactive type | What it sends |
|---|---|
| **button** | Up to a few tappable quick-reply buttons under a body text. |
| **list** | A list-style picker of options. |
| **cta_url** | A single call-to-action button that opens a URL. |
| **voice_call** | A WhatsApp [Business Calling](https://docs.soosh.io/features/calling) button that lets the customer call you. Requires the account to have Business Calling enabled. |
| **flow** | Launches a [WhatsApp Flow](https://docs.soosh.io/features/whatsapp-flows) form. The `flow_id` must belong to your organization. |

### Templates

When the service window is closed — or for any structured, pre-approved outreach — send an approved [template](https://docs.soosh.io/features/templates) via `POST /api/messages/template`. You supply the template name or ID plus its body/header/button parameters. The send is rejected if the template isn't `APPROVED`, if required parameters are missing, or if the contact has opted out of marketing and the template is a `MARKETING` template. See the [Messages API](https://docs.soosh.io/reference/api/messages) for the full parameter list.

### Reactions

React to any message with an emoji. Each user can have **one** reaction per message; sending an empty emoji removes your reaction.

```json
POST /api/contacts/{id}/messages/{message_id}/reaction
{ "emoji": "👍" }
```

### Marking messages as read

Opening a conversation should mark its incoming messages read to clear the unread badge:

`POST /api/contacts/{id}/mark-read`

This flips the contact's incoming messages to `read`. If the sending account has **auto read receipts** enabled, Soosh also sends read receipts (the blue ticks) back to the customer over the WhatsApp API.

> **Tip:** Canned responses speed up repetitive replies — type `/shortcut` in the chat input to insert a pre-written message. See [Canned Responses](https://docs.soosh.io/features/canned-responses).

## Private conversation notes

Notes are **internal annotations** on a conversation. They are stored against the contact, visible to your team in the chat view, and **never sent to the customer**.

- Any user with **`chat:read`** can view notes; **`chat:write`** is required to create them.
- A note records its author and timestamps, and displays the author's name.
- **Only the note's author can edit or delete their own note.**
- Note changes broadcast in real time over WebSocket, so teammates viewing the same conversation see them appear live.

Endpoints (see the route table): `GET` / `POST /api/contacts/{id}/notes`, and `PUT` / `DELETE /api/contacts/{id}/notes/{note_id}`.

> **Note:** Notes are the right place for internal context ("customer is escalated, waiting on refund approval"). Anything the customer should see must be sent as a message.

## Contact management

Each conversation is backed by a contact record you can manage from the inbox.

### Assignment

Assign a conversation to an agent to make ownership explicit and — for agents without `contacts:read` — grant them access to it. Assignment requires **`contacts:write`**.

```json
PUT /api/contacts/{id}/assign
{ "user_id": "…agent uuid…" }   // null to unassign
```

The assignee must be a user in the same organization. Unassign by sending `null`.

### Tags

Tags are organization-scoped, colour-coded labels. Manage the tag catalog under **`tags:read` / `tags:write` / `tags:delete`**; valid colours are `blue`, `red`, `green`, `yellow`, `purple`, `gray`. Apply tags to a contact (requires **`contacts:write`**):

```json
PUT /api/contacts/{id}/tags
{ "tags": ["vip", "billing"] }
```

Renaming or deleting a tag in the catalog propagates the change to every contact that carries it. Filter the inbox by tag as described in [Search and tag filtering](#search-and-tag-filtering).

### Contact fields

A contact carries a phone number, profile name, WhatsApp account, tags, and a free-form `metadata` object. Creating and editing contacts requires **`contacts:write`**; both are audit-logged. Re-creating a previously deleted contact restores the soft-deleted record rather than erroring.

### Marketing opt-out

Contacts flagged `marketing_opt_out` cannot be sent `MARKETING`-category templates — such sends are rejected. This keeps bulk and promotional messaging compliant with the customer's stated preference.

## Phone masking

When phone masking is enabled for the organization, phone numbers (and profile names that are themselves phone numbers) are masked in list and detail responses. This is an org-level privacy control applied server-side, so agents never see the raw number.

## Real-time updates

The inbox is driven by the WebSocket hub: new inbound and outbound messages, status changes (sent / delivered / read / failed), reaction updates, and note changes are all broadcast to connected clients for the organization, so the list and open conversation update without a refresh.

## Related

- [Canned Responses](https://docs.soosh.io/features/canned-responses) — quick replies and slash commands
- [Templates](https://docs.soosh.io/features/templates) — pre-approved messages for the closed service window
- [Roles & Permissions](https://docs.soosh.io/features/roles-permissions) — the `chat`, `chat.assign`, `contacts`, and `tags` permissions
- [Contacts API](https://docs.soosh.io/reference/api/contacts) — contact, assignment, tags, and notes endpoints
- [Messages API](https://docs.soosh.io/reference/api/messages) — send text, media, templates, and reactions
