Сервер Gratio звонит собеседнику с номера канала. Когда тот снимет трубку, звучит приветствие из playUrl, дальше — playAudio или живой звук callAudio. Подходит для напоминаний и голосового бота.
| Запрос | POST /waInstance{idInstance}/makeCall/{apiTokenInstance} |
| Тело | JSON |
| Каналы | MAX, WhatsApp — если в getCapabilities call_audio: true |
Параметры
| Параметр | Тип | Обязательный | Описание |
|---|---|---|---|
chatId |
string | да | личный чат собеседника или номер 79991234567@c.us. Группе звонить нельзя |
playUrl |
string | нет | что сказать, когда снимут трубку: ссылка на звуковой файл — wav, mp3, ogg и другие. Своя из uploadFile или внешняя |
record |
boolean | нет | записать голос собеседника, по умолчанию true |
maxDurationSeconds |
number | нет | предел разговора: 1–3600 секунд, по умолчанию 600 |
Пример запроса
Напомнить о занятии и закончить не позже чем через 2 минуты разговора:
curl
curl -X POST "$GRATIO_URL/waInstance$GRATIO_ID/makeCall/$GRATIO_TOKEN" \
-H 'Content-Type: application/json' \
-d '{
"chatId": "79991234567@c.us",
"playUrl": "https://example.ru/audio/reminder.mp3",
"record": true,
"maxDurationSeconds": 120
}'
Python
import os
import requests
BASE = f"{os.environ['GRATIO_URL']}/waInstance{os.environ['GRATIO_ID']}"
TOKEN = os.environ["GRATIO_TOKEN"]
url = f"{BASE}/makeCall/{TOKEN}"
payload = {
"chatId": "79991234567@c.us",
"playUrl": "https://example.ru/audio/reminder.mp3",
"record": True,
"maxDurationSeconds": 120,
}
response = requests.post(url, json=payload, timeout=60)
print(response.status_code, response.json())
Node.js
const { GRATIO_URL, GRATIO_ID, GRATIO_TOKEN } = process.env;
const base = `${GRATIO_URL}/waInstance${GRATIO_ID}`;
const url = `${base}/makeCall/${GRATIO_TOKEN}`;
const payload = {
chatId: "79991234567@c.us",
playUrl: "https://example.ru/audio/reminder.mp3",
record: true,
maxDurationSeconds: 120,
};
const response = await fetch(url, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(payload),
});
console.log(response.status, await response.json());
PHP
<?php
$base = getenv('GRATIO_URL') . '/waInstance' . getenv('GRATIO_ID');
$url = $base . '/makeCall/' . getenv('GRATIO_TOKEN');
$payload = [
'chatId' => '79991234567@c.us',
'playUrl' => 'https://example.ru/audio/reminder.mp3',
'record' => true,
'maxDurationSeconds' => 120,
];
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => ['Content-Type: application/json'],
CURLOPT_POSTFIELDS => json_encode($payload, JSON_UNESCAPED_UNICODE),
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 60,
]);
$response = json_decode(curl_exec($ch), true);
echo curl_getinfo($ch, CURLINFO_HTTP_CODE), PHP_EOL;
print_r($response);
Пример ответа
Ответ 200 OK в MAX — объект звонка, у собеседника звонит телефон:
{
"callId": "31A9ADA2-3889-4B2B-9D88-6A7142875D7F",
"chatId": "8695836",
"direction": "out",
"state": "ringing",
"answered": false,
"endReason": null,
"endedBy": null,
"talkSeconds": 0.0
}
Поля ответа
| Поле | Тип | Описание |
|---|---|---|
callId |
string | id звонка — для playAudio, callAudio, hangUpCall, getCall |
chatId |
string | собеседник. По номеру …@c.us Gratio нашёл его аккаунт |
state |
string | ringing — звонит. Дальше — callStateChanged: connecting, active, ended |
Все поля — в статье Звонки: как это работает.
Что происходит после вызова
Приложение Gratio Собеседник
│── makeCall ─────────────────►│── звонок ────────────────►│
│◄── {"state": "ringing"} ─────│ │
│ │◄─────────── снял трубку ──│
│◄── callStateChanged: active │══ приветствие ═══════════►│
│◄═══ callAudio, playAudio ═══►│◄═══ голос ═══════════════►│
│◄── callStateChanged: ended │ │
- Не ответил —
endedсendReason: "no_answer". Занято —busy, отклонил —rejected. - Положить трубку раньше или отменить вызов, пока звонит, — hangUpCall.
Ошибки
| Код | code |
Когда | Что делать |
|---|---|---|---|
400 |
validation |
нет chatId; maxDurationSeconds вне 1–3600 |
исправить запрос |
400 |
no_account |
на номере нет аккаунта в этом мессенджере | позвонить через другой канал |
400 |
not_a_user |
MAX: chatId — группа |
звонить в личный чат |
400 |
call_rejected или код MAX |
MAX отказал сразу: приватность собеседника, блокировка | см. message |
400 |
call_failed |
WhatsApp не принял вызов | повторить позже |
400 |
bad_audio |
MAX: файл из playUrl не разобран как звук |
сменить файл |
400 |
audio_format |
WhatsApp: файл из playUrl не разобран как звук |
сменить файл |
400 |
bad_url, url_unavailable |
playUrl не http(s), ведёт во внутреннюю сеть или недоступна |
проверить ссылку |
400 |
not_authorized |
канал не на связи | проверить getStateInstance |
402 |
payment_required |
канал на паузе за неоплату | продлить канал в кабинете |
409 |
busy |
MAX: на канале уже идёт разговор через API | дождаться конца разговора |
429 |
too_frequent |
MAX: звонок чаще раза в 20 секунд | повторить после Retry-After |
429 |
call_tempo |
WhatsApp: звонок чаще раза в 20 секунд | повторить после Retry-After |
501 |
not_supported |
у канала нет звука звонков: Telegram или call_audio: false |
— |
Особенности каналов
- MAX. Ждём ответа 45 секунд. Через API на канале идёт один разговор.
- WhatsApp. Звонок попадает и в ленту — уведомлением
outgoingCall.callId— строка видаcall-…. - Telegram. Только события звонков —
501. - Звонок через API — только голосовой.
Что дальше
- callStateChanged — ответил ли собеседник.
- playAudio — сказать следующую фразу.
- Напоминания и рассылки без блокировок — темп для массовых сценариев.
