Создавать, читать и менять бюджеты

Получите список бюджетов с тем, что от них осталось, создайте бюджет, измените его лимит, отправьте его в архив или восстановите.

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

Виды бюджетов

type говорит, что считает бюджет.

typeЧто он ограничивает
daily, weekly, monthlyУдержанное и списанное в текущий день, неделю или месяц. Следующий начинается с нуля, и resets_at говорит когда
totalУдержанное и списанное навсегда. Он заново не начинается
per_operationОдин холд: холд больше лимита отклоняется с operation_limit_exceeded. Ничего не суммируется
concurrencyХолды, которые открыты одновременно. limit_amount — их число, и ещё один отклоняется с concurrency_limit_exceeded

Денежный бюджет считает списанное и удержанное вместе, и холд, который вывел бы их за лимит, отклоняется с budget_exceeded. Статья Как работает резервирование бюджета объясняет холд.

Что покрывает бюджет

  • scope, равный project, создаёт бюджет проекта ключа. organization создаёт бюджет всей организации, который считает траты каждого проекта.

  • operation_code сужает бюджет до вызовов одной операции. Без него бюджет покрывает каждый вызов.

  • type, scope и operation_code потом изменить нельзя: учтённые по ним траты за ними не последуют. Вместо этого создайте другой бюджет.

Ключ читает бюджеты своего проекта и бюджеты организации. Создаёт, меняет и отправляет в архив он только бюджеты своего проекта: запись в бюджет организации отвечает 403 с кодом project_access_restricted. Бюджет другого проекта или несуществующий отвечает 404 с кодом budget_not_found.

Кто может менять бюджет

Чтение требует разрешения read. Создание, изменение и отправка в архив требуют management:write: ключ, которым тратит приложение, — gateway:write, — читает бюджеты и не может их менять. Такой запрос отвечает 403 с кодом insufficient_scope. Журнал аудита записывает каждое создание, изменение и отправку в архив.

Изменить, отправить в архив и восстановить

  • Новый limit_amount действует со следующего холда, в уже открытом окне. Лимит ниже того, что окно уже использовало, принимается: новый холд не помещается, пока окно не начнётся заново или лимит не поднимут.

  • name — ваша собственная метка. null её стирает, а запрос без неё её сохраняет.

  • Отправка в архив сохраняет бюджет и выводит его из новых холдов. Уже взятые холды всё равно рассчитываются. status, равный active, восстанавливает его.

  • Список не показывает архивные бюджеты, если не отправить include_archived=1.

Изменение ждёт вызовы, которые в этот момент удерживают деньги по бюджету. Когда ожидание слишком долгое, оно отвечает 503 с кодом service_unavailable и заголовком Retry-After, и ничего не меняется. Отправьте тот же запрос снова.

События бюджета

Холд сообщает, насколько использован бюджет: budget.threshold_reached на 50 % и на 80 % лимита, budget.exceeded на всём лимите.

  • О каждом уровне сообщается не больше раза за окно, а холд, который проходит два уровня сразу, сообщает только о более высоком.

  • Бюджеты типов per_operation и concurrency таких событий не отправляют.

  • Изменение лимита событий не отправляет. Лимит, опущенный ниже того, что окно использовало, не пропускает ни одного холда, поэтому budget.exceeded в этом окне для него не приходит. Поднятый лимит не сообщает заново об уровнях, о которых это окно уже сообщило.

Операции

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

Список бюджетов с текущим остатком

GET /v1/budgets

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

Параметры

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

queryinteger

1 lists the archived budgets too; 0, the default, does not — the reserve path only knows active budgets. A flag in the query string is 1 or 0: true and false are a field-validation 422.

  • Одно из: 0, 1
  • По умолчанию: 0

Ответы

200

Budgets of the caller's organization/project

