Створювати, читати й змінювати бюджети

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

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

Види бюджетів

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