
## Когда использовать Outbound {#when-to-use}

Outbound исполняет HTTP-задания, которые ваше приложение передаёт через API Adal. Входящий Сервер, Канал и Маршрутизатор не нужны. Получатель и регион задаются в каждой отправке. Для пересылки уже принятого вебхука нужен [Inbound Direct](/ru/docs/inbound/direct), а не этот API.

## Поток отправки {#how-it-works}

Приложение → API Adal → выбранный регион → HTTP-получатель. Исполнение асинхронное: API принимает задание, а результат и попытки читаются отдельно. Ответ получателя не возвращается синхронно как тело ответа на постановку.

## Авторизация {#authentication}

Создайте [API-токен](/ru/docs/common/account-api-tokens) и передавайте его API по адресу `https://api.adal.cloud`:

```http
Authorization: Bearer <API-token>
```

Публичный базовый URL API — `https://api.adal.cloud`. В примерах задайте `ADAL_API_URL` этим значением без завершающего слеша. Публичные подключения используют HTTPS и WSS.

### Обновление сессии {#refresh-token}

Для запросов приложения используйте API-токен; вход в кабинет не авторизует ваше приложение. По истечении API-токена выпустите и подключите новый.

### Какой токен передавать {#access-token}

Нужен именно секрет API-токена аккаунта, а не CLI-токен Канала, пароль или данные входа в кабинет. Кабинет Outbound использует собственную сессию; для просмотра журнала в нём не требуется вставлять API-токен.

## Регион {#choose-region}

`GET /outbound/regions` с API-токеном возвращает `regions` с полями `ID`, `Code`, `Name`, `Country`, `City` (регистр важен). Выберите фактический `ID` и передайте его как `region_id`. Регион не выбирается автоматически по URL получателя и не меняется у принятого задания. Подробнее — [Регионы](/ru/docs/common/regions).

## Постановка {#send-message}

Используйте `POST /outbound/requests` с `Content-Type: application/json`. Query у этого API-пути не допускается. Тело — один JSON-объект; неизвестные, повторные поля и неверные типы отклоняются.

### Поля задания {#message-fields}

| Поле                 | Требование                                                                                     |
|----------------------|------------------------------------------------------------------------------------------------|
| `region_id`          | Обязательный UUID из справочника, в каноническом нижнем регистре                               |
| `method`             | Обязательный корректный HTTP-метод                                                             |
| `url`                | Обязательный полный HTTP/HTTPS URL получателя; query в нём допустим, userinfo и fragment — нет |
| `headers`            | Обязательный объект: имя заголовка → массив строк; `{}` для отсутствующих заголовков           |
| `body`               | Обязательная строка standard base64; `""` для пустого тела                                     |
| `idempotency_key`    | Необязательный непустой ключ одной логической операции                                         |
| `save_response_body` | Необязательный boolean, по умолчанию `false`                                                   |

Передавайте только перечисленные выше поля отправки; идентификаторы запроса и время приёма назначаются автоматически. Не отправляйте `null` вместо обязательных значений. В отличие от базового URL Ендпоинта Inbound, Outbound принимает полный конечный URL и не добавляет к нему путь Сервера.

### Заголовки {#headers}

Например, `"headers":{"Content-Type":["text/plain"],"X-Demo":["first","second"]}`. Значения — массивы, а не одиночные строки. Переносы строк в значениях запрещены. Транспортные заголовки, Host и Content-Length формируются для нового соединения; служебные заголовки клиента также могут заменяться. Не ожидайте побайтового совпадения всего сетевого пакета.

### Ключ идемпотентности {#automatic-idempotency-key}

Автоматической защиты одинаковых вызовов без ключа нет. Выберите ключ явно, сохраните его и повторяйте с тем же ключом только ту же логическую отправку. Для новой операции используйте новый ключ. Проверка выполняется в пределах аккаунта и срока хранения; после его истечения ключ не защищает от нового исполнения.

Ключ постановки не означает автоматическую установку HTTP-заголовка `Idempotency-Key` получателю. Если его требует ваш обработчик, передайте нужный заголовок явно и реализуйте дедупликацию на стороне приложения.

### Тело {#request-body}

`aGVsbG8=` — standard base64 для байтов `hello`. Тело нельзя передавать вложенным JSON-объектом: сначала сериализуйте нужные данные в байты и закодируйте. URL-safe base64 не заменяет standard base64. Учитывается размер декодированных байтов, а не длина base64-строки.

## Ответ принятия {#send-response}

Успешный ответ — `202` с `request_id` и `received_at`. Он подтверждает приём задания, а не HTTP-успех. Сохраните идентификатор и читайте журнал; запись может появиться не мгновенно. При потере ответа или `503` исход может быть неопределённым: повторяйте с прежним ключом, а не создавайте новую логическую операцию.

## Статусы {#statuses}

`received`, `delivering`, `success`, `failed`, `rejected`, `duplicate` описывают разные этапы и исходы. Истечение HTTP-данных — отдельный признак, а не седьмой статус. Значения, фильтры и `duplicate_of` описаны в [журнале](/ru/docs/outbound/history).

