Прочитать запросы на согласование и решить их

Получите список запросов на согласование, которых ждут выполнения, и одобрите или отклоните запрос.

Согласование — это запрос решения человека, которого ждёт выполнение. Его создаёт узел Требуется одобрение, а также узел AI-модель, чья политика перерасхода просит человека. Операции этой страницы перечисляют запросы и решают их. Консоль показывает те же запросы на Согласования.

Кто читает и кто решает

Чтение запросов требует разрешения management:read. Решение требует management:write, потому что решение позволяет выполнению тратить деньги. Журнал аудита записывает каждое решение.

Ключ читает и решает запросы своего проекта. Запрос другого проекта или несуществующий отвечает 404 с кодом approval_not_found.

Список идёт от новых к старым и читается страница за страницей, как описывает статья Запросы. Отправьте status=pending, чтобы читать только запросы, которые ещё ждут.

Что делает решение

  • Тело необязательно. Его reason длиной до 500 символов сохраняется с согласованием и видно в трассировке выполнения.

  • Ответ — согласование с новым status и decided_at. Решение, принятое API-ключом, называет ключ в decided_by. Решение, принятое в консоли, называет человека в decided_by_user_id и decided_by_name.

  • Запрос не двигает выполнение. Выполнение продолжается в течение минуты: через порт Одобрено после одобрения и через Отклонено после отклонения.

  • Запрос от узла модели решается так же. Одобрение позволяет вызову модели продолжиться с новым холдом, а отклонение отказывает в нём с overrun_stopped — статья Согласования говорит, что дальше.

  • Slen отправляет событие вебхука approval.decided с решением.

Запрос, который больше нельзя решить

Запрос ждёт до expires_at. Автор узла Требуется одобрение задаёт время на узле, а запрос от узла модели ждёт 24 часа. Когда никто не решил вовремя, запрос в течение минуты становится expired, а approval.decided говорит expired. Дальше всё идёт так же, как после отклонения: из узла Требуется одобрение выполнение выходит через Отклонено, а вызову узла модели отказано с overrun_stopped.

  • Запрос, который больше не pending, отвечает 409 с кодом approval_already_decided: его кто-то решил, или его срок истёк.

  • Запрос, который ещё pending, когда его время прошло, отвечает 409 с кодом approval_expired. Он сразу закрывается как expired, будто никто не решил, и выполнение идёт дальше так же, как после отклонения.

  • Запрос, выполнение которого закончилось и больше не ждёт, отвечает тем же approval_expired. Он закрывается как expired, ничего не продолжается, и событие вебхука не отправляется.

Операции

Описания операций и полей приведены на английском.

Согласования, которых ждут выполнения

GET /v1/approvals

  • Разрешение: management:read

Параметры

ПараметрОписание
limit необязательно

queryinteger

Page size (default 30).

  • Минимум: 1
  • Максимум: 100
cursor необязательно

querystring

  • Максимальная длина: 32
status необязательно

queryApprovalStatus

  • Одно из: pending, approved, rejected, expired
project необязательно

querystring

current narrows the list to the active project — an API key's own, a person's as switched on POST /api/auth/me/project — plus the organization's rows where the resource has them. A literal, never an id: anything else is 422. Without it the list is everything within the caller's reach.

  • Одно из: current

Ответы

200

One cursor page of approvals

