Звонки в API — на двух уровнях. События приходят во всех мессенджерах: кто звонит и чем кончилось — для журнала звонков и перезвона. Звонки со звуком ведёт сервер Gratio: отвечает или звонит сам, говорит файлом, пишет голос собеседника и отдаёт живой звук приложению — для голосового бота, автоинформатора, записи разговора.
| Канал | События звонков | Звонки со звуком |
|---|---|---|
| MAX | да | если call_audio: true |
| да | если call_audio: true — включается для номера |
|
| Telegram | да | нет: методы звонков отвечают 501 |
Проверьте флаг call_audio в getCapabilities. Без него методы звонков отвечают 501 not_supported, а события приходят как обычно.
События звонков
Звонки номеру и с его телефона приходят уведомлениями incomingCall и outgoingCall: первое, со status: "offer", — пока звонит, итог — следующим. Флаг в настройках — incomingCallWebhook.
Сервер в разговор не вмешивается, пока приложение не вызвало метод: телефоны номера звонят как обычно.
Звонки со звуком
| Метод | Что делает |
|---|---|
| answerCall | ответить на входящий |
| rejectCall | отклонить входящий |
| makeCall | позвонить собеседнику |
| playAudio | сказать звуковым файлом |
| callAudio | живой звук в обе стороны через WebSocket |
| hangUpCall | положить трубку |
| getCall и getActiveCalls | состояние звонка и идущие разговоры |
callId — id звонка: idMessage из incomingCall со status: "offer" или callId из ответа makeCall. В MAX это UUID, в WhatsApp — строка вида call-….
Ход звонка, который ведёт сервер, приходит уведомлением callStateChanged: каждое состояние — один раз. Флаг в настройках — тот же incomingCallWebhook.
Входящий
Собеседник Gratio Приложение
│── звонок ───────────►│ │
│ │── incomingCall: offer ────────►│
│ │◄────────────────── answerCall ─│
│ │── callStateChanged: connecting►│
│◄═══ голос ══════════►│── callStateChanged: active ───►│
│ │◄═══ callAudio, playAudio ═════►│
│── кладёт трубку ────►│── callStateChanged: ended ────►│
- Пришёл
incomingCallсоstatus: "offer". Пока звонит, вызовите answerCall или rejectCall. В MAX на это есть до 90 секунд. Ничего не вызвали — звонок звонит на телефонах номера как обычно. connecting— сервер соединяется,active— звук пошёл: приветствие изplayUrlзвучит с начала.- Во время разговора: playAudio — файл, callAudio — живой звук, hangUpCall — положить трубку.
ended— причина вendReason, запись — вrecording.
Исходящий
Приложение Gratio Собеседник
│── makeCall ─────────────────►│── звонок ────────────────►│
│◄── callStateChanged: ringing │ │
│ │◄─────────── снял трубку ──│
│◄── callStateChanged: connecting │
│◄── callStateChanged: active │◄═══ голос ═══════════════►│
│◄═══ callAudio, playAudio ═══►│ │
│── hangUpCall ───────────────►│── отбой ─────────────────►│
│◄── callStateChanged: ended │ │
- makeCall отвечает объектом звонка со
state: "ringing"— у собеседника звонит телефон. - Снял трубку —
connecting, затемactive. Не ответил —endedсendReason: "no_answer"; в MAX ждём 45 секунд. - Дальше — как у входящего.
Объект звонка
Его возвращают answerCall, makeCall, getCall, getActiveCalls; те же поля — в callStateChanged:
{
"callId": "31A9ADA2-3889-4B2B-9D88-6A7142875D7F",
"chatId": "8695836",
"direction": "in",
"state": "ended",
"answered": true,
"endReason": "hangup",
"endedBy": "remote",
"talkSeconds": 21.7,
"recording": {
"downloadUrl": "https://api.gratio.net/calls/7100000001/31A9ADA2-3889-4B2B-9D88-6A7142875D7F/5e0c….wav",
"mimeType": "audio/wav",
"durationSeconds": 21.7
}
}
| Поле | Тип | Описание |
|---|---|---|
callId |
string | id звонка |
chatId |
string | собеседник |
direction |
string | in — входящий, ответили через answerCall; out — позвонили через makeCall |
state |
string | ringing — звонит, connecting — соединяемся, active — идёт разговор, ended — закончился |
answered |
boolean | звук шёл — разговор состоялся |
endReason |
string или null | почему закончился — см. таблицу ниже; до конца — null |
endedBy |
string или null | кто закончил — см. таблицу ниже; до конца — null |
talkSeconds |
number | длительность разговора, секунд |
recording |
object | только после конца и если писали: downloadUrl, mimeType, durationSeconds |
Почему закончился
endReason |
Что значит |
|---|---|
hangup |
положили трубку |
rejected |
звонок отклонён |
canceled |
звонящий сбросил до ответа |
busy |
собеседник занят |
no_answer |
не ответили |
max_duration |
разговор дошёл до maxDurationSeconds — сервер положил трубку |
failed |
соединение не установилось или сорвалось |
connection_lost |
MAX: пропала связь со звонком |
disconnected |
MAX: канал отключился от мессенджера во время разговора |
restart |
MAX: сервис обновлялся, и разговор не закончился за 2 минуты |
Кто закончил
endedBy |
Кто |
|---|---|
remote |
собеседник или мессенджер |
api |
приложение: hangUpCall, rejectCall или команда hangup в callAudio |
system |
сервер Gratio: предел длительности, нет ответа, сбой |
Запись
- Пишется голос собеседника: WAV, моно, 16 кГц, 16 бит. Включена по умолчанию, выключить —
record: false. - Ссылка приходит в
recording.downloadUrlвcallStateChangedсоstate: "ended"и вgetCall. Ссылка подписанная, без токена — как ссылки на файлы, см. Файлы и ссылки на них. - Свою запись в другом формате ведите через callAudio: там тот же звук кадрами.
Ограничения
| Что | Сколько | При превышении |
|---|---|---|
| Разговор через API | MAX: один на канал | 409 busy; второй входящий звонит на телефонах как обычно |
| Исходящий звонок | не чаще раза в 20 секунд | MAX — 429 too_frequent, WhatsApp — 429 call_tempo, с Retry-After |
| Длительность | maxDurationSeconds: 1–3600, по умолчанию 600 |
сервер кладёт трубку, endReason: "max_duration" |
| Очередь звука собеседнику | до 5 минут | 400 audio_queue_full |
| Видео | не передаётся — только голос | — |
Что дальше
- incomingCall и outgoingCall — события звонков.
- answerCall — ответить на входящий.
- callAudio — живой звук для голосового бота.
- Звонки: автоответчик и голосовой бот — руководство целиком.
