# Chats and contacts

> Docs index: https://wahasend.com/llms.txt · Everything in one file: https://wahasend.com/docs.md · API base URL: https://app.wahasend.com/api/v1

Read what your number sent and received, one conversation per person, and look up contacts. Comes with **Connect** (feature `inbox`). A person is keyed by their phone digits, or by their `@lid` id when WhatsApp hides the number.

<a id="chats-list"></a>

### List conversations

`GET /api/v1/chats`

Newest first, with the last message and the unread count.

- Unlocked by: Connect (`inbox`)
- Per-number key: yes

> A chat known only by its WhatsApp id has `phone: "…@lid"`; when both are known, `lid` is added. A last message with a file adds `lastAttachment`, e.g. `"PDF · invoice.pdf · 240 KB"`.

**Query parameters**

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `limit` | number | no | Default 50, at most 200 conversations (values up to 500 are accepted and give 200). |
| `search` | string | no | Part of a phone number or name. |
| `containerId` | uuid | no | Which of your WhatsApp numbers to use; it always wins. Default: your default number (else any connected one), or a number of the group when [several numbers](https://wahasend.com/docs/phone-numbers.md#several-numbers) is on. Ignored with a per-number key, which always uses its own number. |

**Example**

curl:

```bash
curl "https://app.wahasend.com/api/v1/chats?limit=20" \
  -H "X-API-Key: $WAHASEND_API_KEY"
```

JavaScript:

```js
const res = await fetch('https://app.wahasend.com/api/v1/chats?limit=20', {
  headers: { 'X-API-Key': process.env.WAHASEND_API_KEY },
});
const data = await res.json();
```

Python:

```python
import os
import requests

r = requests.get(
    "https://app.wahasend.com/api/v1/chats?limit=20",
    headers={"X-API-Key": os.environ["WAHASEND_API_KEY"]},
)
print(r.json())
```

**Response 200**

```json
{
  "success": true,
  "chats": [
    {
      "phone": "22212345678",
      "name": "Aïcha",
      "lastMessage": "Merci, à demain",
      "lastDirection": "in",
      "lastAt": "2026-09-30T10:41:07.000Z",
      "unread": 1
    }
  ]
}
```

<a id="chats-thread"></a>

### Read a conversation

`GET /api/v1/chats/:phone`

The last messages with one person, oldest first. Sent messages carry their delivery `status`.

- Unlocked by: Connect (`inbox`)
- Per-number key: yes

**Path parameters**

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `phone` | string | yes | Phone digits (with or without `+`) or the `@lid` id, URL-encoded. |

**Query parameters**

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `limit` | number | no | Default 50, at most 500. |
| `containerId` | uuid | no | Which of your WhatsApp numbers to use; it always wins. Default: your default number (else any connected one), or a number of the group when [several numbers](https://wahasend.com/docs/phone-numbers.md#several-numbers) is on. Ignored with a per-number key, which always uses its own number. |

**Example**

curl:

```bash
curl https://app.wahasend.com/api/v1/chats/22212345678 \
  -H "X-API-Key: $WAHASEND_API_KEY"
```

JavaScript:

```js
const res = await fetch('https://app.wahasend.com/api/v1/chats/22212345678', {
  headers: { 'X-API-Key': process.env.WAHASEND_API_KEY },
});
const data = await res.json();
```

Python:

```python
import os
import requests

r = requests.get(
    "https://app.wahasend.com/api/v1/chats/22212345678",
    headers={"X-API-Key": os.environ["WAHASEND_API_KEY"]},
)
print(r.json())
```

**Response 200**

```json
{
  "success": true,
  "phone": "22212345678",
  "name": "Aïcha",
  "messages": [
    {
      "id": "4f0c6a1e-2b7d-4c1a-9e35-7d8f2a6b1c90",
      "direction": "out",
      "text": "Your order #1042 is ready for pickup.",
      "at": "2026-09-30T10:30:12.000Z",
      "status": "read"
    },
    {
      "id": "9a3e1b77-0c52-4f8e-b1d4-2e6c9f0a7b13",
      "direction": "in",
      "text": "Merci, à demain",
      "at": "2026-09-30T10:41:07.000Z",
      "type": "chat"
    }
  ]
}
```

<a id="chats-unread"></a>

### Unread messages

`GET /api/v1/chats/unread`

Received messages nobody has marked read, oldest first. Does not mark them.

- Unlocked by: Connect (`inbox`)
- Per-number key: yes

**Query parameters**

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `limit` | number | no | Default 100, at most 500. |
| `containerId` | uuid | no | Which of your WhatsApp numbers to use; it always wins. Default: your default number (else any connected one), or a number of the group when [several numbers](https://wahasend.com/docs/phone-numbers.md#several-numbers) is on. Ignored with a per-number key, which always uses its own number. |

**Example**

curl:

```bash
curl https://app.wahasend.com/api/v1/chats/unread \
  -H "X-API-Key: $WAHASEND_API_KEY"
```

JavaScript:

```js
const res = await fetch('https://app.wahasend.com/api/v1/chats/unread', {
  headers: { 'X-API-Key': process.env.WAHASEND_API_KEY },
});
const data = await res.json();
```

Python:

```python
import os
import requests

r = requests.get(
    "https://app.wahasend.com/api/v1/chats/unread",
    headers={"X-API-Key": os.environ["WAHASEND_API_KEY"]},
)
print(r.json())
```

**Response 200**

```json
{
  "success": true,
  "messages": [
    {
      "id": "9a3e1b77-0c52-4f8e-b1d4-2e6c9f0a7b13",
      "phone": "22212345678",
      "name": "Aïcha",
      "text": "Merci, à demain",
      "type": "chat",
      "at": "2026-09-30T10:41:07.000Z"
    }
  ]
}
```

<a id="chats-ack"></a>

### Mark messages read

`POST /api/v1/chats/unread/ack`

Marks the given received messages as read in WahaSend (the contact sees no blue ticks). A per-number key marks only its own number's messages.

- Unlocked by: Connect (`inbox`)
- Per-number key: yes

**Request body**

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `ids` | uuid[] | yes | 1–500 message ids from the unread list. |

**Example**

curl:

```bash
curl -X POST https://app.wahasend.com/api/v1/chats/unread/ack \
  -H "X-API-Key: $WAHASEND_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "ids": [
    "9a3e1b77-0c52-4f8e-b1d4-2e6c9f0a7b13"
  ]
}'
```

JavaScript:

```js
const res = await fetch('https://app.wahasend.com/api/v1/chats/unread/ack', {
  method: 'POST',
  headers: { 'X-API-Key': process.env.WAHASEND_API_KEY, 'Content-Type': 'application/json' },
  body: JSON.stringify({
    "ids": [
      "9a3e1b77-0c52-4f8e-b1d4-2e6c9f0a7b13"
    ]
  }),
});
const data = await res.json();
```

Python:

```python
import os
import requests

r = requests.post(
    "https://app.wahasend.com/api/v1/chats/unread/ack",
    headers={"X-API-Key": os.environ["WAHASEND_API_KEY"]},
    json={
        "ids": [
            "9a3e1b77-0c52-4f8e-b1d4-2e6c9f0a7b13",
        ],
    },
)
print(r.json())
```

**Response 200**

```json
{
  "success": true,
  "marked": 1
}
```

<a id="chats-read"></a>

### Mark a conversation read

`POST /api/v1/chats/:phone/read`

Marks everything received from this person as read (with a per-number key: on its number only).

- Unlocked by: Connect (`inbox`)
- Per-number key: yes

**Path parameters**

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `phone` | string | yes | Phone digits or `@lid` id. |

**Example**

curl:

```bash
curl -X POST https://app.wahasend.com/api/v1/chats/22212345678/read \
  -H "X-API-Key: $WAHASEND_API_KEY"
```

JavaScript:

```js
const res = await fetch('https://app.wahasend.com/api/v1/chats/22212345678/read', {
  method: 'POST',
  headers: { 'X-API-Key': process.env.WAHASEND_API_KEY },
});
const data = await res.json();
```

Python:

```python
import os
import requests

r = requests.post(
    "https://app.wahasend.com/api/v1/chats/22212345678/read",
    headers={"X-API-Key": os.environ["WAHASEND_API_KEY"]},
)
print(r.json())
```

**Response 200**

```json
{
  "success": true,
  "marked": 3
}
```

<a id="contacts-search"></a>

### Find contacts

`GET /api/v1/contacts`

Searches the phone's contacts by saved name, WhatsApp name or part of the number.

- Unlocked by: Connect (`inbox`)
- Per-number key: yes

**Query parameters**

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `search` | string | yes | 1–100 characters. |
| `limit` | number | no | Default 10, at most 50. |

**Example**

curl:

```bash
curl "https://app.wahasend.com/api/v1/contacts?search=A%C3%AFcha" \
  -H "X-API-Key: $WAHASEND_API_KEY"
```

JavaScript:

```js
const res = await fetch('https://app.wahasend.com/api/v1/contacts?search=A%C3%AFcha', {
  headers: { 'X-API-Key': process.env.WAHASEND_API_KEY },
});
const data = await res.json();
```

Python:

```python
import os
import requests

r = requests.get(
    "https://app.wahasend.com/api/v1/contacts?search=A%C3%AFcha",
    headers={"X-API-Key": os.environ["WAHASEND_API_KEY"]},
)
print(r.json())
```

**Response 200**

```json
{
  "success": true,
  "contacts": [
    {
      "id": "5e1b7c3a-9d2f-4a86-b0e4-1c7f9a3d5b62",
      "name": "Aïcha",
      "phone": "22212345678",
      "lid": "104937261508834@lid",
      "saved": true,
      "optedOut": false
    }
  ]
}
```

**Errors to expect**

- [`VALIDATION_ERROR`](https://wahasend.com/docs/errors.md#validation_error) (400): Validation failed. Check the details for specific field errors.

<a id="contacts-count"></a>

### Count contacts

`GET /api/v1/contacts/count`

How many contacts are known, and when the phone's recent history was last imported.

- Unlocked by: Connect (`inbox`)
- Per-number key: yes

**Example**

curl:

```bash
curl https://app.wahasend.com/api/v1/contacts/count \
  -H "X-API-Key: $WAHASEND_API_KEY"
```

JavaScript:

```js
const res = await fetch('https://app.wahasend.com/api/v1/contacts/count', {
  headers: { 'X-API-Key': process.env.WAHASEND_API_KEY },
});
const data = await res.json();
```

Python:

```python
import os
import requests

r = requests.get(
    "https://app.wahasend.com/api/v1/contacts/count",
    headers={"X-API-Key": os.environ["WAHASEND_API_KEY"]},
)
print(r.json())
```

**Response 200**

```json
{
  "success": true,
  "count": 312,
  "historyImportedAt": "2026-09-29T18:03:55.000Z",
  "importing": false
}
```

<a id="contacts-sync"></a>

### Update from the phone

`POST /api/v1/contacts/sync`

Re-reads the address book now and imports recent chats in the background. The number must be connected.

- Unlocked by: Connect (`inbox`)
- Per-number key: yes

**Request body**

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `containerId` | uuid | no | Which of your WhatsApp numbers to use; it always wins. Default: your default number (else any connected one), or a number of the group when [several numbers](https://wahasend.com/docs/phone-numbers.md#several-numbers) is on. Ignored with a per-number key, which always uses its own number. |

**Example**

curl:

```bash
curl -X POST https://app.wahasend.com/api/v1/contacts/sync \
  -H "X-API-Key: $WAHASEND_API_KEY"
```

JavaScript:

```js
const res = await fetch('https://app.wahasend.com/api/v1/contacts/sync', {
  method: 'POST',
  headers: { 'X-API-Key': process.env.WAHASEND_API_KEY },
});
const data = await res.json();
```

Python:

```python
import os
import requests

r = requests.post(
    "https://app.wahasend.com/api/v1/contacts/sync",
    headers={"X-API-Key": os.environ["WAHASEND_API_KEY"]},
)
print(r.json())
```

**Response 200**

```json
{
  "success": true,
  "contacts": 312,
  "saved": 240,
  "lidsLinked": 118,
  "messagesLinked": 6,
  "importing": true
}
```

**Errors to expect**

- [`NO_SESSION_CONFIGURED`](https://wahasend.com/docs/errors.md#no_session_configured) (400): This account has no connected WhatsApp number.
- [`WAHA_ERROR`](https://wahasend.com/docs/errors.md#waha_error) (502): WhatsApp could not complete the request. Try again.
- [`WAHA_SESSION_ERROR`](https://wahasend.com/docs/errors.md#waha_session_error) (503): WhatsApp is not connected.