application/json
{
  "data": [
    {
      "budget_id": "74438200973594624",
      "name": "string",
      "project_id": "74438200973594624",
      "type": "daily",
      "scope": "organization",
      "operation_code": "generate_email",
      "status": "active",
      "limit_amount": "0.02700000",
      "reserved_amount": "0.02700000",
      "captured_amount": "0.02700000",
      "available_amount": "0.02700000",
      "currency": "USD",
      "resets_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)

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.

429

Rate limited for this API key

Заголовки

  • X-Request-Id
  • Retry-After429

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

Создать бюджет

POST /v1/budgets

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

A budget is configuration of what may be spent: the key an application runs operations with (gateway:write) reads budgets and cannot create, change or archive one (403 insufficient_scope). In the console that is the owner and the admin; a developer reads. A successful create, change or archive is written to the audit journal as budget.create, budget.update, budget.archive (GET /v1/management/audit-logs, resource_type budget).

scope=organization needs a caller that reaches every project (403 project_access_restricted); scope=project is the active project. The answer already carries resets_at.

Тело запроса

application/json
{
  "type": "daily",
  "limit_amount": "0.02700000",
  "scope": "organization",
  "operation_code": "generate_email",
  "name": "string"
}

Ответы

201

The created budget

application/json
{
  "data": {
    "budget_id": "74438200973594624",
    "name": "string",
    "project_id": "74438200973594624",
    "type": "daily",
    "scope": "organization",
    "operation_code": "generate_email",
    "status": "active",
    "limit_amount": "0.02700000",
    "reserved_amount": "0.02700000",
    "captured_amount": "0.02700000",
    "available_amount": "0.02700000",
    "currency": "USD",
    "resets_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)

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.

429

Rate limited for this API key

Заголовки

  • X-Request-Id
  • Retry-After429

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

Изменить лимит или вернуть бюджет из архива

PATCH /v1/budgets/{id}

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

Audited as budget.update (see createBudget).

A new limit_amount binds the very next authorization, in the window that is already open — the current day, week or month, or the one window of a budget that never resets. A limit below what the window has already spent is accepted: it admits no further hold, and the holds taken before it still capture and release.

The budget webhooks are about holds, not about this request: changing a limit sends none. budget.threshold_reached (50 %, 80 %) and budget.exceeded (100 %) are announced by the first successful hold that finds a level crossed under the limit in force, each level once per window. Two consequences. A limit lowered below what the window already holds admits no hold, so budget.exceeded is not sent for it until the window turns — never, for a budget that does not reset; read available_amount in the answer instead. A limit raised does not re-arm the levels already announced in this window: they stay silent until the window turns, although under the new limit they are not reached.

A budget of no project caps every project: only a caller that reaches every project changes or archives it (403 project_access_restricted).

Параметры

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

pathId

Snowflake identifier, as a string.

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

Тело запроса

application/json
{
  "limit_amount": "0.02700000",
  "status": "active",
  "name": "string"
}

Ответы

200

The updated budget

application/json
{
  "data": {
    "budget_id": "74438200973594624",
    "name": "string",
    "project_id": "74438200973594624",
    "type": "daily",
    "scope": "organization",
    "operation_code": "generate_email",
    "status": "active",
    "limit_amount": "0.02700000",
    "reserved_amount": "0.02700000",
    "captured_amount": "0.02700000",
    "available_amount": "0.02700000",
    "currency": "USD",
    "resets_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.

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.

503

service_unavailable: the change waited for calls in flight on this budget — a reserve, capture or release holding its window — for longer than the database lets a lock be waited for, and was rolled back whole. Nothing was changed: neither the limit, nor the status, nor the name. Send the same request again.

Заголовки

  • X-Request-Id
  • Retry-After503

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

Отправить бюджет в архив

DELETE /v1/budgets/{id}

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

Archive, not delete: reservations settle against the budget_usage rows this budget owns. Audited as budget.archive (see createBudget).

A budget of no project caps every project: only a caller that reaches every project changes or archives it (403 project_access_restricted).

Параметры

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

pathId

Snowflake identifier, as a string.

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

Ответы

200

The archived budget

application/json
{
  "data": {
    "budget_id": "74438200973594624",
    "name": "string",
    "project_id": "74438200973594624",
    "type": "daily",
    "scope": "organization",
    "operation_code": "generate_email",
    "status": "active",
    "limit_amount": "0.02700000",
    "reserved_amount": "0.02700000",
    "captured_amount": "0.02700000",
    "available_amount": "0.02700000",
    "currency": "USD",
    "resets_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.

503

service_unavailable: the change waited for calls in flight on this budget — a reserve, capture or release holding its window — for longer than the database lets a lock be waited for, and was rolled back whole. Nothing was changed: neither the limit, nor the status, nor the name. Send the same request again.

Заголовки

  • X-Request-Id
  • Retry-After503

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

Примеры

Получить список бюджетов

Месячный бюджет проекта использовал 432 из 500: 419,60 списано и 12,40 ещё удержано.

Terminal
curl https://api.slen.ai/api/v1/budgets \
  -H "Authorization: Bearer $SLEN_API_KEY"
200 OK
{
  "data": [
    {
      "budget_id": "74437302811459584",
      "name": "Production",
      "project_id": "74438200973594624",
      "type": "monthly",
      "scope": "project",
      "operation_code": null,
      "status": "active",
      "limit_amount": "500.00000000",
      "reserved_amount": "12.40000000",
      "captured_amount": "419.60000000",
      "available_amount": "68.00000000",
      "currency": "USD",
      "resets_at": "2026-11-01T00:00:00+00:00"
    },
    {
      "budget_id": "74437291503616000",
      "name": null,
      "project_id": null,
      "type": "total",
      "scope": "organization",
      "operation_code": null,
      "status": "active",
      "limit_amount": "10000.00000000",
      "reserved_amount": "12.40000000",
      "captured_amount": "2361.27500000",
      "available_amount": "7626.32500000",
      "currency": "USD",
      "resets_at": null
    }
  ]
}

Создать бюджет

Дневной бюджет одной операции в проекте ключа. Ответ уже говорит, когда кончается его окно.

Terminal
curl https://api.slen.ai/api/v1/budgets \
  -H "Authorization: Bearer $SLEN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "daily",
    "scope": "project",
    "operation_code": "generate_email",
    "limit_amount": "25",
    "name": "Follow-up emails"
  }'
201 Created
{
  "data": {
    "budget_id": "74443127894704128",
    "name": "Follow-up emails",
    "project_id": "74438200973594624",
    "type": "daily",
    "scope": "project",
    "operation_code": "generate_email",
    "status": "active",
    "limit_amount": "25.00000000",
    "reserved_amount": "0.00000000",
    "captured_amount": "0.00000000",
    "available_amount": "25.00000000",
    "currency": "USD",
    "resets_at": "2026-10-03T00:00:00+00:00"
  }
}

Поднять лимит

Новый лимит действует со следующего холда. Удержанное и списанное остаются как были.

Terminal
curl -X PATCH https://api.slen.ai/api/v1/budgets/74437302811459584 \
  -H "Authorization: Bearer $SLEN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "limit_amount": "750"
  }'
200 OK
{
  "data": {
    "budget_id": "74437302811459584",
    "name": "Production",
    "project_id": "74438200973594624",
    "type": "monthly",
    "scope": "project",
    "operation_code": null,
    "status": "active",
    "limit_amount": "750.00000000",
    "reserved_amount": "12.40000000",
    "captured_amount": "419.60000000",
    "available_amount": "318.00000000",
    "currency": "USD",
    "resets_at": "2026-11-01T00:00:00+00:00"
  }
}

Отправить бюджет в архив

Ответ — бюджет со status, равным archived.

Terminal
curl -X DELETE https://api.slen.ai/api/v1/budgets/74443127894704128 \
  -H "Authorization: Bearer $SLEN_API_KEY"
200 OK
{
  "data": {
    "budget_id": "74443127894704128",
    "name": "Follow-up emails",
    "project_id": "74438200973594624",
    "type": "daily",
    "scope": "project",
    "operation_code": "generate_email",
    "status": "archived",
    "limit_amount": "25.00000000",
    "reserved_amount": "0.00000000",
    "captured_amount": "0.00000000",
    "available_amount": "25.00000000",
    "currency": "USD",
    "resets_at": "2026-10-03T00:00:00+00:00"
  }
}

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

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