## Попытки {#delivery-retries}

Исполнитель делает автоматические попытки до успеха или завершения по правилам исполнения. `2xx` без ошибки и с корректным окончанием чтения ответа — HTTP-успех; он не доказывает бизнес-результат. Redirect автоматически не выполняется. Расписание и ограничения — [в общих правилах](/ru/docs/common/retries).

## Повторные эффекты {#at-least-once}

Получатель может выполнить действие до потери ответа. Повторная HTTP-попытка может вызвать его снова даже при одном принятом задании. Идемпотентность постановки и идемпотентность внешнего эффекта — разные задачи; сервис не обещает exactly-once.

## Безопасность получателя {#destination-security}

Используйте конечный URL под вашим контролем и не передавайте API-токен Adal получателю. Локальные, приватные и служебные назначения проверяются исполнителем; успешный `202` не означает, что URL разрешён и доступен для исполнения. Сертификат HTTPS и доступность проверяются при подключении.

## История и диагностика {#history}

В кабинете откройте **Outbound → Requests**. В API используйте журнал и карточку по `request_id`. Попытки, причины ожидания, подробности сети/TLS/HTTP и смена снимка описаны в [диагностике](/ru/docs/outbound/diagnostics); тела — в [HTTP-данных](/ru/docs/outbound/http-data).

## Регион и хранение {#regional-processing}

HTTP-данные хранятся в выбранном регионе. Видимая запись журнала не означает, что её содержимое ещё доступно. Истёкшее содержимое не восстанавливается из оставшейся строки журнала. Повторы и чтение не продлевают срок. См. [Хранение](/ru/docs/common/storage).

## Расход {#credits}

Декодированное исходное тело учитывается один раз при начале первой попытки. По умолчанию ответ не сохраняется; при `save_response_body=true` дополнительно учитываются сохранённые ответы каждой попытки, включая ошибочные и неполные. См. [Трафик](/ru/docs/common/traffic).

## Ошибки {#troubleshooting}

| Ответ                   | Что проверить                                                                                        |
|-------------------------|------------------------------------------------------------------------------------------------------|
| `400 invalid_request`   | JSON, поля, UUID, URL, массивы заголовков, base64; это отказ валидации, не статус `rejected` задания |
| `401`                   | Правильный API-токен, срок и отзыв                                                                   |
| `413 payload_too_large` | Размер тела, конверта и метаданных; запрос не опубликован                                            |
| `503 unavailable`       | Временный отказ или неопределённое принятие; при повторе сохранить ключ                              |

Ошибки чтения результатов `404`, `409` и `410` имеют другой смысл; не заменяйте чтение новым POST. Разбирайте их по статьям журнала, диагностики и тел.

## Границы {#limitations}

Тело, JSON-конверт, метаданные, подробности и скачивание имеют отдельные ограничения. Base64 увеличивает размер тела внутри JSON: допустимость исходных байтов сама по себе не означает допустимость всего конверта. Размер URL и заголовков также влияет на метаданные. Пакет трафика не снимает технических ограничений.

При `413 payload_too_large` проверьте объём исходного тела, всего JSON и метаданных; уменьшите передаваемые данные и уберите ненужные заголовки. Повтор неизменённого запроса не устраняет превышение. Ошибка формата, в том числе некорректный `idempotency_key`, относится к `400 invalid_request`, а не к превышению размера.

Не рассчитывайте на строгий порядок, фиксированное время исполнения, ручной replay в кабинете или автоматическое переключение региона.

## Полный путь интеграции {#complete-flow}

Создать API-токен → получить регионы → сохранить ключ операции → отправить задание → сохранить ID → прочитать исход и попытки → при необходимости загрузить детали и тела. При неопределённости постановки повторять тот же запрос с тем же ключом; при ошибке чтения повторять чтение.

## Пути API {#api-summary}

| Метод и путь                                                              | Назначение                          |
|---------------------------------------------------------------------------|-------------------------------------|
| `GET /outbound/regions`                                                   | Доступные регионы                   |
| `POST /outbound/requests`                                                 | Приём задания                       |
| `GET /outbound/requests`                                                  | Журнал                              |
| `GET /outbound/requests/{request_id}`                                     | Карточка                            |
| `GET /outbound/requests/{request_id}/http`                                | Сводка HTTP-данных                  |
| `GET /outbound/requests/{request_id}/http/details`                        | Страница подробностей одной ревизии |
| `GET /outbound/requests/{request_id}/body`                                | Исходные байты запроса              |
| `GET /outbound/requests/{request_id}/attempts/{attempt_id}/response/body` | Сохранённые байты ответа попытки    |

## Дальше {#related-pages}

[Быстрый старт](/ru/docs/outbound/quickstart), [журнал](/ru/docs/outbound/history), [диагностика](/ru/docs/outbound/diagnostics), [HTTP-данные](/ru/docs/outbound/http-data).
