AISARAISAR
REST API

Звонки

Программное управление голосовыми звонками: инициировать исходящий вызов к контакту (`POST /calls/originate`) и завершить активный вызов (`POST /calls/{call}/hangup`). Это API управления звонками, а не браузерный софтфон — оно лишь ставит вызов в работу через телефонный шлюз AISAR; сам звук идёт по SIP/WebRTC вне HTTP. Вся группа доступна только при активной подписке и включённом на плане функционале телефонии (`telephony`); кроме того, вызывающий пользователь должен быть заведён как оператор телефонии (иметь провиженный SIP-эндпоинт) и обладать правом `telephony.use` в текущей компании — иначе `403 { "data": { "message": "Telephony is not available for your account." } }`. `POST /calls/originate` принимает `contact_id` и `channel_id` (оба обязательны, целые). Канал задаёт способ дозвона: канал WhatsApp/WABA звонит контакту в WhatsApp, а канал типа `sip_telephony` набирает телефонный номер контакта через SIP-транк. И контакт, и канал должны принадлежать текущей компании (иначе `404 { "data": { "message": "Contact or channel not found." } }`). Успех (200) возвращает созданную запись звонка: `{ "data": { "call": { id, direction: "outbound", status: "ringing", to_number, from_number, asterisk_channel_id, timeline_message_id } } }` — вызов создаётся в состоянии `ringing`, а в таймлайн диалога добавляется карточка звонка (`timeline_message_id`). Дальнейшие переходы статуса (`ringing → answered → completed`, либо `rejected` / `missed` / `failed`) приходят через события реального времени и вебхуки семейства `call.*`, а не в теле этого ответа. WhatsApp-звонки требуют действующего разрешения на звонок (call permission) от контакта: без него `originate` вернёт `422` с блоком `eligibility`, где `call.can_call = false`. Проверить готовность и запросить разрешение заранее можно через `GET /v1/contacts/{contact}/outbound-eligibility` и `POST /v1/contacts/{contact}/call-permission/request` (группа «Контакты»). Для SIP-каналов разрешение не требуется (`eligibility.call.permission_status = "not_required"`), нужен лишь телефонный номер у контакта — иначе `422 { "data": { "message": "Contact has no phone number to dial." } }`. Прочие исходы `originate`: `403` с блоком `eligibility` — канал или контакт не поддерживает звонок (нет WhatsApp-аккаунта, оператор не включён); `502` — телефонный шлюз не смог инициировать вызов; `422` — ошибка валидации тела (отсутствуют `contact_id` / `channel_id`). `POST /calls/{call}/hangup` завершает активный вызов. Помимо доступности телефонии, завершить вызов может только его участник (назначенный оператор либо сторона вызова) или пользователь с правом управления телефонией компании — иначе `403`. Успех: `{ "message": "Hangup requested." }` (запрос на разрыв передан в шлюз; фактическое завершение подтверждается событием `call.*`). Обратите внимание: ответ `hangup`, в отличие от `originate`, не обёрнут в `data`.

Эндпоинты

МетодПуть
POST/v1/calls/originate

Инициировать исходящий звонок контакту через WhatsApp- или SIP-канал.

POST/v1/calls/{call}/hangup

Завершить активный звонок (доступно участнику вызова или менеджеру телефонии).

Примеры

Исходящий WhatsApp-звонок

Запрос

bash
curl -X POST https://api.aisar.app/v1/calls/originate \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "contact_id": 42,
    "channel_id": 7
  }'

Ответ

json
{
  "data": {
    "call": {
      "id": 5001,
      "direction": "outbound",
      "status": "ringing",
      "to_number": "7700000XXXX",
      "from_number": "7708550XXXX",
      "asterisk_channel_id": "1720787000.4521",
      "timeline_message_id": 88214
    }
  }
}

Исходящий звонок через SIP-транк

Запрос

bash
curl -X POST https://api.aisar.app/v1/calls/originate \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "contact_id": 42,
    "channel_id": 12
  }'

Ответ

json
{
  "data": {
    "call": {
      "id": 5002,
      "direction": "outbound",
      "status": "ringing",
      "to_number": "7700000XXXX",
      "from_number": "7727000XXXX",
      "asterisk_channel_id": "1720787100.4530",
      "timeline_message_id": 88221
    }
  }
}

WhatsApp-звонок без разрешения контакта (422)

Запрос

bash
curl -X POST https://api.aisar.app/v1/calls/originate \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "contact_id": 42,
    "channel_id": 7
  }'

Ответ

json
{
  "data": {
    "message": "No valid call permission or daily attempts exhausted.",
    "eligibility": {
      "message": {
        "window_open": true,
        "window_expires_at": 1720800000,
        "requires_template": false
      },
      "call": {
        "channel_kind": "whatsapp",
        "can_call": false,
        "permission_status": "none",
        "permission_expires_at": null,
        "can_request_permission": true,
        "request_cooldown_until": null,
        "attempts_remaining": 5,
        "has_whatsapp_account": true
      }
    }
  }
}

Завершение активного звонка

Запрос

bash
curl -X POST https://api.aisar.app/v1/calls/5001/hangup \
  -H "Authorization: Bearer YOUR_API_TOKEN"

Ответ

json
{
  "message": "Hangup requested."
}

Телефония недоступна для аккаунта (403)

Запрос

bash
curl -X POST https://api.aisar.app/v1/calls/originate \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "contact_id": 42,
    "channel_id": 7
  }'

Ответ

json
{
  "data": {
    "message": "Telephony is not available for your account."
  }
}