# Отправка WHATSAPP
::::::{tip}
Для получения возможности отправки WHATSAPP-сообщений необходимо заполнить [анкету](https://i-dgtl.ru/wa-registration-2/), после чего будет зарегистрировано имя отправителя и шаблон для отправки сообщений.
Получение WHATSAPP-шаблонов и преобразование в сообщения описано [здесь](../templates/get.md#formirovanie-whatsapp-soobsheniya).
::::::
::::::{tip}
Отправка сообщений происходит в режиме чата:
* если чат инициируется клиентом, первое сообщение должно соответствовать зарегистрированному шаблону. После каждого ответа абонента открывается 24-часовое окно для отправки сообщений с произвольным содержанием. Если абонент не ответил, клиент может отправлять сообщения пользователю вне рамок 24-часового окна с использованием заранее зарегистрированных шаблонов сообщений;
* если чат инициируется абонентом, в течение 24-часового окна клиент может отправлять сообщения с произвольным содержанием.
::::::
## Отправка WHATSAPP-сообщений
`POST` `https://direct.i-dgtl.ru/api/v1/message`
Метод позволяет отправлять массив одиночных сообщений **(от 1 до 1000)**
#### Headers
| Name | Type | Description |
| ----------------------------------------------- | ------ | ------------------ |
| Authorization\* | string | `Basic {TOKEN_1}` |
| Content-Type\* | string | `application/json` |
#### Request Body
| Name | Type | Description |
| --------------------------------------------- | ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| channelType\* | string | Канал отправки (`WHATSAPP`) |
| senderName\* | string | Имя отправителя. Допускаются WHATSAPP-имена в статусе "Одобрено" |
| destination\* | string | Номер абонента |
| content\* | object | Контент сообщения. Ниже описаны возможные варианты содержимого. |
| tags | array | Теги сообщения (массив строк). Каждый тег должен соответствовать выражению `^\w+$` (допускаются буквы в любом регистре, цифры и нижнее подчеркивание "\_") |
| useLocalTime | boolean |
Флаг, отвечающий за таймзону, в которой будет отправлено сообщение:
true – отправка в таймзоне абонента
false – отправка по МСК
По умолчанию true
|
| localSendTime | string | Нижняя граница допустимого времени отправки сообщения (с учетом значенияuseLocalTime)
Дата в формате YYYY-MM-DD hh:mm:ss в диапазоне от (текущее время в UTC - 12 часов) до (текущее время в UTC + 7 дней)
По умолчанию сообщение будет отправлено сразу
|
| localCompletionTime | string | Верхняя граница допустимого времени отправки сообщения (с учетом `useLocalTime`) в диапазоне от `localSendTime` до (текущее время в UTC + 70 дней) |
| ttl | integer | Время жизни сообщения в секундах. По истечении ttl сообщению устанавливается финальный статус.
60 ≤ ttl ≤ 86400
|
| hours | array | Допустимые часы отправки (массив чисел). В массиве могут быть переданы целые числа от 0 до 23, каждое из которых соответствует разрешенному для отправки интервалу с учетом `useLocalTime`; значения должны быть уникальны. |
| days | array | Допустимые дни отправки (массив чисел). В массиве могут быть переданы целые числа от 1 (пн) до 7 (вс), каждое из которых соответствует разрешенному для отправки дню недели; значения должны быть уникальны. |
| shortUrl | boolean | Флаг, отвечающий за сокращение ссылок в сообщении:
true - ссылки в тексте сообщения будут сокращены
По умолчанию false
|
| callbackUrl | string | Адрес для отправки callback |
| callbackEvents | array | События, по которым будут отправлены callback (массив строк). При наличии `callbackUrl` и отсутствии `callbackEvents` в запросе, будет отправлен callback по событию `delivered`. |
| externalMessageId | string | Внутренний id сообщения в вашей системе. До 100 символов |
::::::{tab-set}
:::::{tab-item} 200
В случае успешного запроса возвращается ответ, в котором перечислены идентификаторы сообщений и коды результата. При значении errors = false гарантируется, что все переданные сообщения успешно созданы.
```
{
"errors": false,
"items": [
{
"messageUuid": "063474ec-a34f-4558-90c5-984395000004",
"code": 201
},
{
"messageUuid": "063564ec-a34f-4558-90c5-984395000005",
"code": 201
}
]
}
```
:::::
:::::{tab-item} 401
Использование невалидного токена / отсутствие заголовка авторизации.
::::{tab-set}
:::{tab-item} 4012
```
{
"error": {
"code": 4012,
"msg": "Bad credentials"
}
}
```
:::
:::{tab-item} 4010
```
{
"error": {
"code": 4010,
"msg": "Not Authenticated"
}
}
```
:::
::::
:::::
:::::{tab-item} 403
Использование неподходящего токена.
```
{
"error": {
"code": 4030,
"msg": "Access Denied"
}
}
```
:::::
:::::{tab-item} 422
Невалидные параметры в теле запроса; ниже приведены несколько примеров ответа.
```
{
"error": {
"code": 4220,
"msg": "Invalid msisdn"
}
}
-----------------------------------------------------------------------------
{
"error": {
"code": 4220,
"msg": "Invalid text length in viber content (0)"
}
}
-----------------------------------------------------------------------------
{
"error": {
"code": 4220,
"msg": "Invalid caption length in viber content (3)"
}
}
-----------------------------------------------------------------------------
{
"error": {
"code": 4220,
"msg": "Invalid caption length in viber content (3)"
}
}
```
:::::
:::::{tab-item} 402
Payment Required. Недостаточно средств на балансе.
```javascript
{
"error": {
"code": 402,
"msg": "Insufficient funds"
}
}
```
:::::
::::::
::::::{tip}
Рекомендуемое время ожидания ответа: 70 секунд.\
Как правило, ответ на запрос возвращается не более чем за несколько секунд, но таймаут величиной в 70 секунд позволяет гарантированно получить ответ на запрос, в том числе в ситуациях повышенной нагрузки.
::::::
::::::{tip}
Для данного канала рекомендуется использовать ttl не менее 24 часов, так как сервис может доставить сообщение даже спустя 24 часа неактивности абонента (например, если устройство было выключено).
::::::
::::::{tip}
Для использования личного домена в сокращенных ссылках необходимо обратиться в поддержку
::::::
Возможные варианты перечислений:
| Параметр | Варианты |
| -------------- | --------------------------------------------------------------------- |
| callbackEvents | [События для отправки callback](../extra/references/#callback-events) |
## Текстовое сообщение
Текстовое WHATSAPP-сообщение, помимо текста, может содержать заголовок, подпись и кнопки.
Для отправки текстового WHATSAPP-сообщения используется следующий объект `content`:
```
{
"contentType": "text",
"text": "текст whatsapp-сообщения",
"header": {
"text": "Заголовок сообщения"
},
"footer": {
"text": "Подпись сообщения"
},
"buttons": [
{
"text": "текст кнопки",
"url": "https://i-dgtl.ru"
},
{
"text": "текст второй кнопки",
"phone": "78124269988"
}
]
}
```
| Параметр | Тип | Описание |
| ------------------- | ------------------------------------------- | --------------------------------------------------------------------------------------------------------------------- |
| contentType | string
required
| Тип контента (`text`) |
| text | string
required
| Текст сообщения; строка в кодировке UTF-8 без Byte Order Mark
От 1 до 1000 символов
|
| header | object
optional
| Заголовок сообщения |
| header.text | string
optonal
| Текст для заголовка
От 1 до 60 символов
|
| header.documentUrl | string
optional
| Ссылка на документ для заголовка. Документ должен быть в формате PDF. |
| header.documentName | string
optional
| Название документа для заголовка; может присутствовать только при наличии documentUrl |
| header.imageUrl | string
optional
| Ссылка на изображение для заголовка. Изображение должно быть в формате JPG или PNG |
| footer | object
optional
| Подпись сообщения |
| footer.text | string
optional
| Текст для подписи; от 1 до 60 символов |
| buttons | array (objects)
optional
| Массив с объектами кнопок |
| buttons.text | string
optonal
| Текст кнопки; от 1 до 25 символов |
| buttons.url | string
optional
| Ссылка, на которую происходит переход при нажатии на кнопку; от 1 до 1000 символов; должна начинаться с `http` |
| buttons.phone | string
optional
| Телефонный номер, на который предлагается сделать вызов при нажатии на кнопку; от 1 до 1000 символов |
| buttons.payload | string
optional
| Скрытый текст, который будет передан во входящем сообщении, если пользователь нажмет на кнопку; от 1 до 1000 символов |
### Заголовок в сообщениях
в объекте `header` допускается использовать только одно из:
* `text`
* `documentUrl` и `documentName`
* `imageUrl`
### Кнопки в сообщениях
* кнопки передаются объектами в массиве `buttons`
* в каждом объекте обязателен `text`
* существует два типа кнопок:
* кнопка с ссылкой: содержит `text` и `url` или `text` и `phone`
* кнопка с текстом: содержит `text` и `payload`
* в одном сообщении допускается передача кнопок только одного типа (то есть передача `payload`-кнопок вместе с `url/phone`-кнопками не допускается)
* в сообщении допускается только одна кнопка с параметром `url`
* в сообщении допускается только одна кнопка с параметром `phone`
* при передаче кнопок с текстом допускается не более трех объектов в массиве
* при передаче кнопок с ссылкой допускается не более двух объектов в массиве
* наличие кнопок в сообщении не влияет на возможность наличия заголовка и подписи
### Примеры объектов
::::::{tab-set}
:::::{tab-item} Текст
```
{
"contentType": "text",
"text": "текст сообщения"
}
```
:::::
:::::{tab-item} С заголовком
```
{
"contentType": "text",
"text": "Текст сообщения",
"header": {
"documentUrl": "https://example.com/document.pdf",
"documentName": "document.pdf"
}
}
```
:::::
:::::{tab-item} С заголовком и подписью
```
{
"contentType": "text",
"text": "Текст сообщения",
"header": {
"imageUrl": "https://example.com/image.png"
},
"footer": {
"text": "Подпись сообщения"
}
}
```
:::::
:::::{tab-item} С текстовыми кнопками
```
{
"contentType": "text",
"text": "Текст сообщения",
"buttons": [
{
"text": "текст кнопки 1",
"payload": "id=1"
},
{
"text": "текст кнопки 2",
"payload": "id=2"
}
]
}
```
:::::
:::::{tab-item} С кнопками и ссылками
```
{
"contentType": "text",
"text": "Текст сообщения",
"buttons": [
{
"text": "текст кнопки 1",
"url": "https://i-dgtl.ru/"
},
{
"text": "текст кнопки 2",
"phone": "78124269988"
}
]
}
```
:::::
::::::
## Аутентификационное сообщение
Для отправки аутентификационного WHATSAPP-сообщения используется следующий объект content:
```
{
"contentType": "authentication",
"text": "1234",
"lang": "ru",
"addSecurityRecommendation": true,
"codeExpirationMinutes": 10,
"buttons": [
{
"text": "Скопировать"
}
]
}
```
| Параметр | Тип | Описание |
| ------------------------- | ----------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| contentType | string
required
| Тип контента (`authentication`) |
| text | string
required
| Текст сообщения, не более 15 символов |
| lang | string
required
| Язык сообщения, не более 2 символов |
| addSecurityRecommendation | boolean
required
| Определяет, будет ли сообщение содержать предустановленный текст безопасности |
| codeExpirationMinutes | integer
optional
| Срок действия пароля или кода в минутах. Если не указывать этот параметр, сообщение не будет содержать предупреждение об истечении срока действия пароля. **Допустимые значения: от 1 до 90**. |
| buttons | array
required
| Массив кнопок. Должен содержать ровно одну кнопку. |
| buttons.text | string
required
| Текст на кнопке, не более 25 символов |
::::::{tip}
Значения параметров lang, addSecurityRecommendation, codeExpirationMinutes, buttons.text должны соответствовать указанным в зарегистрированном шаблоне
::::::
## Сообщение с изображением
Для отправки WHATSAPP-сообщения с изображением используется следующий объект `content`:
```
{
"contentType": "image",
"imageUrl": "https://image.png",
"imageName": "Изображение"
}
```
| Параметр | Тип | Описание |
| ----------- | ------------------------------------- | ---------------------- |
| contentType | string
required
| Тип контента (`image`) |
| imageUrl | string
required
| Ссылка на изображение |
| imageName | string
required
| Название изображения |
## Сообщение с документом
Для отправки WHATSAPP-сообщения с документом используется следующий объект `content`:
```
{
"contentType": "document",
"documentUrl": "https://document.pdf",
"documentName": "Документ"
}
```
| Параметр | Тип | Описание |
| ------------ | ------------------------------------- | ------------------------- |
| contentType | string
required
| Тип контента (`document`) |
| documentUrl | string
required
| Ссылка на документ |
| documentName | string
required
| Название документа |
## Сообщение с видео
Для отправки WHATSAPP-сообщения с видео используется следующий объект `content`:
```
{
"contentType": "video",
"videoUrl": "https://video.mp4",
"videoName": "Название видео"
}
```
| Параметр | Тип | Описание |
| ----------- | ------------------------------------- | ---------------------- |
| contentType | string
required
| Тип контента (`video`) |
| videoUrl | string
required
| Ссылка на видео |
| videoName | string
optional
| Название видео |
## Пример запроса
::::::{tab-set}
:::::{tab-item} JSON
```
POST https://direct.i-dgtl.ru/api/v1/message
Authorization: Basic QWxhZGRpbjp...
Content-Type: application/json
[
{
"senderName": "SENDER",
"channelType": "WHATSAPP",
"content": {
"contentType": "text",
"text": "Текст WHATSAPP-сообщения",
},
"destination": "7818242882",
}
]
```
:::::
:::::{tab-item} cURL
```
curl -X POST 'https://direct.i-dgtl.ru/api/v1/message' \
-H 'Content-Type: application/json' \
-H 'Authorization: Basic QWxhZGRpbjpvc...' \
-d '[{"senderName":"SENDER","channelType":"WHATSAPP","content":{"contentType":"text","text":"Текст WHATSAPP-сообщения"},"destination":"7818242882"}]'
```
:::::
:::::{tab-item} Python
```
import requests
import json
url = "https://direct.i-dgtl.ru/api/v1/message"
payload = json.dumps([
{
"senderName": "SENDER",
"channelType": "WHATSAPP",
"destination": "7818242882",
"content": {
"contentType": "text",
"text": "Текст WHATSAPP-сообщения"
}
}
])
headers = {
'Content-Type': 'application/json'
}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
```
:::::
:::::{tab-item} JavaScript
```
const myHeaders = new Headers();
myHeaders.append("Content-Type", "application/json");
const raw = JSON.stringify([
{
"senderName": "SENDER",
"channelType": "WHATSAPP",
"destination": "7818242882",
"content": {
"contentType": "text",
"text": "Текст WHATSAPP-сообщения"
}
}
]);
const requestOptions = {
method: "POST",
headers: myHeaders,
body: raw,
redirect: "follow"
};
fetch("https://direct.i-dgtl.ru/api/v1/message", requestOptions)
.then((response) => response.text())
.then((result) => console.log(result))
.catch((error) => console.error(error));
```
:::::
:::::{tab-item} Java
```
OkHttpClient client = new OkHttpClient().newBuilder()
.build();
MediaType mediaType = MediaType.parse("application/json");
RequestBody body = RequestBody.create(mediaType, "[\n {\n \"senderName\": \"SENDER\",\n \"channelType\": \"WHATSAPP\",\n \"destination\": \"7818242882\",\n \"content\": {\n \"contentType\": \"text\",\n \"text\": \"Текст WHATSAPP-сообщения\"\n }\n }\n]");
Request request = new Request.Builder()
.url("https://direct.i-dgtl.ru/api/v1/message")
.method("POST", body)
.addHeader("Content-Type", "application/json")
.build();
Response response = client.newCall(request).execute();
```
:::::
:::::{tab-item} PHP
```
'application/json'
];
$body = '[
{
"senderName": "SENDER",
"channelType": "WHATSAPP",
"destination": "7818242882",
"content": {
"contentType": "text",
"text": "Текст WHATSAPP-сообщения"
}
}
]';
$request = new Request('POST', 'https://direct.i-dgtl.ru/api/v1/message', $headers, $body);
$res = $client->sendAsync($request)->wait();
echo $res->getBody();
```
:::::
:::::{tab-item} Go
```
package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://direct.i-dgtl.ru/api/v1/message"
method := "POST"
payload := strings.NewReader(`[
{
"senderName": "SENDER",
"channelType": "WHATSAPP",
"destination": "7818242882",
"content": {
"contentType": "text",
"text": "Текст WHATSAPP-сообщения"
}
}
]`)
client := &http.Client {
}
req, err := http.NewRequest(method, url, payload)
if err != nil {
fmt.Println(err)
return
}
req.Header.Add("Content-Type", "application/json")
res, err := client.Do(req)
if err != nil {
fmt.Println(err)
return
}
defer res.Body.Close()
body, err := io.ReadAll(res.Body)
if err != nil {
fmt.Println(err)
return
}
fmt.Println(string(body))
}
```
:::::
::::::
::::::{tip}
В примере указан минимальный набор параметров, который позволяет моментально отправить WHATSAPP-сообщение (при наличии зарегистрированного имени отправителя и шаблона). Вы можете кастомизировать контент, время отправки, настроить коллбэки и добавить теги, используя опциональные параметры, описанные выше на данной странице.
::::::