application/json
{
  "data": [
    {
      "approval_id": "74438200973594624",
      "project_id": "74438200973594624",
      "execution_id": "74438200973594624",
      "flow_id": "74438200973594624",
      "node_key": "string",
      "operation_code": "generate_email",
      "note": "string",
      "status": "pending",
      "decided_by": "string",
      "decided_by_user_id": "74438200973594624",
      "decided_by_name": "string",
      "reason": "string",
      "expires_at": "2026-10-02T09:30:00Z",
      "created_at": "2026-10-02T09:30:00Z",
      "decided_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 (insufficient_scope), policy or tenant (not_a_member); a blocked end customer (customer_blocked); an act only a signed-in person may take (session_required); the role rule on members and invitations (member_forbidden, invite_forbidden); a write to the organization's own rows, or a read of the audit journal, by a caller that does not reach every project (project_access_restricted)

422

Validation failure or a semantically impossible request. Field-level validation from the framework answers {"message", "errors"}; domain refusals answer the standard error envelope. An Idempotency-Key longer than 190 characters is invalid_request in that envelope.

Заголовки

  • X-Request-Id

Тело каждой ошибки — конверт ошибки.

Одобрить выполнение

POST /v1/approvals/{id}/approve

  • Разрешение: management:write

A person's verdict names them (decided_by_user_id, decided_by_name); a key's names the key in decided_by, as before.

409 approval_already_decided — the request has left pending: somebody decided it, its deadline passed, or its execution ended. 409 approval_expired — this very call found the request past its expires_at, or found that the execution it belongs to is no longer waiting (it failed, was lost or ran into its parked ceiling); the request is closed as expired and nothing is continued.

A verdict that is accepted is announced to webhook subscribers as approval.decided (see createWebhookEndpoint), and the node that asked leaves {status, reason, approval_id, decided_at} in its output: a refusal and a deadline nobody met both leave through rejected, and nodes.<key>.output.status (rejected / expired) tells them apart.

Параметры

ПараметрОписание
id обязательно

pathId

Snowflake identifier, as a string.

  • Шаблон: ^\d+$
  • Пример: 74438200973594624

Тело запроса необязательно

application/json
{
  "reason": "string"
}

Ответы

200

The decided approval

application/json
{
  "data": {
    "approval_id": "74438200973594624",
    "project_id": "74438200973594624",
    "execution_id": "74438200973594624",
    "flow_id": "74438200973594624",
    "node_key": "string",
    "operation_code": "generate_email",
    "note": "string",
    "status": "pending",
    "decided_by": "string",
    "decided_by_user_id": "74438200973594624",
    "decided_by_name": "string",
    "reason": "string",
    "expires_at": "2026-10-02T09:30:00Z",
    "created_at": "2026-10-02T09:30:00Z",
    "decided_at": "2026-10-02T09:30:00Z"
  }
}

Ошибки

СтатусКодыКогда
401

No credential, or one that is not valid

403

Authenticated, but not allowed: scope (insufficient_scope), policy or tenant (not_a_member); a blocked end customer (customer_blocked); an act only a signed-in person may take (session_required); the role rule on members and invitations (member_forbidden, invite_forbidden); a write to the organization's own rows, or a read of the audit journal, by a caller that does not reach every project (project_access_restricted)

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 (last_owner); the owned-organization limit (organization_limit_reached); an end customer with credit history that cannot be deleted (customer_has_history)

422

Validation failure or a semantically impossible request. Field-level validation from the framework answers {"message", "errors"}; domain refusals answer the standard error envelope. An Idempotency-Key longer than 190 characters is invalid_request in that envelope.

Заголовки

  • X-Request-Id

Тело каждой ошибки — конверт ошибки.

Отклонить выполнение

POST /v1/approvals/{id}/reject

  • Разрешение: management:write

A person's verdict names them (decided_by_user_id, decided_by_name); a key's names the key in decided_by, as before.

409 approval_already_decided — the request has left pending: somebody decided it, its deadline passed, or its execution ended. 409 approval_expired — this very call found the request past its expires_at, or found that the execution it belongs to is no longer waiting (it failed, was lost or ran into its parked ceiling); the request is closed as expired and nothing is continued.

A verdict that is accepted is announced to webhook subscribers as approval.decided (see createWebhookEndpoint), and the node that asked leaves {status, reason, approval_id, decided_at} in its output: a refusal and a deadline nobody met both leave through rejected, and nodes.<key>.output.status (rejected / expired) tells them apart.

Параметры

ПараметрОписание
id обязательно

pathId

Snowflake identifier, as a string.

  • Шаблон: ^\d+$
  • Пример: 74438200973594624

Тело запроса необязательно

application/json
{
  "reason": "string"
}

Ответы

200

The decided approval

application/json
{
  "data": {
    "approval_id": "74438200973594624",
    "project_id": "74438200973594624",
    "execution_id": "74438200973594624",
    "flow_id": "74438200973594624",
    "node_key": "string",
    "operation_code": "generate_email",
    "note": "string",
    "status": "pending",
    "decided_by": "string",
    "decided_by_user_id": "74438200973594624",
    "decided_by_name": "string",
    "reason": "string",
    "expires_at": "2026-10-02T09:30:00Z",
    "created_at": "2026-10-02T09:30:00Z",
    "decided_at": "2026-10-02T09:30:00Z"
  }
}

Ошибки

СтатусКодыКогда
401

No credential, or one that is not valid

403

Authenticated, but not allowed: scope (insufficient_scope), policy or tenant (not_a_member); a blocked end customer (customer_blocked); an act only a signed-in person may take (session_required); the role rule on members and invitations (member_forbidden, invite_forbidden); a write to the organization's own rows, or a read of the audit journal, by a caller that does not reach every project (project_access_restricted)

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 (last_owner); the owned-organization limit (organization_limit_reached); an end customer with credit history that cannot be deleted (customer_has_history)

422

Validation failure or a semantically impossible request. Field-level validation from the framework answers {"message", "errors"}; domain refusals answer the standard error envelope. An Idempotency-Key longer than 190 characters is invalid_request in that envelope.

Заголовки

  • X-Request-Id

Тело каждой ошибки — конверт ошибки.

Примеры

Прочитать запросы, которые ждут

Одно выполнение ждёт решения у своего узла review. Заметку оставил на узле автор флоу.

Terminal
curl "https://api.slen.ai/api/v1/approvals?status=pending" \
  -H "Authorization: Bearer $SLEN_API_KEY"
200 OK
{
  "data": [
    {
      "approval_id": "74443031076798464",
      "project_id": "74438200973594624",
      "execution_id": "74443028719599616",
      "flow_id": "74438623450128384",
      "node_key": "review",
      "operation_code": "generate_email",
      "note": "Check the tone before the email goes out.",
      "status": "pending",
      "decided_by": null,
      "decided_by_user_id": null,
      "decided_by_name": null,
      "reason": null,
      "expires_at": "2026-10-03T09:20:11+00:00",
      "created_at": "2026-10-02T09:20:11+00:00",
      "decided_at": null
    }
  ],
  "meta": {
    "limit": 30,
    "next_cursor": null
  }
}

Одобрить запрос

Ответ — согласование с решением и ключом, который его принял.

Terminal
curl -X POST https://api.slen.ai/api/v1/approvals/74443031076798464/approve \
  -H "Authorization: Bearer $SLEN_API_KEY"
200 OK
{
  "data": {
    "approval_id": "74443031076798464",
    "project_id": "74438200973594624",
    "execution_id": "74443028719599616",
    "flow_id": "74438623450128384",
    "node_key": "review",
    "operation_code": "generate_email",
    "note": "Check the tone before the email goes out.",
    "status": "approved",
    "decided_by": "74438344587730944",
    "decided_by_user_id": null,
    "decided_by_name": null,
    "reason": null,
    "expires_at": "2026-10-03T09:20:11+00:00",
    "created_at": "2026-10-02T09:20:11+00:00",
    "decided_at": "2026-10-02T09:31:40+00:00"
  }
}

Отклонить запрос

Причина сохраняется с согласованием. Выполнение выходит из узла через Отклонено.

Terminal
curl https://api.slen.ai/api/v1/approvals/74443031076798464/reject \
  -H "Authorization: Bearer $SLEN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "reason": "The customer asked us not to write again."
  }'
200 OK
{
  "data": {
    "approval_id": "74443031076798464",
    "project_id": "74438200973594624",
    "execution_id": "74443028719599616",
    "flow_id": "74438623450128384",
    "node_key": "review",
    "operation_code": "generate_email",
    "note": "Check the tone before the email goes out.",
    "status": "rejected",
    "decided_by": "74438344587730944",
    "decided_by_user_id": null,
    "decided_by_name": null,
    "reason": "The customer asked us not to write again.",
    "expires_at": "2026-10-03T09:20:11+00:00",
    "created_at": "2026-10-02T09:20:11+00:00",
    "decided_at": "2026-10-02T09:31:40+00:00"
  }
}

Что читать дальше

Собрано из openapi b070e1f, sdk contract 5cc7055, php ae4a53b, node 84bc62d