Выполните флоу и прочитайте его вызовы модели
Отправьте запрос через флоу, привязанный к коду операции, прочитайте операции — вызовы модели во флоу — со всеми попытками за ними и получите список холдов этих вызовов.
Две вещи на этой странице носят одно имя. Запрос к флоу называет код операции, и POST /v1/operations/execute выполняет флоу, привязанный к этому коду. Операция — это ещё и запись об одном вызове модели во флоу; два чтения этой страницы показывают список таких записей и одну запись со всеми попытками за ней. Последняя операция страницы показывает список холдов этих вызовов. Консоль показывает те же записи на странице Операции, на её вкладке Операции — экран описан в статье Операции, авторизации и реестр.
Выполнение и операция
POST /v1/operations/executeотвечает выполнением: одним проходом флоу, которое называетexecution_id. Выполнение читают снова черезGET /v1/executions/{id}/statusиGET /v1/executions/{id}.Операция — это один вызов модели, который называет
operation_id. Одна операция открывается на каждый вызов модели, который делает флоу.Идентификатор выполнения — не идентификатор операции: на него
GET /v1/operations/{id}отвечает404с кодомoperation_not_found.
Запись о вызове модели
Операция открывается, когда узел AI-модель вот-вот вызовет модель, после того как деньги на вызов зарезервированы. Она начинается со статуса pending и заканчивается одним из трёх статусов.
| Статус | Что он значит |
|---|---|
completed | Модель ответила |
failed | Вызов закончился без ответа модели |
uncertain | Неизвестно, чем закончился вызов: провайдер не ответил вовремя или принял вызов на выполнение в фоне, и его не удалось об этом вызове спросить |
Холд вызова со статусом uncertain не возвращается сразу: провайдеру, возможно, уже заплатили, поэтому холд держится, пока не истечёт. Такой вызов Slen тоже не повторяет. Когда ответ на вызов потерян, об этом сообщает событие вебхука operation.uncertain. Вызов, который провайдер выполняет в фоне, тоже сообщает, чем он закончился: operation.completed — когда провайдер ответил, operation.failed — когда вызов не удался, operation.uncertain — когда спросить провайдера о вызове больше не удалось. Чтобы найти вызовы с неизвестным исходом без вебхука, выберите операции по статусу, как в примере ниже.
Попытка — это один вызов одного подключения провайдера. Когда пул модели после сбоя переходит к другому подключению, операция получает следующую попытку с очередным номером. Попытка говорит, какое подключение и какую модель она использовала и чем она закончилась. Её cost остаётся null, пока вызов не закрыт.
Список содержит операции проекта ключа, сначала самые новые. Попытки он не показывает:
attemptsтам — пустой список. Чтобы их увидеть, прочитайте одну операцию.Операция не хранит ни промпт, ни ответ модели.
Попытка называет своё подключение и свой пул:
connection_nameиpool_name, рядом с ними —providerиconnection_deleted. Имя равноnull, если пул с тех пор удалён (pool_idостаётся) или если подключение или пул вне досягаемости ключа. Удалённое подключение сохраняет имя.finish_reason— почему провайдер остановился, так, как он это сообщил.flow_executionназывает выполнение и узел, вызовом модели которого является операция:execution_id,flow_idиnode_key. Когда выполнение вне досягаемости ключа, этоnull, и это поле есть только при чтении одной операции, не в списке.
Поиск и нумерованные страницы
q ищет по списку. Цифры, которые являются ID операции проекта, находят ровно эту операцию, какой бы старой она ни была: окно from и to к ней не применяется, а status и operation_code — применяются. Любой другой текст находит операции, у которых external_user_id равен этому тексту или начинается с него, внутри окна; % и _ там — обычные символы. На q длиннее 190 символов ответ — 422. Значение входит в адрес, поэтому external_user_id, который является адресом e-mail, попадает в историю браузеров и в журналы доступа.
Список читают курсором, как любой список, — Список по страницам, — или по номеру страницы. Отправьте page, и в meta придут page, limit, total и anchor. total считается до 10 000; дальше он остаётся 10 000, а total_capped равен true. Отправляйте anchor первой страницы со всеми остальными страницами: считаются только операции с ID не больше него, поэтому операция, открытая за это время, не сдвигает строки со страницы на страницу. На page вместе с cursor и на anchor без page ответ — 422.
Холды вызовов
GET /v1/authorizations показывает список холдов проекта, самые новые — первыми: по одному на каждый вызов модели, с тем, сколько вызов должен был стоить, сколько было зарезервировано и сколько списано. Он требует разрешения read и читает окно не длиннее семи дней, как список операций, — курсором или по номеру страницы. operation_code оставляет холды одного кода операции. Что значит каждый статус холда, объясняет статья Как работает резервирование бюджета, а консоль показывает те же холды на вкладке Авторизации экрана Операции.
Операции
Описания операций и полей приведены на английском.
Запустить флоу, привязанный к операции
POST /v1/operations/execute
- Разрешение:
gateway:write - Нужен Idempotency-Key
- Доступно в SDK для PHP и Node.js
The caller names what it wants done, never a model or a pool. Answers 202 when the flow parked at a queue or approval node — waiting_on says on what — and also when execution_mode: async handed the run to a queue worker, where the status is queued and nothing has walked yet. Both carry retry_after_seconds. Idempotent.
The Idempotency-Key belongs to the execution it opened, and no copy of the answer is kept beside it: a repeated key with the same body is answered from that execution as it is now (replayed: true) and runs nothing. 202 with retry_after_seconds while it has not finished — queued, waiting, or running when the retry met a walk still under way (a synchronous run may outlast the caller's timeout) — and 200 with the outcome once it has: output of a completed run, error_code and error_message of one that was refused or failed, even when the first answer was an error envelope — error repeats the two as {code, message}, on a replay exactly as on the first answer. The same key with a different body is 409 idempotency_conflict.
A flow that refuses is not an HTTP error: a reject node answers 200 with status: rejected. A walk that throws is one: the execution is closed — failed, rejected when the gateway refused to spend (policy_denied, customer_blocked, budget_exceeded, insufficient_credits, an overrun), uncertain when the provider's answer was lost — with the same code in its error_code, and the answer is the error envelope with the status of what threw. The code of the envelope and the code of the row are one and the same, also for what is wrong with the setup rather than refused by a policy: customer_not_found (404), model_not_allowed (403), cost_calculation_failed (422) and ledger_unavailable (503) close the execution failed with that code.
A synchronous run that outlives the running ceiling (15 minutes by default) is closed failed with execution_lost while its walk is still under way. Whatever that walk goes on to compute is not the outcome of the execution, and the call is answered with the execution as its row has it — 200, failed, execution_lost, no output, replayed: false — exactly what a repeated key is told afterwards. A model call the walk did make is paid for, and cost.actual arrives.
A model node routes a refusal to spend into its deny port when something is connected to it — policy_denied, customer_blocked, budget_exceeded, insufficient_credits, overrun_stopped — and then the flow decides what the caller hears. The setup errors above are never routed.
403 customer_blocked — the context.user_id names a customer that is blocked (POST /v1/customers/{externalUserId}/block). Nothing is created: no execution, no hold. A repeated key of an execution opened before the block is still answered by that execution. A run already under way — queued, or parked at an approval — meets the block at its next model node that takes credits: the hold is refused, and the execution closes rejected with customer_blocked (a model node with something on its deny port routes it there, like a policy refusal). A run whose operation has no price in credits takes no hold and finishes.
404 flow_not_found — no flow is bound to the operation, the flow was never published, or it is archived. Nothing is created for such a call — no execution, no hold — so the same key runs once the flow is un-archived. An execution parked before its flow was archived still finishes, and the key of an execution that exists is answered by it whatever became of the flow or its binding since: the 404 is for a key that opened nothing.
Параметры
| Параметр | Описание |
|---|---|
Idempotency-Key обязательноheader | Replay guard for a financial write. The same key returns the original result with the original status and never charges twice; a different body under a used key answers
|
Тело запроса
{
"operation": "generate_email",
"input": {},
"context": {
"user_id": "74438200973594624",
"credit_type": "default"
},
"execution_mode": "sync"
}Ответы
The finished run
{
"data": {
"execution_id": "74438200973594624",
"status": "running",
"operation": "generate_email",
"output": {},
"error_code": "string",
"error_message": "string",
"cost": {
"estimated": "0.02700000",
"actual": "0.02700000"
},
"cache": {
"hit": true,
"cached_at": "2026-10-02T09:30:00Z"
},
"waiting_on": {
"node_key": "string",
"type": "queue_node",
"resume_at": "2026-10-02T09:30:00Z"
},
"trace_url": "string",
"retry_after_seconds": 1,
"error": {
"code": "string",
"message": "string"
},
"replayed": true
}
}The run has not finished: it parked, was queued, or — on a repeated key — is still walking. Come back after retry_after_seconds.
{
"data": {
"execution_id": "74438200973594624",
"status": "running",
"operation": "generate_email",
"output": {},
"error_code": "string",
"error_message": "string",
"cost": {
"estimated": "0.02700000",
"actual": "0.02700000"
},
"cache": {
"hit": true,
"cached_at": "2026-10-02T09:30:00Z"
},
"waiting_on": {
"node_key": "string",
"type": "queue_node",
"resume_at": "2026-10-02T09:30:00Z"
},
"trace_url": "string",
"retry_after_seconds": 1,
"error": {
"code": "string",
"message": "string"
},
"replayed": true
}
}Ошибки
| Статус | Коды | Когда |
|---|---|---|
| 400 | Malformed request — e.g. the | |
| 401 | No credential, or one that is not valid | |
| 402 | Refused because of money: | |
| 403 | Authenticated, but not allowed: scope ( | |
| 404 | No such resource for this tenant. Somebody else's resource — and a resource of a project the caller does not reach — answers the same way on purpose: the two must not be distinguishable. | |
| 409 | State conflict: idempotency clash, stale draft, illegal transition; the last owner of an organization ( | |
| 422 | Validation failure or a semantically impossible request. Field-level validation from the framework answers | |
| 429 | Rate limited for this API key | |
| 500 | The walk broke and the execution is closed as | |
| 502 | The walk broke and the execution is closed as | |
| 503 | The walk broke and the execution is closed as | |
| 504 | The walk broke and the execution is closed as |
Заголовки
X-Request-IdRetry-After429
Тело каждой ошибки — конверт ошибки.
Список операций
GET /v1/operations
- Разрешение:
read
Параметры
| Параметр | Описание |
|---|---|
cursor необязательноquery | The |
limit необязательноquery | Page size (default 30).
|
page необязательноquery | The page number, from 1. Turns the list into its numbered form: the answer's
|
anchor необязательноquery | The
|
q необязательноquery | Search. Digits that are the id of an operation of the project find exactly that operation, past the window — the id carries its own moment, so
|
operation_code необязательноquery |
|
status необязательноquery |
|
from необязательноquery | Window start, ISO-8601 — a value with an offset is the moment it names, one without is read as UTC. The rule of the three lists that take this parameter (
|
to необязательноquery | Window end, ISO-8601, inclusive. See
|
Ответы
One page of operations — a cursor page, or a numbered one with page
{
"data": [
{
"operation_id": "74438200973594624",
"operation_code": "generate_email",
"external_user_id": "user_8421",
"status": "pending",
"attempts": [
{
"attempt_id": "74438200973594624",
"attempt_number": 1,
"connection_id": "74438200973594624",
"pool_id": "74438200973594624",
"model_code": "gpt-4o-mini",
"model_price_id": "74438200973594624",
"status": "pending",
"error_code": "string",
"provider_request_id": "74438200973594624",
"input_tokens": 1,
"output_tokens": 1,
"cost": "0.02700000",
"cost_multiplier": "string",
"latency_ms": 1,
"started_at": "2026-10-02T09:30:00Z",
"completed_at": "2026-10-02T09:30:00Z",
"pool_name": "string",
"connection_name": "string",
"connection_deleted": true,
"provider": "string",
"finish_reason": "string"
}
],
"created_at": "2026-10-02T09:30:00Z",
"updated_at": "2026-10-02T09:30:00Z",
"flow_execution": {
"execution_id": "74438200973594624",
"flow_id": "74438200973594624",
"node_key": "string"
}
}
],
"meta": {
"limit": 1,
"next_cursor": "string"
}
}Ошибки
| Статус | Коды | Когда |
|---|---|---|
| 401 | No credential, or one that is not valid | |
| 403 | Authenticated, but not allowed: scope ( | |
| 422 | Validation failure or a semantically impossible request. Field-level validation from the framework answers |
Заголовки
X-Request-Id
Тело каждой ошибки — конверт ошибки.
Один запрос со всеми попытками провайдеров
GET /v1/operations/{id}
- Разрешение:
read
The way to find out what an uncertain operation actually did.
Параметры
| Параметр | Описание |
|---|---|
id обязательноpath | Snowflake identifier, as a string.
|
Ответы
The operation and its attempts
{
"data": {
"operation_id": "74438200973594624",
"operation_code": "generate_email",
"external_user_id": "user_8421",
"status": "pending",
"attempts": [
{
"attempt_id": "74438200973594624",
"attempt_number": 1,
"connection_id": "74438200973594624",
"pool_id": "74438200973594624",
"model_code": "gpt-4o-mini",
"model_price_id": "74438200973594624",
"status": "pending",
"error_code": "string",
"provider_request_id": "74438200973594624",
"input_tokens": 1,
"output_tokens": 1,
"cost": "0.02700000",
"cost_multiplier": "string",
"latency_ms": 1,
"started_at": "2026-10-02T09:30:00Z",
"completed_at": "2026-10-02T09:30:00Z",
"pool_name": "string",
"connection_name": "string",
"connection_deleted": true,
"provider": "string",
"finish_reason": "string"
}
],
"created_at": "2026-10-02T09:30:00Z",
"updated_at": "2026-10-02T09:30:00Z",
"flow_execution": {
"execution_id": "74438200973594624",
"flow_id": "74438200973594624",
"node_key": "string"
}
}
}Ошибки
| Статус | Коды | Когда |
|---|---|---|
| 401 | No credential, or one that is not valid | |
| 403 | Authenticated, but not allowed: scope ( | |
| 404 | No such resource for this tenant. Somebody else's resource — and a resource of a project the caller does not reach — answers the same way on purpose: the two must not be distinguishable. |
Заголовки
X-Request-Id
Тело каждой ошибки — конверт ошибки.
Список холдов
GET /v1/authorizations
- Разрешение:
read
Параметры
| Параметр | Описание |
|---|---|
cursor необязательноquery | The |
limit необязательноquery | Page size (default 30).
|
page необязательноquery | The page number, from 1. Turns the list into its numbered form: the answer's
|
anchor необязательноquery | The
|
operation_code необязательноquery |
|
from необязательноquery | Window start, ISO-8601 — a value with an offset is the moment it names, one without is read as UTC. The rule of the three lists that take this parameter (
|
to необязательноquery | Window end, ISO-8601, inclusive. See
|
Ответы
One page of reservations — a cursor page, or a numbered one with page
{
"data": [
{
"reservation_id": "74438200973594624",
"status": "authorized",
"model_code": "gpt-4o-mini",
"operation_code": "generate_email",
"external_user_id": "user_8421",
"idempotency_key": "order-42:email",
"estimated_cost": "0.02700000",
"reserved_amount": "0.02700000",
"captured_amount": "0.02700000",
"overrun_amount": "0.02700000",
"estimated_input_tokens": 1,
"estimated_output_tokens": 1,
"max_output_tokens": 1,
"safety_multiplier": "string",
"estimation_strategy": "fixed",
"model_price_id": "74438200973594624",
"customer_hold_id": "74438200973594624",
"customer_hold_credits": "12.5000",
"currency": "USD",
"expires_at": "2026-10-02T09:30:00Z",
"created_at": "2026-10-02T09:30:00Z"
}
],
"meta": {
"limit": 1,
"next_cursor": "string"
}
}Ошибки
| Статус | Коды | Когда |
|---|---|---|
| 401 | No credential, or one that is not valid | |
| 403 | Authenticated, but not allowed: scope ( | |
| 422 | Validation failure or a semantically impossible request. Field-level validation from the framework answers |
Заголовки
X-Request-Id
Тело каждой ошибки — конверт ошибки.
Примеры
Выполнить флоу
Флоу, привязанный к generate_email, ответил сразу, поэтому статус — completed, а в output лежит то, что вернул флоу. cost.actual здесь — null: вызов модели закрывается после ответа.
curl https://api.slen.ai/api/v1/operations/execute \
-H "Authorization: Bearer $SLEN_API_KEY" \
-H "Idempotency-Key: order-42:email" \
-H "Content-Type: application/json" \
-d '{
"operation": "generate_email",
"input": {
"messages": [
{
"role": "user",
"content": "Write a short follow-up email."
}
]
}
}'{
"data": {
"execution_id": "74438200973594700",
"status": "completed",
"operation": "generate_email",
"output": {
"model": "gpt-4o",
"content": "Hi Ada, just checking in on the proposal I sent last week.",
"finish_reason": "stop",
"tool_calls": null,
"usage": {
"input_tokens": 14,
"output_tokens": 16,
"cached_input_tokens": 0
}
},
"error": null,
"error_code": null,
"error_message": null,
"cost": {
"estimated": "0.00412500",
"actual": null
},
"cache": {
"hit": false,
"cached_at": null
},
"replayed": false,
"waiting_on": null,
"trace_url": "/v1/executions/74438200973594700"
}
}Найти вызовы с неизвестным исходом
Фильтр оставляет операции со статусом uncertain одного кода операции, ID клиента которых начинается с user_84, на первой нумерованной странице. Среди них — один вызов для user_8421.
curl "https://api.slen.ai/api/v1/operations?q=user_84&operation_code=generate_email&status=uncertain&page=1" \
-H "Authorization: Bearer $SLEN_API_KEY"{
"data": [
{
"operation_id": "74442181054119936",
"operation_code": "generate_email",
"external_user_id": "user_8421",
"status": "uncertain",
"attempts": [],
"created_at": "2026-10-02T09:12:04+00:00",
"updated_at": "2026-10-02T09:13:04+00:00"
}
],
"meta": {
"limit": 30,
"page": 1,
"total": 1,
"total_capped": false,
"anchor": "74442181054119936"
}
}Прочитать вызов с его попытками
У вызова была одна попытка, через пул Primary. Подключение не ответило вовремя, поэтому попытка — uncertain, и в ней нет ни токенов, ни стоимости, ни finish_reason. Вызов — это вызов модели узла model одного флоу, и flow_execution называет его выполнение.
curl https://api.slen.ai/api/v1/operations/74442181054119936 \
-H "Authorization: Bearer $SLEN_API_KEY"{
"data": {
"operation_id": "74442181054119936",
"operation_code": "generate_email",
"external_user_id": "user_8421",
"status": "uncertain",
"attempts": [
{
"attempt_id": "74442181058314240",
"attempt_number": 1,
"connection_id": "74438912450035712",
"pool_id": "74438955400675328",
"model_code": "gpt-4o-mini",
"model_price_id": "1108",
"status": "uncertain",
"error_code": "operation_uncertain",
"provider_request_id": null,
"input_tokens": null,
"output_tokens": null,
"cost": null,
"cost_multiplier": "1.0000",
"latency_ms": 60004,
"started_at": "2026-10-02T09:12:04+00:00",
"completed_at": "2026-10-02T09:13:04+00:00",
"pool_name": "Primary",
"connection_name": "OpenAI production",
"connection_deleted": false,
"provider": "openai",
"finish_reason": null
}
],
"created_at": "2026-10-02T09:12:04+00:00",
"updated_at": "2026-10-02T09:13:04+00:00",
"flow_execution": {
"execution_id": "74442180941398016",
"flow_id": "74438623450128384",
"node_key": "model"
}
}
}Получить холды одной операции
Запрос оставляет холды generate_email за последние семь дней, по двадцать на страницу.
curl "https://api.slen.ai/api/v1/authorizations?operation_code=generate_email&limit=20" \
-H "Authorization: Bearer $SLEN_API_KEY"Что читать дальше
Отправить запрос — тот же запрос из SDK и каждое поле его ответа.
Идемпотентность — чем отвечают на повтор запроса к флоу.
Асинхронные запуски и ожидание — прочитать выполнение, которое ответило
202.Записи реестра — деньги, которые каждый вызов зарезервировал и списал.
Как работает резервирование бюджета — что холд делает с бюджетом и чем он заканчивается.
AI-флоу — как код операции привязывают к флоу.
Выполнения — статус и трассировка выполнения, которое открыл запрос.
Собрано из openapi b070e1f, sdk contract 5cc7055, php ae4a53b, node 84bc62d