> ## Documentation Index
> Fetch the complete documentation index at: https://docs.hubtalk.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Как проходит обзвон

> Что происходит после запроса, как читать ответ и зачем обязателен ключ повтора.

# Как проходит обзвон

## Как проходит обзвон, запущенный запросом

**Шаг 1. Ваша система отправляет один запрос.** В нём: название кампании, имя агента, скорость обзвона, рабочие часы, цель обзвона, подтверждение согласия и сам список номеров с данными для разговора.

**Шаг 2. Платформа разбирает список.** Тот же разбор, что у файла в кабинете: нормализация номеров, поиск дублей, проверка обязательных колонок, сверка с реестром «не звонить», проверка географии для США. Ничего из этого на пути через API не пропускается и не упрощается.

**Шаг 3. Платформа проверяет, можно ли запускать.** Опубликован ли агент, есть ли линия, не в прошлом ли окно, подписано ли подтверждение, не все ли номера оказались в реестре «не звонить».

**Шаг 4. Если всё в порядке — обзвон начинается.** Тем же планировщиком, что и у кампаний из кабинета: с вашей скоростью, в ваши рабочие часы, с повторами недозвонов по вашим правилам и с учётом ограничений частоты звонков на один номер, действующих в вашей организации.

**Шаг 5. Вы читаете ответ.** В нём — что получилось: поехал ли обзвон, сколько строк принято, что не так с непринятыми.

Отдельного «нажатия кнопки» в этой схеме нет: один запрос делает все три вещи сразу — создаёт, принимает номера и запускает.

## Как читать ответ

Ответ приходит **всегда**, даже когда обзвон не начался. Читается он по одному полю и двум спискам.

**`status` — единственный ответ на вопрос «поехало ли»:**

| Значение    | Что означает                              |
| ----------- | ----------------------------------------- |
| `running`   | обзвон идёт                               |
| `scheduled` | всё в порядке, ждём начала окна           |
| `draft`     | не начался, причина — в списке `blockers` |

**`blockers` — почему не начался.** Это не «ошибки запроса», а состояние дел: агент снят с публикации, номера попали в реестр «не звонить», окно в прошлом, нет подписи под подтверждением согласия. Каждая причина названа отдельным кодом — тем же, что виден в кабинете на экране запуска.

<Warning>
  Одна тонкость, о которой стоит знать заранее: если вы **позже читаете карточку кампании** отдельным запросом, `blockers` там отвечает на вопрос «что сказала бы проверка запуска прямо сейчас», а не «почему кампания не работает». У работающей кампании этот список никогда не пуст — как минимум в нём стоит «нужна подпись подтверждения», потому что подпись даётся на каждый запуск, а не хранится как состояние. Решает вопрос «идёт ли обзвон» только поле `status`.
</Warning>

**`warnings` — предупреждения.** Они ничего не блокируют и есть почти у каждой кампании: например, «начало не задано — набор начнётся сразу» и «действует частотная политика» с цифрами, сколько раз в сутки и за неделю можно звонить на один номер.

**`import` — что стало со списком номеров.** Сколько строк увидели, сколько приняли, сколько с предупреждениями, сколько отклонили, сколько дублей, и по каким причинам (сгруппировано по коду причины с номерами первых строк). `dnc_screen` отдельно называет: сколько читаемых строк проверено, сколько не проверено, сколько строк совпало с реестром и сколько это уникальных номеров; каждое совпадение несёт строку, исходный телефон, имя, причину и запись реестра.

<Note>
  **Кампания и отчёт сохраняются в любом исходе.** Даже когда обзвон не начался, кампания остаётся в кабинете, а отчёт по строкам доступен: это единственный способ понять, что не так с данными, и удалять его вместе с неудачей значило бы уничтожить ровно то, что нужно для исправления.
</Note>

### Одно правило, которое избавляет от догадок

**Действие, которое ничего не изменило, — всегда ошибка.** Успешный ответ означает, что состояние в теле ответа и есть новое состояние. Поэтому:

* запрос на создание отвечает успехом, даже если обзвон не начался: кампания и отчёт действительно созданы, и `status` честно говорит `draft`;
* отдельный запрос «запусти», который ничего не запустил, отвечает **ошибкой** — и называет причину в самой ошибке, чтобы не пришлось спрашивать второй раз;
* повторная команда «поставь на паузу» уже остановленной кампании — **не** ошибка: состояние и так такое, как вы просили.

## Повторная отправка: почему обязателен «ключ повтора»

Сеть иногда обрывает ответ уже после того, как платформа всё сделала. Ваша система в этот момент не знает, дошёл запрос или нет, и обычно повторяет его. Для одного звонка это неприятно; для списка из десяти тысяч номеров это означает **обзвонить всех дважды**.

Поэтому на создании кампании **и** на добавлении номеров в неё обязателен заголовок `Idempotency-Key` — произвольная строка, которую ваша система придумывает для каждой новой кампании или партии (например, идентификатор задачи в вашей системе). Дальше платформа разбирается сама:

* **тот же ключ, то же тело** — вернётся тот же ответ, что и в первый раз; вторая кампания не появится;
* **тот же ключ, пока первый запрос ещё выполняется** — отказ `409 idempotency_key_in_flight`: подождите ответ, не повторяйте снова;
* **тот же ключ, но ДРУГОЕ тело** — отказ `422 idempotency_key_reuse`. Это защита от самой неприятной ошибки: без неё вы получили бы ответ на чужой запрос и решили бы, что платформа проигнорировала ваши настройки;
* **запрос отклонён до создания кампании** — ключ освобождается сразу, и исправленный запрос с тем же ключом пройдёт нормально. Если отказ случился уже после создания (например, не удалось сохранить список), ключ остаётся занятым, а созданную кампанию можно найти в списке кампаний.

Ключи помнятся сутки. Практический вывод: **новая кампания — новый ключ, новая партия — новый ключ.** Повторять с прежним ключом стоит только буквально тот же запрос.
