Когда использовать Outbound
Outbound исполняет HTTP-задания, которые ваше приложение передаёт через API Adal. Входящий Сервер, Канал и Маршрутизатор не нужны. Получатель и регион задаются в каждой отправке. Для пересылки уже принятого вебхука нужен Inbound Direct, а не этот API.
Поток отправки
Приложение → API Adal → выбранный регион → HTTP-получатель. Исполнение асинхронное: API принимает задание, а результат и попытки читаются отдельно. Ответ получателя не возвращается синхронно как тело ответа на постановку.
Авторизация
Создайте API-токен и передавайте его API по адресу https://api.adal.cloud:
Authorization: Bearer <API-token>
Публичный базовый URL API — https://api.adal.cloud. В примерах задайте ADAL_API_URL этим значением без завершающего слеша. Публичные подключения используют HTTPS и WSS.
Обновление сессии
Для запросов приложения используйте API-токен; вход в кабинет не авторизует ваше приложение. По истечении API-токена выпустите и подключите новый.
Какой токен передавать
Нужен именно секрет API-токена аккаунта, а не CLI-токен Канала, пароль или данные входа в кабинет. Кабинет Outbound использует собственную сессию; для просмотра журнала в нём не требуется вставлять API-токен.
Регион
GET /outbound/regions с API-токеном возвращает regions с полями ID, Code, Name, Country, City (регистр важен). Выберите фактический ID и передайте его как region_id. Регион не выбирается автоматически по URL получателя и не меняется у принятого задания. Подробнее — Регионы.
Постановка
Используйте POST /outbound/requests с Content-Type: application/json. Query у этого API-пути не допускается. Тело — один JSON-объект; неизвестные, повторные поля и неверные типы отклоняются.
Поля задания
| Поле | Требование |
|---|---|
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":{"Content-Type":["text/plain"],"X-Demo":["first","second"]}. Значения — массивы, а не одиночные строки. Переносы строк в значениях запрещены. Транспортные заголовки, Host и Content-Length формируются для нового соединения; служебные заголовки клиента также могут заменяться. Не ожидайте побайтового совпадения всего сетевого пакета.
Ключ идемпотентности
Автоматической защиты одинаковых вызовов без ключа нет. Выберите ключ явно, сохраните его и повторяйте с тем же ключом только ту же логическую отправку. Для новой операции используйте новый ключ. Проверка выполняется в пределах аккаунта и срока хранения; после его истечения ключ не защищает от нового исполнения.
Ключ постановки не означает автоматическую установку HTTP-заголовка Idempotency-Key получателю. Если его требует ваш обработчик, передайте нужный заголовок явно и реализуйте дедупликацию на стороне приложения.
Тело
aGVsbG8= — standard base64 для байтов hello. Тело нельзя передавать вложенным JSON-объектом: сначала сериализуйте нужные данные в байты и закодируйте. URL-safe base64 не заменяет standard base64. Учитывается размер декодированных байтов, а не длина base64-строки.
Ответ принятия
Успешный ответ — 202 с request_id и received_at. Он подтверждает приём задания, а не HTTP-успех. Сохраните идентификатор и читайте журнал; запись может появиться не мгновенно. При потере ответа или 503 исход может быть неопределённым: повторяйте с прежним ключом, а не создавайте новую логическую операцию.
Статусы
received, delivering, success, failed, rejected, duplicate описывают разные этапы и исходы. Истечение HTTP-данных — отдельный признак, а не седьмой статус. Значения, фильтры и duplicate_of описаны в журнале.
Попытки
Исполнитель делает автоматические попытки до успеха или завершения по правилам исполнения. 2xx без ошибки и с корректным окончанием чтения ответа — HTTP-успех; он не доказывает бизнес-результат. Redirect автоматически не выполняется. Расписание и ограничения — в общих правилах.
Повторные эффекты
Получатель может выполнить действие до потери ответа. Повторная HTTP-попытка может вызвать его снова даже при одном принятом задании. Идемпотентность постановки и идемпотентность внешнего эффекта — разные задачи; сервис не обещает exactly-once.
Безопасность получателя
Используйте конечный URL под вашим контролем и не передавайте API-токен Adal получателю. Локальные, приватные и служебные назначения проверяются исполнителем; успешный 202 не означает, что URL разрешён и доступен для исполнения. Сертификат HTTPS и доступность проверяются при подключении.
История и диагностика
В кабинете откройте Outbound → Requests. В API используйте журнал и карточку по request_id. Попытки, причины ожидания, подробности сети/TLS/HTTP и смена снимка описаны в диагностике; тела — в HTTP-данных.
Регион и хранение
HTTP-данные хранятся в выбранном регионе. Видимая запись журнала не означает, что её содержимое ещё доступно. Истёкшее содержимое не восстанавливается из оставшейся строки журнала. Повторы и чтение не продлевают срок. См. Хранение.
Расход
Декодированное исходное тело учитывается один раз при начале первой попытки. По умолчанию ответ не сохраняется; при save_response_body=true дополнительно учитываются сохранённые ответы каждой попытки, включая ошибочные и неполные. См. Трафик.
Ошибки
| Ответ | Что проверить |
|---|---|
400 invalid_request |
JSON, поля, UUID, URL, массивы заголовков, base64; это отказ валидации, не статус rejected задания |
401 |
Правильный API-токен, срок и отзыв |
413 payload_too_large |
Размер тела, конверта и метаданных; запрос не опубликован |
503 unavailable |
Временный отказ или неопределённое принятие; при повторе сохранить ключ |
Ошибки чтения результатов 404, 409 и 410 имеют другой смысл; не заменяйте чтение новым POST. Разбирайте их по статьям журнала, диагностики и тел.
Границы
Тело, JSON-конверт, метаданные, подробности и скачивание имеют отдельные ограничения. Base64 увеличивает размер тела внутри JSON: допустимость исходных байтов сама по себе не означает допустимость всего конверта. Размер URL и заголовков также влияет на метаданные. Пакет трафика не снимает технических ограничений.
При 413 payload_too_large проверьте объём исходного тела, всего JSON и метаданных; уменьшите передаваемые данные и уберите ненужные заголовки. Повтор неизменённого запроса не устраняет превышение. Ошибка формата, в том числе некорректный idempotency_key, относится к 400 invalid_request, а не к превышению размера.
Не рассчитывайте на строгий порядок, фиксированное время исполнения, ручной replay в кабинете или автоматическое переключение региона.
Полный путь интеграции
Создать API-токен → получить регионы → сохранить ключ операции → отправить задание → сохранить ID → прочитать исход и попытки → при необходимости загрузить детали и тела. При неопределённости постановки повторять тот же запрос с тем же ключом; при ошибке чтения повторять чтение.
Пути API
| Метод и путь | Назначение |
|---|---|
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 |
Сохранённые байты ответа попытки |