# Messages

With the API, a bot can write to a contact from your own system: remind them of an appointment, send a receipt, reply from a CRM. Use the **sendMessage** method for this — it sends text, an image or a file right away and tells you whether the message went out.

The **sendMessageToQueue** method is deprecated and will be switched off — use sendMessage in new integrations.

The message is saved in the contact's conversation under the name "API" — you can see it in [Conversations and messaging](https://support.watbot.org/chatbots/messages/dialogs). It does not start the bot's scenario.

## sendMessage

Sends a contact text, an image or a file.

```endpoint
POST https://watbot.org/api/v1/sendMessage
```

The contact is specified in one of two ways: by contact ID — `contact_id`, or by bot and messenger ID — `bot_id`, `messenger` and `contact_external_id` together.

| Parameter | Type | Required | Description |
|---|---|---|---|
| `contact_id` | number | yes, without `messenger` | Contact ID |
| `bot_id` | number | yes, without `contact_id` | Bot ID |
| `messenger` | string | yes, without `contact_id` | The contact's messenger: `telegram`, `max`, `viber`, `vk` or `web` (website chat) |
| `contact_external_id` | string | yes, without `contact_id` | The contact's ID in the messenger, up to 255 characters — see below |
| `text` | string | yes, without `image` and `file` | Message text. With an image or file, it becomes the caption |
| `image` | string | yes, without `text` and `file` | Link to an image |
| `file` | string | yes, without `text` and `image` | Link to a file |
| `filename` | string | no | File name shown to the recipient. Non-Latin letters are transliterated; any character other than letters, digits, `.`, `_` and `-` is replaced with `_` |

What to pass in `contact_external_id`:

| `messenger` | Value |
|---|---|
| `telegram` | Telegram user ID (the contact's `telegram_id` field) or their phone |
| `max` | MAX user ID (the `max_user_id` field) or phone |
| `viber` | Viber user ID (the `viber_id` field) or phone |
| `vk` | VK user ID — `700123456` (the older form `vk700123456` also works) — or phone |
| `web` | The visitor ID of the website chat |

The phone is compared with the contact's number (the `phone` field in the contact methods' responses) character for character. The most reliable option is `contact_id` — the [contact](https://support.watbot.org/api/contacts) methods return it.

If both `image` and `file` are passed, the image is sent.

```bash title="Request: text"
curl -X POST "https://watbot.org/api/v1/sendMessage" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{"contact_id": 4815162, "text": "Emily, your order #1042 has been shipped."}'
```

```bash title="Request: file by Telegram ID"
curl -X POST "https://watbot.org/api/v1/sendMessage" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{
    "bot_id": 12345,
    "messenger": "telegram",
    "contact_external_id": "123456789",
    "file": "https://example.com/invoices/1042.pdf",
    "filename": "Invoice 1042.pdf",
    "text": "Your invoice"
  }'
```

```json title="Response 200"
{
  "success": true
}
```

```json title="Response 404"
{
  "message": "Contact not found"
}
```

**Sending limit.** No more than 10 messages per 10 seconds to one messenger. The counter is kept per account and separately for each messenger: the 10 seconds start with the first message, then the counter resets. Rejected requests do not count and do not extend the window. A `429` response carries a `Retry-After` header with the number of seconds to wait before retrying. The general API rate limit applies separately — see [Limits](https://support.watbot.org/api#limits).

Method errors (general ones are under [Errors](https://support.watbot.org/api#errors)):

| Code | When | Response |
|---|---|---|
| `404` | The contact or bot is not among yours: no such ID, it belongs to another account or was deleted; no contact with this `messenger` and `contact_external_id` in the bot | `{"message": "Contact not found"}` or `{"message": "Bot not found"}` |
| `422` | None of `text`, `image`, `file`; the link in `image` or `file` is not a URL; `contact_id` or `bot_id` is not a positive integer | `{"message": "…", "errors": {…}}` |
| `429` | The sending limit for this messenger is exceeded | `{"error": "Message sending limit reached for telegram"}` |
| `501` | The contact comes from a channel that sending is no longer supported for | `{"error": "Sending messages to … is not supported"}` |

Error texts come in the language from the `Accept-Language` header.

## sendMessageToQueue

> [!WARNING]
> This method is deprecated and will be switched off on 1 December 2026 — use [sendMessage](https://support.watbot.org/api/messages#sendmessage) instead. Until then, every response of the method carries the headers `Deprecation: true` and `Sunset: Tue, 01 Dec 2026 00:00:00 GMT`. From 1 December 2026 (00:00 UTC), the method responds with status `410`: `{"error": "This API method was removed on 2026-12-01.", "code": "method_removed"}`.

Puts a text message to a contact in a queue. The queue is processed once a minute.

```endpoint
POST https://watbot.org/api/v1/sendMessageToQueue
```

The contact is looked up among the contacts of all your bots, or, with `bot_id`, only among that bot's contacts. Pass at least one of `contact_id`, `bitrix_contact_id`, `phone`; if you pass several, the contact must match all of them. If several contacts match `phone` or `bitrix_contact_id` and `bot_id` is not passed, the message is queued for one of them: first a contact of a messenger the method can send to who has not blocked the bot, then one whose `phone` field (WhatsApp) matches exactly, then the one with the most recent conversation. The response headers `X-Contact-Id` and `X-Contact-Ambiguous: true` show who the message went to. With `bot_id` no choice is made: if several contacts of that bot match too, the method responds with `422` and does not queue the message — pass `contact_id`.

| Parameter | Type | Required | Description |
|---|---|---|---|
| `contact_id` | number | one of three | Contact ID |
| `bitrix_contact_id` | number | one of three | ID of the Bitrix24 contact linked to the bot's contact |
| `phone` | string | one of three | Contact's phone, up to 20 characters. Spaces, brackets, hyphens and `+` are removed; a leading `8` is replaced with `7` |
| `bot_id` | number | no | ID of the bot to send from. Pass it when the number or Bitrix24 ID belongs to contacts of several of your bots |
| `text` | string | yes | Message text, up to 1024 characters |
| `message_id` | string | no | Your own message ID, up to 255 characters. Protects against duplicates: a repeated request with the same `message_id` to the same contact does not queue the message again while the earlier one is waiting or already sent — the response is the same `201`. After a sending error, a repeat queues the message again |

```bash title="Request"
curl -X POST "https://watbot.org/api/v1/sendMessageToQueue" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{"contact_id": 4815162, "text": "Reminder: your appointment is tomorrow at 11:00 AM."}'
```

```json title="Response 422"
{
  "error": "Contact not found"
}
```

```json title="Response 422: contact_id needed"
{
  "message": "Several contacts of the bot match this data — specify contact_id.",
  "errors": {
    "contact_id": ["Several contacts of the bot match this data — specify contact_id."]
  }
}
```

A successful response is status `201` with an empty body and the chosen contact's ID in the `X-Contact-Id` header. The cleaned-up `phone` must match the contact's number character for character. For a contact from a channel that sending is no longer supported for, the method responds with `422`: `{"error": "Messenger is not supported"}`. Contacts who have unsubscribed from the bot or blocked it do not receive messages from the queue — such messages are removed from the queue on its next run.
