Iris API¶
Что такое Iris¶
Iris — это асинхронный API для обмена данными между внешней системой и CARGO.RUN Логистика.
Через Iris внешняя система может:
- отправлять команды на создание, обновление и удаление объектов
- читать изменившиеся данные со стороны CARGORUN
- выполнять выборочные чтения по query
- получать результат обработки через polling или webhook
Iris работает в контексте конкретной организации и конкретного внутреннего пользователя. Для внешних M2M интеграций подставляется автоматически через technical user.
Базовые принципы¶
Iris работает как очередь задач:
- клиент отправляет одну или несколько команд
- сервер создает отдельные задачи
- сервер отдает ответ 202 сразу и клиент получает
taskId - сервер обрабатывает задачи асинхронно
- клиент забирает результат либо через polling, либо через webhook
У одной команды может быть несколько задач, если в запросе передано несколько элементов в commands.
Авторизация и контекст организации¶
Для вызова Iris используется обычная JWT авторизация по пользователю, либо M2M-авторизация, описанная в разделе авторизации и создания организаций.
Для org-scoped вызовов Iris обязательно:
Authorization: Bearer <access_token>- Для М2М:
X-Organization-Id: <organizationId>
Основные маршруты¶
Iris доступен по двум одинаковым префиксам:
POST /api/iris/queueGET /api/iris/queue?id=<taskId>
Также доступны алиасы:
POST /api/tasks/queueGET /api/tasks/queue?id=<taskId>
Схема работы¶
Внешняя система
|
| POST /api/iris/queue
v
Cargorun Iris
|
| создает taskId
| запускает обработку
v
Внутренний обработчик
|
| формирует результат
v
Iris task result
| \
| \__ GET /api/iris/queue?id=...
|
\____ webhook callback, если настроен
Жизненный цикл задачи¶
1. Создание¶
Клиент отправляет QueuedApiTaskCommandsCollectionModel (см. Scalar/openapi json).
На каждый элемент commands[] сервер создает отдельную Iris-задачу.
2. Выполнение¶
Задача получает один из статусов:
Awaiting: создана, ожидает выполненияInProgress: выполняетсяCompleted: завершенаError: завершилась с ошибкой
3. Получение результата¶
Результат можно получить:
- опросом через
GET /api/iris/queue?id=<taskId> - webhook-уведомлением, если он настроен в
SyncSystem
Откуда берутся изменения для чтения¶
Когда в системе изменяется сущность, CARGO.RUN Логистика публикует это изменение во внутреннюю таблицу pending-изменений.
Изменение сохраняется:
- отдельно для каждого sync user
- только для тех sync users, у которых есть подходящий
SyncSystem - кроме того sync user, который сам сделал изменение
То есть Iris читает не "все изменения в системе вообще", а только pending-изменения для конкретного sync user.
Режимы SyncSystem¶
У каждого sync user есть SyncSystem.Behavior. Для Iris это влияет на чтение изменений.
Read¶
Поведение по умолчанию.
Смысл:
- клиент читает изменения
- после успешного
Readэти pending-изменения считаются прочитанными - отдельное подтверждение не требуется
ReadConfirmation¶
Режим чтения с подтверждением.
Смысл:
- клиент читает изменения
- после чтения pending-изменения не удаляются
- затем клиент должен отдельно подтвердить, что он действительно обработал эти версии
Подтверждение выполняется действием ReadConfirmation.
Когда использовать Read, а когда ReadConfirmation¶
Read подходит, если:
- достаточно факта успешного ответа от API
- внешний клиент не требует отдельного ack-цикла
ReadConfirmation подходит, если:
- внешний клиент хочет явно подтверждать обработку данных
- важно не потерять изменение между моментом чтения и моментом фактической записи во внешнюю систему
Действия Iris¶
Iris поддерживает пять действий:
WriteReadReadConfirmationReadQueryDelete
Формат запроса на постановку задач¶
Общая форма¶
Ответ:
{
"latencyMsec": 120,
"enqueuedInMsec": 15,
"commands": [
{
"id": 123456,
"action": "Write",
"status": "Success",
"readyInMsec": 120
}
]
}
Если конкретная задача не была поставлена в очередь, у нее будет:
status = Failedid = null
Write¶
Write используется для создания или обновления объектов во внутренней системе.
Объекты передаются в objects[], где:
type— тип сущностиmodelType— тип моделиbody— данные объектаid— внутренний id, если обновляется существующая записьversion— версия объекта, если нужен optimistic concurrency controlkey— внешний ключ объекта
Общий смысл:
- если
idне передан, обычно создается новый объект - если
idпередан, обычно обновляется существующий объект - конкретная логика зависит от обработчика соответствующей сущности
Read¶
Read используется для чтения изменений.
Есть три основных режима.
Вариант 1. Прочитать все pending-изменения¶
Передается action = Read и пустой список objects.
Пример:
В этом случае Iris вернет все pending-изменения для текущего sync user.
Вариант 2. Прочитать все pending-изменения только по определенным типам¶
Передаются объекты без id, но с type.
Пример:
В этом случае Iris:
- берет все pending-изменения только по типам
DriverиCar - формирует по ним результирующие объекты
Вариант 3. Прочитать конкретный объект¶
Передается объект с id.
Пример:
Такой сценарий читает сам объект, а не список pending-изменений по типу.
ReadConfirmation¶
ReadConfirmation доступен только если для текущего sync user в SyncSystem установлен Behavior = ReadConfirmation.
Смысл действия:
- клиент подтверждает, что ранее прочитанная версия объекта действительно обработана
Пример:
{
"commands": [
{
"action": "ReadConfirmation",
"objects": [
{
"type": "Driver",
"id": 100500,
"version": "11111111-2222-3333-4444-555555555555"
}
]
}
]
}
Как это работает:
- сервер находит pending-версию для текущего sync user,
entityIdиtype - сравнивает переданную
versionс текущей pending-версией - если версия совпала, подтверждение успешно и pending-запись удаляется
- если версия не совпала, возвращается
VersionMismatch, а в ответе отдается актуальная версия
Важно¶
Для ReadConfirmation нужно передавать корректную версию, полученную из предыдущего Read.
ReadQuery¶
ReadQuery используется для выборочного чтения по query, а не по pending-изменениям.
Особенности:
- это не "забрать изменения", а "выполнить запрос"
id,versionиkeyдолжны быть пустымиqueryдолжен быть заполнен- по одному
typeможно передать только один объект в рамках одной команды
Пример:
{
"commands": [
{
"action": "ReadQuery",
"objects": [
{
"type": "Driver",
"query": "$filter=isDeleted eq false&$top=100"
}
]
}
]
}
Delete¶
Delete используется для удаления объектов.
Для Delete обязательно передавать id.
Пример:
Получение результата задачи¶
Endpoint¶
GET /api/iris/queue?id=<taskId>
Ответ¶
Пример:
{
"message": null,
"status": "Completed",
"readyInMsec": 100,
"remainingObjectCount": 0,
"attemptCount": 1,
"maxAttemptCount": 3,
"nextRetryAt": null,
"callbackStatus": "Delivered",
"callbackAttemptCount": 1,
"callbackMaxAttemptCount": 3,
"callbackNextRetryAt": null,
"callbackDeliveredAt": "2026-06-29T10:00:00Z",
"lastError": null,
"objects": [
{
"key": "ext-driver-1",
"type": "Driver",
"sourceType": null,
"id": 100500,
"version": "11111111-2222-3333-4444-555555555555",
"body": {},
"message": null,
"status": "Success"
}
]
}
Если задача еще выполняется, сервер добавляет HTTP-заголовок:
Retry-After: <seconds>
Его можно использовать как минимальную паузу до следующего poll-запроса.
Статусы объектов в результате¶
Created: промежуточный статус, результат создан, но еще не завершенSuccess: объект обработан успешноError: объект завершился ошибкойVersionMismatch: подтверждение чтения не прошло, потому что версия уже изменилась
Polling-сценарий¶
Рекомендуемый цикл:
1. POST /api/iris/queue
2. Получить taskId
3. Подождать примерно readyInMsec или Retry-After
4. GET /api/iris/queue?id=taskId
5. Повторять, пока status не станет Completed или Error
Webhook¶
Iris может отправлять webhook после завершения задачи.
Webhook берется из SyncSystem.Callback текущего sync user в момент создания задачи.
Это означает:
- если у sync user не настроен callback URL, webhook не будет
- если callback потом изменить, уже созданные задачи используют старый snapshot настроек
Когда webhook отправляется¶
Webhook ставится в очередь доставки, когда задача переходит в Completed или Error, и для нее есть callback URL.
Важно¶
Webhook не отправляется "на каждый изменившийся объект". Он отправляется на завершенную Iris-задачу.
Формат webhook-запроса¶
Метод:
POST <callback-url>
Content-Type: application/json
Заголовки:
X-Cargorun-Task-Id: строковыйtaskIdX-Cargorun-Webhook-Event:queued-task.finishedX-Cargorun-Webhook-Timestamp: Unix timestamp в секундахX-Cargorun-Webhook-Signature:sha256=<hex>— только если настроен секрет
Подпись считается так:
Тело webhook содержит:
eventIdtaskIdactionstatuscompletedAtattemptCountmaxAttemptCountmessageobjects
Пример:
{
"eventId": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
"taskId": 123456,
"action": "Read",
"status": "Completed",
"completedAt": "2026-06-29T10:00:00Z",
"attemptCount": 1,
"maxAttemptCount": 3,
"message": null,
"objects": [
{
"key": "ext-driver-1",
"type": "Driver",
"sourceType": null,
"id": 100500,
"version": "11111111-2222-3333-4444-555555555555",
"body": {},
"message": null,
"status": "Success"
}
]
}
Поведение webhook-доставки¶
Если callback возвращает успешный HTTP-статус, доставка считается успешной.
Если callback возвращает:
408429- любой
5xx - сетевую ошибку
такая ошибка считается retryable, и Iris попытается повторить доставку.
Статус webhook-доставки можно видеть в результате задачи:
NoneAwaitingInProgressDeliveredError
Схема webhook¶
Iris task
|
| завершилась
v
Webhook delivery queue
|
| POST callback URL
v
Система клиента
|
| 2xx -> Delivered
| error/timeout -> retry or Error
Связь между чтением изменений и webhook¶
Есть два независимых механизма:
Read/ReadConfirmation— клиент сам забирает изменени�� из Iris- webhook — клиент получает уведомление, что конкретная Iris-задача завершилась
Webhook не заменяет ReadConfirmation.
Если у sync user стоит Behavior = ReadConfirmation, то:
- сначала клиент делает
Read - затем получает данные
- затем, когда внешняя система их реально обработала, отправляет
ReadConfirmation
Webhook в этом сценарии только сообщает о завершении самой Iris-зачи, но не является подтверждением прочтения изменений.
Практические сценарии¶
Сценарий 1. Забор всех новых изменений¶
1. POST /api/iris/queue с action=Read и пустым objects
2. Получить taskId
3. Дождаться Completed
4. Забрать objects из результата
5. Если режим ReadConfirmation не используется, изменения автоматически считаются прочитанными
Сценарий 2. Забор изменений с явным подтверждением¶
1. POST /api/iris/queue с action=Read
2. Получить версии объектов
3. Обработать данные во внешней системе
4. POST /api/iris/queue с action=ReadConfirmation
5. Передать id + type + version для подтверждения
Сценарий 3. Асинхронная запись объекта¶
1. POST /api/iris/queue с action=Write
2. Получить taskId
3. Polling или webhook
4. На Completed проверить objects[].status и objects[].message
Типовые ошибки¶
400 Bad Request¶
Обычно означает:
- невалидный body
- для
Deleteне переданid - для
ReadQueryпереданыid,versionилиkey - для
ReadQueryне переданquery - для
ReadConfirmationпередан недопустимый набор полей - комбинация
action/type/modelType/sourceTypeне поддерживается
401 Unauthorized¶
Обычно означает:
- невалидный bearer token
- не передан
X-Organization-Id - integration client не имеет доступа к организации
404 или пустой результат при чтении статуса¶
Обычно означает:
- указан неверный
taskId - задача принадлежит другой организации
Рекомендации клиенту¶
- В случае с M2M авторизацией, всегда передавать
X-Organization-Idдля Iris. - Для интеграций с подтверждением доставки данных использовать
ReadConfirmation. - Для webhook проверять HMAC-подпись, если настроен секрет.
- Сохранять
taskId,id,typeиversionиз результатов чтения. - Обрабатывать
VersionMismatchкак сигнал, что объект уже изменился и нужно брать новую версию. - Не считать webhook подтверждением чтения в сценарии
ReadConfirmation.