Budgets
A Budget is a spend boundary for one billing user. It is not a wallet, a funding source, or an authorize-time reservation.
Two identifiers, two roles
budget_idis Vluna's internal identifier. Management endpoints keep using it for list, get, close, support, and reporting joins.budgetis an immutable external reference. Your integration can choose it and pass it through Gate requests without storing a Vluna UUID.
The external reference is unique within the billing account and billing user. It is opaque to Vluna: use a run id, job id, or another stable resource id whose scope and lifecycle your system owns. Do not put secrets in it.
Create a Budget
POST /mgt/v1/budgets accepts optional budget:
{
"budget": "run_01K4Q6FJ2B",
"name": "Email assistant run",
"scope_kind": "global",
"limit_xusd": "50000000"
}
The response returns both identifiers:
{
"ok": true,
"data": {
"budget_id": "8a53a407-975d-491d-811b-d9168915484e",
"budget": "run_01K4Q6FJ2B",
"status": "active",
"consumed_xusd": "0"
}
}
If budget is omitted, Vluna generates budget_id and uses the same string as
the external reference. This keeps the simple store-and-forward flow available
without introducing a second generated value.
Select it in Gate requests
Pass the external reference as budget in authorize or direct ingest:
{
"lease": "run_01K4Q6FJ2B:model-call:1",
"budget": "run_01K4Q6FJ2B",
"feature_code": "openai.gpt-4o",
"estimated_quantity_minor": "1200"
}
Authorize resolves the reference in the current account/user namespace and
binds the internal Budget to the lease. Commit therefore needs only lease; it
does not accept budget again. Direct ingest has no lease, so it accepts
budget on each request.
Gate responses and operational facts may return budget_id. Treat it as a
diagnostic and join key, not as the value your runtime must carry between its
own resources.
Management remains ID-based
Use the internal UUID for:
GET /mgt/v1/budgets/{budget_id}POST /mgt/v1/budgets/{budget_id}/close- support, audit, and reporting joins
Creating an external reference does not rename these management APIs. This separation keeps runtime mapping convenient without making a user-controlled identifier the database primary key.
Failure and lifecycle rules
- Reusing an external reference in the same account/user namespace returns a conflict.
- Gate selection of an unknown reference returns
422withRESOURCE.NOT_FOUND. - The Budget must be active and within its configured window when evaluated.
- Authorize checks current headroom but reserves nothing. If work fails, send no compensation request. Only committed or ingested usage consumes the Budget.
Next
- Runtime authorization: Authorize
- Direct usage writes: Ingest
- Funding model: Funding and grants overview