API v2 (бета)
Сообщения
Отправляйте сообщение сразу или в заданное время на номер телефона, в группу WhatsApp, сохранённому контакту или на имя пользователя Telegram. Отправляйте одно и то же сообщение до 1000 получателям одним запросом, читайте историю, следите за статусом сообщения и отменяйте его, пока оно ожидает.
| Операция | Endpoint | Область доступа |
|---|---|---|
| Отправка сообщения | POST /api/v2/messages | messages:send |
| Отправка многим получателям | POST /api/v2/messages/batch | messages:send |
| Список сообщений | GET /api/v2/messages | messages:read |
| Получение сообщения | GET /api/v2/messages/{id} | messages:read |
| Отмена сообщения | DELETE /api/v2/messages/{id} | messages:send |
Ключи, ошибки, Idempotency-Key и лимиты работают так, как описано в обзоре API v2. Чтобы узнавать об отправке или ошибке без опроса, добавьте webhook endpoint.
Отправка сообщения#
https://wbiztool.com/api/v2/messagesТело запроса: JSON (application/json)
Сообщение ставится в очередь, и ответ приходит раньше, чем оно уйдёт: HTTP 202 и Message в статусе queued (или scheduled, если send_at в будущем). Следите за ним через Получение сообщения или вебхук.
curl -X POST https://wbiztool.com/api/v2/messages \
-H "Authorization: Bearer $WBIZTOOL_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: order-1042-ready" \
-d '{
"from": 101,
"to": { "phone": "+919876543210" },
"text": "Hi Asha, your order #1042 is ready."
}'import os
import requests
response = requests.post(
"https://wbiztool.com/api/v2/messages",
headers={
"Authorization": f"Bearer {os.environ['WBIZTOOL_API_KEY']}",
"Idempotency-Key": "order-1042-ready",
},
json={
"from": 101,
"to": {"phone": "+919876543210"},
"text": "Hi Asha, your order #1042 is ready.",
},
timeout=30,
)
body = response.json()
if response.status_code == 202:
print("Queued:", body["id"], body["status"])
else:
print("Refused:", body["error"]["code"], body["error"]["message"])// Node.js 18+ (built-in fetch). Save as .mjs to use top-level await.
const response = await fetch("https://wbiztool.com/api/v2/messages", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.WBIZTOOL_API_KEY}`,
"Content-Type": "application/json",
"Idempotency-Key": "order-1042-ready",
},
body: JSON.stringify({
from: 101,
to: { phone: "+919876543210" },
text: "Hi Asha, your order #1042 is ready.",
}),
});
const body = await response.json();
if (response.status === 202) {
console.log("Queued:", body.id, body.status);
} else {
console.error("Refused:", body.error.code, body.error.message);
}<?php
$ch = curl_init('https://wbiztool.com/api/v2/messages');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('WBIZTOOL_API_KEY'),
'Content-Type: application/json',
'Idempotency-Key: order-1042-ready',
],
CURLOPT_POSTFIELDS => json_encode([
'from' => 101,
'to' => ['phone' => '+919876543210'],
'text' => 'Hi Asha, your order #1042 is ready.',
]),
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30,
]);
$body = json_decode(curl_exec($ch), true);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($status === 202) {
echo 'Queued: ' . $body['id'] . ' ' . $body['status'];
} else {
echo 'Refused: ' . $body['error']['code'] . ' ' . $body['error']['message'];
}Ответ (202):
{
"id": 9817263,
"status": "queued",
"from": { "id": 101, "phone": "919800000000", "platform": "whatsapp" },
"to": { "phone": "+919876543210", "contact_id": 991 },
"text": "Hi Asha, your order #1042 is ready.",
"media": null,
"send_at": null,
"expires_at": null,
"created_at": "2026-10-18T10:15:02.311Z",
"sent_at": null,
"error": null
}
Тело запроса
toobjectобязательноКто получит сообщение: ровно одно из полей
phone,group,contact_idилиusername. См. Получатели.frominteger or nullОбязателен, если в рабочем пространстве не один подключённый номерidномера, который отправляет сообщение, из Списка номеров. Если не указан, отправляет единственный подключённый номер: один подключённый номер WhatsApp используется, даже если подключён ещё и аккаунт Telegram, а аккаунт Telegram — только когда не подключено ни одного номера WhatsApp. Номер, вышедший из аккаунта, тоже принимается: его сообщения ждут, пока он снова подключится.textstringОбязателен, если не отправляется медиафайлТекст сообщения, до 3000 символов. С
mediaэто подпись, и её можно не указывать. Форматирование WhatsApp работает:*bold*,_italic_,~strikethrough~. В JSON переносы строк пишутся как\n.mediaobject or nullнеобязательноИзображение или файл для отправки. См. Медиафайлы.
send_atstring or nullнеобязательноОтправить в это время, а не сейчас: ISO 8601 со смещением, например
2026-10-20T09:30:00+05:30. Время должно быть в будущем. См. Планирование и срок действия.expires_atstring or nullнеобязательноНе отправлять после этого времени: вместо этого сообщение становится
expired. ISO 8601 со смещением, в будущем и позжеsend_at.
Заголовки
AuthorizationheaderобязательноBearer wbz_live_…, ключ с областью доступаmessages:send.Idempotency-KeyheaderнеобязательноЛюбая уникальная строка, чтобы повтор никогда не отправил второе сообщение. См. Idempotency-Key.
Ошибки при отправке#
| HTTP | Код | Когда |
|---|---|---|
400 | validation_failed | Поле отсутствует, имеет неверный тип или неизвестно; в to нет ни одного поля или их несколько; в media указаны оба поля url и media_id или ни одного; expires_at не позже send_at |
400 | text_required | Нет ни text, ни media |
400 | text_too_long | text длиннее 3000 символов |
400 | invalid_datetime | send_at или expires_at не в формате ISO 8601 со смещением |
402 | no_credits | У рабочего пространства закончились сообщения по тарифу |
403 | number_not_allowed | Ключ ограничен другими номерами |
403 | account_disabled | Аккаунт владельца рабочего пространства отключён |
422 | invalid_phone | to.phone — не номер телефона в международном формате с + |
422 | invalid_username | to.username — не имя пользователя Telegram, не ссылка и не ID tg: |
422 | username_needs_telegram | to.username с номером WhatsApp в from |
422 | contact_not_found | Нет контакта с таким to.contact_id |
422 | media_not_found | Нет файла с таким media.media_id |
422 | invalid_media_url | media.url — не публичная ссылка http(s) |
422 | time_in_past | send_at или expires_at уже прошло |
422 | number_not_found | from — не номер этого рабочего пространства |
422 | from_required | Нет from, а в рабочем пространстве нет подключённых номеров или их несколько |
422 | message_rejected | Сообщение не удалось поставить в очередь; причина — в message |
429 | number_daily_cap_reached | Номер отправил 1000 сообщений за последние 24 часа |
Отклонённая отправка ничего не оставляет: сообщение не сохраняется, и отменять нечего. Ошибки, которые возможны в любом запросе (ключи, области доступа, лимиты запросов, Idempotency-Key), описаны на странице ошибок.
Отправка многим получателям#
https://wbiztool.com/api/v2/messages/batchТело запроса: JSON (application/json)
Отправляет одно и то же сообщение до 1000 получателям. Тело запроса такое же, как в Отправке сообщения, только to — это список получателей.
- Всё или ничего. Каждый получатель проверяется до того, как что-либо ставится в очередь, и весь список должен уложиться в оставшиеся сообщения тарифа и в запас номера-отправителя на ближайшие 24 часа. Если хотя бы один получатель указан неверно, в очередь ничего не ставится, а
fieldназывает его, напримерto[3].phone. - Один и тот же получатель, указанный дважды, получит одно сообщение.
- Ответ —
202сdata: по одному Message на получателя, в порядкеto.
curl -X POST https://wbiztool.com/api/v2/messages/batch \
-H "Authorization: Bearer $WBIZTOOL_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: opening-hours-2026-10-20" \
-d '{
"from": 101,
"to": [
{ "phone": "+919876543210" },
{ "phone": "+447700900123" },
{ "group": "Bakery staff" }
],
"text": "We open at 10 tomorrow."
}'import os
import requests
recipients = ["+919876543210", "+447700900123"]
response = requests.post(
"https://wbiztool.com/api/v2/messages/batch",
headers={
"Authorization": f"Bearer {os.environ['WBIZTOOL_API_KEY']}",
"Idempotency-Key": "opening-hours-2026-10-20",
},
json={
"from": 101,
"to": [{"phone": p} for p in recipients] + [{"group": "Bakery staff"}],
"text": "We open at 10 tomorrow.",
},
timeout=60,
)
body = response.json()
if response.status_code == 202:
for message in body["data"]:
print(message["id"], message["to"], message["status"])
else:
print("Refused:", body["error"]["code"], body["error"]["field"], body["error"]["message"])// Node.js 18+ (built-in fetch). Save as .mjs to use top-level await.
const recipients = ["+919876543210", "+447700900123"];
const response = await fetch("https://wbiztool.com/api/v2/messages/batch", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.WBIZTOOL_API_KEY}`,
"Content-Type": "application/json",
"Idempotency-Key": "opening-hours-2026-10-20",
},
body: JSON.stringify({
from: 101,
to: [...recipients.map((phone) => ({ phone })), { group: "Bakery staff" }],
text: "We open at 10 tomorrow.",
}),
});
const body = await response.json();
if (response.status === 202) {
for (const message of body.data) console.log(message.id, message.to, message.status);
} else {
console.error("Refused:", body.error.code, body.error.field, body.error.message);
}<?php
$recipients = ['+919876543210', '+447700900123'];
$to = array_map(fn ($phone) => ['phone' => $phone], $recipients);
$to[] = ['group' => 'Bakery staff'];
$ch = curl_init('https://wbiztool.com/api/v2/messages/batch');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('WBIZTOOL_API_KEY'),
'Content-Type: application/json',
'Idempotency-Key: opening-hours-2026-10-20',
],
CURLOPT_POSTFIELDS => json_encode(['from' => 101, 'to' => $to, 'text' => 'We open at 10 tomorrow.']),
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 60,
]);
$body = json_decode(curl_exec($ch), true);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($status === 202) {
foreach ($body['data'] as $message) {
echo $message['id'] . ' ' . $message['status'] . "\n";
}
} else {
echo 'Refused: ' . $body['error']['code'] . ' ' . $body['error']['field'];
}Ответ (202), по одному Message на получателя; второй и третий выглядят как первый, с to, равным {"phone": "+447700900123", …} и {"group": "Bakery staff", …}:
{
"data": [
{
"id": 9817264,
"status": "queued",
"from": { "id": 101, "phone": "919800000000", "platform": "whatsapp" },
"to": { "phone": "+919876543210", "contact_id": 991 },
"text": "We open at 10 tomorrow.",
"media": null,
"send_at": null,
"expires_at": null,
"created_at": "2026-10-19T16:02:40.118Z",
"sent_at": null,
"error": null
}
]
}
Ошибки при отправке пакета#
Те же, что при отправке одного сообщения, с позицией получателя в field (to[0].phone), а также:
| HTTP | Код | Когда |
|---|---|---|
400 | too_many_recipients | В to больше 1000 элементов |
400 | validation_failed | to пуст или не является списком |
402 | no_credits | Список не умещается в оставшиеся сообщения: requested и remaining показывают, насколько |
429 | number_daily_cap_reached | Список не умещается в запас номера на ближайшие 24 часа: requested и room показывают сколько |
Список сообщений#
https://wbiztool.com/api/v2/messagesСообщения рабочего пространства за последние 90 дней, сначала самые новые, страницами. Сюда входят сообщения, отправленные из панели, кампаниями, напоминаниями, интеграциями и через API v1, а не только через API v2. Ключ, ограниченный некоторыми номерами, видит только их сообщения.
Параметры запроса
numberintegerнеобязательноТолько сообщения с номера с этим
id.statusstringнеобязательноТолько сообщения с этим статусом:
queued,scheduled,sent,delivered,read,failed,cancelledилиexpired.sincestringнеобязательноТолько сообщения, созданные в это время или позже (ISO 8601 со смещением).
untilstringнеобязательноТолько сообщения, созданные раньше этого времени (ISO 8601 со смещением).
limitintegerнеобязательноСообщений на странице, от 1 до 100 (по умолчанию 25).
cursorstringнеобязательноnext_cursorпредыдущей страницы, с теми же фильтрами.
Фильтры можно сочетать. В строке запроса пишите + смещения как %2B (обычный + приходит как пробел, который тоже читается как +) или используйте Z.
curl -G https://wbiztool.com/api/v2/messages \
-H "Authorization: Bearer $WBIZTOOL_API_KEY" \
--data-urlencode "status=failed" \
--data-urlencode "since=2026-10-01T00:00:00+05:30" \
--data-urlencode "limit=100"import os
import requests
headers = {"Authorization": f"Bearer {os.environ['WBIZTOOL_API_KEY']}"}
params = {"status": "failed", "since": "2026-10-01T00:00:00+05:30", "limit": 100}
failed = []
while True:
page = requests.get("https://wbiztool.com/api/v2/messages",
headers=headers, params=params, timeout=30).json()
failed += page["data"]
if not page["next_cursor"]:
break
params["cursor"] = page["next_cursor"] # same filters, next page
for message in failed:
print(message["id"], message["to"], message["error"]["message"])// Node.js 18+ (built-in fetch). Save as .mjs to use top-level await.
const params = new URLSearchParams({ status: "failed", since: "2026-10-01T00:00:00+05:30", limit: "100" });
const failed = [];
while (true) {
const response = await fetch(`https://wbiztool.com/api/v2/messages?${params}`, {
headers: { Authorization: `Bearer ${process.env.WBIZTOOL_API_KEY}` },
});
const page = await response.json();
failed.push(...page.data);
if (!page.next_cursor) break;
params.set("cursor", page.next_cursor); // same filters, next page
}
for (const message of failed) console.log(message.id, message.to, message.error.message);<?php
$params = ['status' => 'failed', 'since' => '2026-10-01T00:00:00+05:30', 'limit' => 100];
$failed = [];
do {
$ch = curl_init('https://wbiztool.com/api/v2/messages?' . http_build_query($params));
curl_setopt_array($ch, [
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('WBIZTOOL_API_KEY')],
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30,
]);
$page = json_decode(curl_exec($ch), true);
curl_close($ch);
$failed = array_merge($failed, $page['data']);
$params['cursor'] = $page['next_cursor']; // same filters, next page
} while ($page['next_cursor']);
foreach ($failed as $message) {
echo $message['id'] . ' ' . $message['error']['message'] . "\n";
}Ответ — {"data": [Message, …], "next_cursor": "…" or null}.
Ошибки при получении списка#
| HTTP | Код | Когда |
|---|---|---|
400 | validation_failed | number — не ID номера, status — не один из статусов, или limit не от 1 до 100 |
400 | invalid_datetime | since или until не в формате ISO 8601 со смещением |
400 | invalid_cursor | Курсор повреждён или создан с другими фильтрами |
Получение сообщения#
https://wbiztool.com/api/v2/messages/{id}Одно сообщение и его текущий статус.
curl https://wbiztool.com/api/v2/messages/9817263 \
-H "Authorization: Bearer $WBIZTOOL_API_KEY"import os
import requests
response = requests.get(
"https://wbiztool.com/api/v2/messages/9817263",
headers={"Authorization": f"Bearer {os.environ['WBIZTOOL_API_KEY']}"},
timeout=30,
)
message = response.json()
print(message["status"], message["sent_at"])// Node.js 18+ (built-in fetch). Save as .mjs to use top-level await.
const response = await fetch("https://wbiztool.com/api/v2/messages/9817263", {
headers: { Authorization: `Bearer ${process.env.WBIZTOOL_API_KEY}` },
});
const message = await response.json();
console.log(message.status, message.sent_at);<?php
$ch = curl_init('https://wbiztool.com/api/v2/messages/9817263');
curl_setopt_array($ch, [
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('WBIZTOOL_API_KEY')],
CURLOPT_RETURNTRANSFER => true,
]);
$message = json_decode(curl_exec($ch), true);
curl_close($ch);
echo $message['status'];Ответ (200), доставленное сообщение:
{
"id": 9817263,
"status": "delivered",
"from": { "id": 101, "phone": "919800000000", "platform": "whatsapp" },
"to": { "phone": "+919876543210", "contact_id": 991 },
"text": "Hi Asha, your order #1042 is ready.",
"media": null,
"send_at": null,
"expires_at": null,
"created_at": "2026-10-18T10:15:02.311Z",
"sent_at": "2026-10-18T10:15:09.870Z",
"error": null
}
Сообщение, которого не существует, которое принадлежит другому рабочему пространству или (для ключа, ограниченного некоторыми номерами) было отправлено с другого номера, возвращает 404 message_not_found.
Отмена сообщения#
https://wbiztool.com/api/v2/messages/{id}Отменяет сообщение, которое ещё ожидает (queued или scheduled), кто бы его ни создал. Ответ — 200 с Message, теперь в статусе cancelled. Webhook endpoint получает message.cancelled.
Ушедшее сообщение отозвать нельзя. Сообщение, которое номер-отправитель забирает именно в этот момент, ещё может уйти, поэтому, если это важно, проверьте его статус после отмены.
curl -X DELETE https://wbiztool.com/api/v2/messages/9817263 \
-H "Authorization: Bearer $WBIZTOOL_API_KEY"import os
import requests
response = requests.delete(
"https://wbiztool.com/api/v2/messages/9817263",
headers={"Authorization": f"Bearer {os.environ['WBIZTOOL_API_KEY']}"},
timeout=30,
)
body = response.json()
if response.status_code == 200:
print("Cancelled")
elif body["error"]["code"] == "not_cancellable":
print("Too late, it is", body["error"]["status"])// Node.js 18+ (built-in fetch). Save as .mjs to use top-level await.
const response = await fetch("https://wbiztool.com/api/v2/messages/9817263", {
method: "DELETE",
headers: { Authorization: `Bearer ${process.env.WBIZTOOL_API_KEY}` },
});
const body = await response.json();
if (response.ok) console.log("Cancelled");
else if (body.error.code === "not_cancellable") console.log("Too late, it is", body.error.status);<?php
$ch = curl_init('https://wbiztool.com/api/v2/messages/9817263');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'DELETE',
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('WBIZTOOL_API_KEY')],
CURLOPT_RETURNTRANSFER => true,
]);
$body = json_decode(curl_exec($ch), true);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
echo $status === 200 ? 'Cancelled' : $body['error']['code'];Ошибки при отмене#
| HTTP | Код | Когда |
|---|---|---|
404 | message_not_found | Для этого ключа такого сообщения нет |
409 | not_cancellable | Оно больше не ожидает; status в ошибке показывает, в каком оно состоянии сейчас, например sent |
Объект Message#
Все операции на этой странице возвращают объекты Message, а события вебхуков передают такой объект в data.message.
| Поле | Тип | Описание |
|---|---|---|
id | integer | ID сообщения. По нему сообщение можно получить или отменить. |
status | string | Где оно сейчас. См. Статусы. |
from | object | Номер-отправитель: id, phone (цифры с кодом страны, без +) и platform (whatsapp или telegram). |
to | object | Получатель: phone (с +), group или username, а также contact_id — сохранённый контакт, которому ушло сообщение. Номер телефона или группа, которым вы пишете впервые, сохраняются как контакт. (contact_id равен null, только если это тестовое сообщение на несохранённый номер.) |
text | string | Текст или подпись; "", если их нет. |
media | object or null | type (image или file), url и file_name (null для изображений). url может быть ссылкой, которая работает ограниченное время; не сохраняйте её. |
send_at | string or null | Время, на которое запланирована отправка, или null для «сейчас». |
expires_at | string or null | Время, после которого сообщение не отправляется, или null. |
created_at | string | Когда оно создано. |
sent_at | string or null | Когда оно ушло, после отправки (sent, delivered или read). |
error | object or null | Для сообщения failed или expired message объясняет причину, например File exceeds WhatsApp size limit (16MB max). Иначе null. |
Статусы#
| Статус | Значение |
|---|---|
queued | Ожидает отправки. |
scheduled | Ожидает своего send_at. |
sent | Отправлено с вашего номера (одна галочка в WhatsApp). |
delivered | Доставлено на телефон получателя (две галочки). |
read | Прочитано получателем (синие галочки). |
failed | Отправить не удалось; причина — в error.message. |
cancelled | Отменено до отправки: через Отмену сообщения, в панели или потому, что его номер или кампания были удалены. |
expired | Не отправлено до своего expires_at. |
queued и scheduled можно отменить. sent ещё может стать delivered, а затем read. failed, cancelled, expired и read — окончательные. Вебхуки сообщают о sent, failed, cancelled и expired; чтобы увидеть delivered и read, получите сообщение.
Получатели#
to принимает ровно одно из этих полей:
| Поле | Пример | Кто получит |
|---|---|---|
phone | {"phone": "+919876543210"} | Номер телефона в международном формате с + (E.164). Пробелы и дефисы допустимы. |
group | {"group": "Bakery staff"} | Группа WhatsApp, в которой состоит номер-отправитель, по её точному названию (до 200 символов). |
contact_id | {"contact_id": 991} | Контакт, сохранённый в рабочем пространстве, по его ID (например, contact_id более раннего сообщения). Сообщение уходит на номер или в группу этого контакта. |
username | {"username": "@asha_bakes"} | Пользователь Telegram: @name, ссылка t.me/name или tg: и ID пользователя. Только с аккаунта Telegram, поэтому укажите его в from (или подключите ровно один). |
Для отправки в группы и в Telegram номер-отправитель должен состоять в этой группе или иметь возможность написать этому пользователю; проблемы с этим проявляются как сообщение failed, а не как ошибка при отправке запроса.
Медиафайлы#
media отправляет изображение или файл, а text становится подписью. Укажите ровно одно из url или media_id:
media.urlstringЛибо url, либо media_idПубличная ссылка
httpилиhttpsна файл, до 1000 символов. Ссылки на частные или локальные адреса отклоняются сinvalid_media_url.media.media_idintegerЛибо url, либо media_idФайл из Медиакаталога рабочего пространства, полученный через Загрузку файла. Загрузите файл один раз и отправляйте его сколько угодно.
media.typestringнеобязательноimageилиfile. Если не указан, ссылка, оканчивающаяся на.jpg,.jpeg,.png,.gifили.webp, отправляется как изображение, а всё остальное — как файл; дляmedia_idиспользуется тип, с которым файл был загружен.media.file_namestringнеобязательноДля
file: имя, которое видит получатель, напримерinvoice-1042.pdf(до 100 символов). Если не указано, имя берётся из ссылки или загруженного файла. От расширения зависит, как будет отправлен файл, поэтому обязательно укажите его. Для изображений игнорируется.
{
"to": { "phone": "+919876543210" },
"text": "Your invoice for order #1042",
"media": { "url": "https://example.com/invoices/1042.pdf", "type": "file", "file_name": "invoice-1042.pdf" }
}
Файл скачивается в момент отправки сообщения, а не при вызове API, поэтому нерабочая ссылка или слишком большой файл проявляются как сообщение failed с причиной в error.message. Ограничения на размер и тип такие же, как в v1: см. Отправка изображений и файлов.
Планирование и срок действия#
send_atпланирует сообщение. До этого времени оно остаётсяscheduled, и его можно отменить, пока оно не ушло. Указывайте время со смещением:2026-10-20T09:30:00+05:30означает 09:30 по времени Индии. Для повторяющихся сообщений используйте напоминания.expires_at— крайний срок: если сообщение к этому времени не ушло (например, номер вышел из аккаунта), оно становитсяexpiredи не уходит с опозданием. Используйте это для одноразовых кодов, времени доставки и предложений. Фоновая задача помечает сообщение как истёкшее не раньше чем через 30 секунд после срока, поэтому не полагайтесь на сроки меньше минуты.- Оба времени должны быть в будущем, а
expires_at— позжеsend_at.
Связанные материалы#
- Вебхуки: получайте
message.sentиmessage.failedвместо опроса. - Медиафайлы: загружайте файлы, чтобы отправлять их по
media_id. - Номера:
id, который указывается вfrom. - Ошибки
