> For the complete documentation index, see [llms.txt](https://docs.otari.ai/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.otari.ai/api-reference/budgets.md).

# Budgets

## List Budgets

> List the deployment's budgets and the caller's organization's, with pagination.

```json
{"openapi":"3.1.0","info":{"title":"otari","version":"0.33.0"},"security":[{"ApiKeyAuth":[]},{"XApiKeyAuth":[]}],"components":{"securitySchemes":{"ApiKeyAuth":{"description":"Enter your API key here (sent as Otari-Key header).","in":"header","name":"Otari-Key","type":"apiKey"},"XApiKeyAuth":{"description":"Anthropic-native clients send credentials here (no Bearer prefix).","in":"header","name":"x-api-key","type":"apiKey"}},"schemas":{"BudgetResponse":{"description":"Response model for budget information.\n\n``max_budget``, ``token_limit`` and ``request_limit`` are the per-user\nceilings, each independent and each unlimited when null, and multiple users\ncan share one budget, so the usage rollup is an aggregate over the users\nassigned to this budget: how many there are and their combined ``spend`` /\n``reserved``.\nAssigning users to a budget is done through the users API (dashboard support\nlands with user management), so a fresh gateway reports zeros here.","properties":{"budget_duration_sec":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Budget Duration Sec"},"budget_id":{"title":"Budget Id","type":"string"},"created_at":{"title":"Created At","type":"string"},"max_budget":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Max Budget"},"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"},"organization_id":{"anyOf":[{"format":"uuid","type":"string"},{"type":"null"}],"title":"Organization Id"},"origin":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"'config' while config.yml declares this budget, in which case a start writes the declared values back over any change made through the API when the budget's entry in config.yml changed, and once on the first start after upgrading to a version that tracks this; null otherwise","title":"Origin"},"request_limit":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Request Limit"},"reset_alignment":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Reset Alignment"},"rpm_limit":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Rpm Limit"},"token_limit":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Token Limit"},"total_reserved":{"default":0,"title":"Total Reserved","type":"number"},"total_spend":{"default":0,"title":"Total Spend","type":"number"},"tpm_limit":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Tpm Limit"},"updated_at":{"title":"Updated At","type":"string"},"user_count":{"default":0,"title":"User Count","type":"integer"}},"required":["budget_id","organization_id","name","max_budget","token_limit","request_limit","budget_duration_sec","reset_alignment","created_at","updated_at"],"title":"BudgetResponse","type":"object"},"HTTPValidationError":{"properties":{"code":{"const":"invalid_request","description":"Stable error code, also sent as the Otari-Error-Code header.","title":"Code","type":"string"},"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"title":"Detail","type":"array"}},"title":"HTTPValidationError","type":"object"},"ValidationError":{"properties":{"ctx":{"title":"Context","type":"object"},"input":{"title":"Input"},"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"title":"Location","type":"array"},"msg":{"title":"Message","type":"string"},"type":{"title":"Error Type","type":"string"}},"required":["loc","msg","type"],"title":"ValidationError","type":"object"}}},"paths":{"/api/v1/budgets":{"get":{"description":"List the deployment's budgets and the caller's organization's, with pagination.","operationId":"budgets-list_budgets","parameters":[{"in":"query","name":"skip","required":false,"schema":{"default":0,"minimum":0,"title":"Skip","type":"integer"}},{"in":"query","name":"limit","required":false,"schema":{"default":100,"maximum":1000,"minimum":1,"title":"Limit","type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/BudgetResponse"},"title":"Response Budgets-List Budgets","type":"array"}}},"description":"Successful Response"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error"}},"summary":"List Budgets","tags":["budgets"]}}}}
```

## Create Budget

> Create a new budget.

```json
{"openapi":"3.1.0","info":{"title":"otari","version":"0.33.0"},"security":[{"ApiKeyAuth":[]},{"XApiKeyAuth":[]}],"components":{"securitySchemes":{"ApiKeyAuth":{"description":"Enter your API key here (sent as Otari-Key header).","in":"header","name":"Otari-Key","type":"apiKey"},"XApiKeyAuth":{"description":"Anthropic-native clients send credentials here (no Bearer prefix).","in":"header","name":"x-api-key","type":"apiKey"}},"schemas":{"CreateBudgetRequest":{"description":"Request model for creating a new budget.","properties":{"budget_duration_sec":{"anyOf":[{"exclusiveMinimum":0,"type":"integer"},{"type":"null"}],"description":"Budget duration in seconds (e.g., 86400 for daily, 604800 for weekly)","title":"Budget Duration Sec"},"max_budget":{"anyOf":[{"maximum":999999999999,"minimum":0,"type":"number"},{"type":"null"}],"description":"Maximum spending limit","title":"Max Budget"},"name":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Admin-facing label for the budget","title":"Name"},"request_limit":{"anyOf":[{"maximum":1000000000000000,"minimum":0,"type":"integer"},{"type":"null"}],"description":"Maximum requests over the period. Independent of max_budget; null is unlimited","title":"Request Limit"},"reset_alignment":{"anyOf":[{"enum":["calendar_day","calendar_week","calendar_month"],"type":"string"},{"type":"null"}],"description":"Reset on a UTC calendar boundary instead of a fixed number of seconds, which is the only way to express a calendar month. Mutually exclusive with budget_duration_sec","title":"Reset Alignment"},"rpm_limit":{"anyOf":[{"maximum":2147483647,"minimum":1,"type":"integer"},{"type":"null"}],"description":"Requests per minute for each user on this budget, across replicas; null is unlimited","title":"Rpm Limit"},"token_limit":{"anyOf":[{"maximum":1000000000000000,"minimum":0,"type":"integer"},{"type":"null"}],"description":"Maximum tokens over the period. Independent of max_budget; null is unlimited","title":"Token Limit"},"tpm_limit":{"anyOf":[{"maximum":2147483647,"minimum":1,"type":"integer"},{"type":"null"}],"description":"Tokens per minute for each user on this budget, counted on what requests used: a request is admitted while the user's minute is under the limit. Null is unlimited","title":"Tpm Limit"}},"title":"CreateBudgetRequest","type":"object"},"BudgetResponse":{"description":"Response model for budget information.\n\n``max_budget``, ``token_limit`` and ``request_limit`` are the per-user\nceilings, each independent and each unlimited when null, and multiple users\ncan share one budget, so the usage rollup is an aggregate over the users\nassigned to this budget: how many there are and their combined ``spend`` /\n``reserved``.\nAssigning users to a budget is done through the users API (dashboard support\nlands with user management), so a fresh gateway reports zeros here.","properties":{"budget_duration_sec":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Budget Duration Sec"},"budget_id":{"title":"Budget Id","type":"string"},"created_at":{"title":"Created At","type":"string"},"max_budget":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Max Budget"},"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"},"organization_id":{"anyOf":[{"format":"uuid","type":"string"},{"type":"null"}],"title":"Organization Id"},"origin":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"'config' while config.yml declares this budget, in which case a start writes the declared values back over any change made through the API when the budget's entry in config.yml changed, and once on the first start after upgrading to a version that tracks this; null otherwise","title":"Origin"},"request_limit":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Request Limit"},"reset_alignment":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Reset Alignment"},"rpm_limit":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Rpm Limit"},"token_limit":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Token Limit"},"total_reserved":{"default":0,"title":"Total Reserved","type":"number"},"total_spend":{"default":0,"title":"Total Spend","type":"number"},"tpm_limit":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Tpm Limit"},"updated_at":{"title":"Updated At","type":"string"},"user_count":{"default":0,"title":"User Count","type":"integer"}},"required":["budget_id","organization_id","name","max_budget","token_limit","request_limit","budget_duration_sec","reset_alignment","created_at","updated_at"],"title":"BudgetResponse","type":"object"},"HTTPValidationError":{"properties":{"code":{"const":"invalid_request","description":"Stable error code, also sent as the Otari-Error-Code header.","title":"Code","type":"string"},"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"title":"Detail","type":"array"}},"title":"HTTPValidationError","type":"object"},"ValidationError":{"properties":{"ctx":{"title":"Context","type":"object"},"input":{"title":"Input"},"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"title":"Location","type":"array"},"msg":{"title":"Message","type":"string"},"type":{"title":"Error Type","type":"string"}},"required":["loc","msg","type"],"title":"ValidationError","type":"object"}}},"paths":{"/api/v1/budgets":{"post":{"description":"Create a new budget.","operationId":"budgets-create_budget","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateBudgetRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BudgetResponse"}}},"description":"Successful Response"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error"}},"summary":"Create Budget","tags":["budgets"]}}}}
```

## Get Budget

> Get details of a specific budget.

```json
{"openapi":"3.1.0","info":{"title":"otari","version":"0.33.0"},"security":[{"ApiKeyAuth":[]},{"XApiKeyAuth":[]}],"components":{"securitySchemes":{"ApiKeyAuth":{"description":"Enter your API key here (sent as Otari-Key header).","in":"header","name":"Otari-Key","type":"apiKey"},"XApiKeyAuth":{"description":"Anthropic-native clients send credentials here (no Bearer prefix).","in":"header","name":"x-api-key","type":"apiKey"}},"schemas":{"BudgetResponse":{"description":"Response model for budget information.\n\n``max_budget``, ``token_limit`` and ``request_limit`` are the per-user\nceilings, each independent and each unlimited when null, and multiple users\ncan share one budget, so the usage rollup is an aggregate over the users\nassigned to this budget: how many there are and their combined ``spend`` /\n``reserved``.\nAssigning users to a budget is done through the users API (dashboard support\nlands with user management), so a fresh gateway reports zeros here.","properties":{"budget_duration_sec":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Budget Duration Sec"},"budget_id":{"title":"Budget Id","type":"string"},"created_at":{"title":"Created At","type":"string"},"max_budget":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Max Budget"},"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"},"organization_id":{"anyOf":[{"format":"uuid","type":"string"},{"type":"null"}],"title":"Organization Id"},"origin":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"'config' while config.yml declares this budget, in which case a start writes the declared values back over any change made through the API when the budget's entry in config.yml changed, and once on the first start after upgrading to a version that tracks this; null otherwise","title":"Origin"},"request_limit":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Request Limit"},"reset_alignment":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Reset Alignment"},"rpm_limit":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Rpm Limit"},"token_limit":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Token Limit"},"total_reserved":{"default":0,"title":"Total Reserved","type":"number"},"total_spend":{"default":0,"title":"Total Spend","type":"number"},"tpm_limit":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Tpm Limit"},"updated_at":{"title":"Updated At","type":"string"},"user_count":{"default":0,"title":"User Count","type":"integer"}},"required":["budget_id","organization_id","name","max_budget","token_limit","request_limit","budget_duration_sec","reset_alignment","created_at","updated_at"],"title":"BudgetResponse","type":"object"},"HTTPValidationError":{"properties":{"code":{"const":"invalid_request","description":"Stable error code, also sent as the Otari-Error-Code header.","title":"Code","type":"string"},"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"title":"Detail","type":"array"}},"title":"HTTPValidationError","type":"object"},"ValidationError":{"properties":{"ctx":{"title":"Context","type":"object"},"input":{"title":"Input"},"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"title":"Location","type":"array"},"msg":{"title":"Message","type":"string"},"type":{"title":"Error Type","type":"string"}},"required":["loc","msg","type"],"title":"ValidationError","type":"object"}}},"paths":{"/api/v1/budgets/{budget_id}":{"get":{"description":"Get details of a specific budget.","operationId":"budgets-get_budget","parameters":[{"in":"path","name":"budget_id","required":true,"schema":{"title":"Budget Id","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BudgetResponse"}}},"description":"Successful Response"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error"}},"summary":"Get Budget","tags":["budgets"]}}}}
```

## Put Budget

> Create a budget under an id you choose, or replace the one with that id.\
> \
> Every field takes the value in the body, and a field left out is cleared, so\
> the same request always leaves the same budget. Answers 201 when it created\
> the budget. Users on a budget it replaces stay on it, and its ceilings follow\
> a change of reset period. A budget an organization owns is not replaced.

```json
{"openapi":"3.1.0","info":{"title":"otari","version":"0.33.0"},"security":[{"ApiKeyAuth":[]},{"XApiKeyAuth":[]}],"components":{"securitySchemes":{"ApiKeyAuth":{"description":"Enter your API key here (sent as Otari-Key header).","in":"header","name":"Otari-Key","type":"apiKey"},"XApiKeyAuth":{"description":"Anthropic-native clients send credentials here (no Bearer prefix).","in":"header","name":"x-api-key","type":"apiKey"}},"schemas":{"CreateBudgetRequest":{"description":"Request model for creating a new budget.","properties":{"budget_duration_sec":{"anyOf":[{"exclusiveMinimum":0,"type":"integer"},{"type":"null"}],"description":"Budget duration in seconds (e.g., 86400 for daily, 604800 for weekly)","title":"Budget Duration Sec"},"max_budget":{"anyOf":[{"maximum":999999999999,"minimum":0,"type":"number"},{"type":"null"}],"description":"Maximum spending limit","title":"Max Budget"},"name":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Admin-facing label for the budget","title":"Name"},"request_limit":{"anyOf":[{"maximum":1000000000000000,"minimum":0,"type":"integer"},{"type":"null"}],"description":"Maximum requests over the period. Independent of max_budget; null is unlimited","title":"Request Limit"},"reset_alignment":{"anyOf":[{"enum":["calendar_day","calendar_week","calendar_month"],"type":"string"},{"type":"null"}],"description":"Reset on a UTC calendar boundary instead of a fixed number of seconds, which is the only way to express a calendar month. Mutually exclusive with budget_duration_sec","title":"Reset Alignment"},"rpm_limit":{"anyOf":[{"maximum":2147483647,"minimum":1,"type":"integer"},{"type":"null"}],"description":"Requests per minute for each user on this budget, across replicas; null is unlimited","title":"Rpm Limit"},"token_limit":{"anyOf":[{"maximum":1000000000000000,"minimum":0,"type":"integer"},{"type":"null"}],"description":"Maximum tokens over the period. Independent of max_budget; null is unlimited","title":"Token Limit"},"tpm_limit":{"anyOf":[{"maximum":2147483647,"minimum":1,"type":"integer"},{"type":"null"}],"description":"Tokens per minute for each user on this budget, counted on what requests used: a request is admitted while the user's minute is under the limit. Null is unlimited","title":"Tpm Limit"}},"title":"CreateBudgetRequest","type":"object"},"BudgetResponse":{"description":"Response model for budget information.\n\n``max_budget``, ``token_limit`` and ``request_limit`` are the per-user\nceilings, each independent and each unlimited when null, and multiple users\ncan share one budget, so the usage rollup is an aggregate over the users\nassigned to this budget: how many there are and their combined ``spend`` /\n``reserved``.\nAssigning users to a budget is done through the users API (dashboard support\nlands with user management), so a fresh gateway reports zeros here.","properties":{"budget_duration_sec":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Budget Duration Sec"},"budget_id":{"title":"Budget Id","type":"string"},"created_at":{"title":"Created At","type":"string"},"max_budget":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Max Budget"},"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"},"organization_id":{"anyOf":[{"format":"uuid","type":"string"},{"type":"null"}],"title":"Organization Id"},"origin":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"'config' while config.yml declares this budget, in which case a start writes the declared values back over any change made through the API when the budget's entry in config.yml changed, and once on the first start after upgrading to a version that tracks this; null otherwise","title":"Origin"},"request_limit":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Request Limit"},"reset_alignment":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Reset Alignment"},"rpm_limit":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Rpm Limit"},"token_limit":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Token Limit"},"total_reserved":{"default":0,"title":"Total Reserved","type":"number"},"total_spend":{"default":0,"title":"Total Spend","type":"number"},"tpm_limit":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Tpm Limit"},"updated_at":{"title":"Updated At","type":"string"},"user_count":{"default":0,"title":"User Count","type":"integer"}},"required":["budget_id","organization_id","name","max_budget","token_limit","request_limit","budget_duration_sec","reset_alignment","created_at","updated_at"],"title":"BudgetResponse","type":"object"},"HTTPValidationError":{"properties":{"code":{"const":"invalid_request","description":"Stable error code, also sent as the Otari-Error-Code header.","title":"Code","type":"string"},"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"title":"Detail","type":"array"}},"title":"HTTPValidationError","type":"object"},"ValidationError":{"properties":{"ctx":{"title":"Context","type":"object"},"input":{"title":"Input"},"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"title":"Location","type":"array"},"msg":{"title":"Message","type":"string"},"type":{"title":"Error Type","type":"string"}},"required":["loc","msg","type"],"title":"ValidationError","type":"object"}}},"paths":{"/api/v1/budgets/{budget_id}":{"put":{"description":"Create a budget under an id you choose, or replace the one with that id.\n\nEvery field takes the value in the body, and a field left out is cleared, so\nthe same request always leaves the same budget. Answers 201 when it created\nthe budget. Users on a budget it replaces stay on it, and its ceilings follow\na change of reset period. A budget an organization owns is not replaced.","operationId":"budgets-put_budget","parameters":[{"description":"An id you choose: up to 128 letters, digits, '.', '_' and '-', starting with a letter or digit","in":"path","name":"budget_id","required":true,"schema":{"description":"An id you choose: up to 128 letters, digits, '.', '_' and '-', starting with a letter or digit","pattern":"^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$","title":"Budget Id","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateBudgetRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BudgetResponse"}}},"description":"Successful Response"},"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BudgetResponse"}}},"description":"The budget was created"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error"}},"summary":"Put Budget","tags":["budgets"]}}}}
```

## Update Budget

> Update a budget.

```json
{"openapi":"3.1.0","info":{"title":"otari","version":"0.33.0"},"security":[{"ApiKeyAuth":[]},{"XApiKeyAuth":[]}],"components":{"securitySchemes":{"ApiKeyAuth":{"description":"Enter your API key here (sent as Otari-Key header).","in":"header","name":"Otari-Key","type":"apiKey"},"XApiKeyAuth":{"description":"Anthropic-native clients send credentials here (no Bearer prefix).","in":"header","name":"x-api-key","type":"apiKey"}},"schemas":{"UpdateBudgetRequest":{"description":"Request model for updating a budget.","properties":{"budget_duration_sec":{"anyOf":[{"exclusiveMinimum":0,"type":"integer"},{"type":"null"}],"title":"Budget Duration Sec"},"max_budget":{"anyOf":[{"maximum":999999999999,"minimum":0,"type":"number"},{"type":"null"}],"title":"Max Budget"},"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"},"request_limit":{"anyOf":[{"maximum":1000000000000000,"minimum":0,"type":"integer"},{"type":"null"}],"description":"Maximum requests over the period. Independent of max_budget; null is unlimited","title":"Request Limit"},"reset_alignment":{"anyOf":[{"enum":["calendar_day","calendar_week","calendar_month"],"type":"string"},{"type":"null"}],"title":"Reset Alignment"},"rpm_limit":{"anyOf":[{"maximum":2147483647,"minimum":1,"type":"integer"},{"type":"null"}],"description":"Requests per minute for each user on this budget, across replicas; null is unlimited","title":"Rpm Limit"},"token_limit":{"anyOf":[{"maximum":1000000000000000,"minimum":0,"type":"integer"},{"type":"null"}],"description":"Maximum tokens over the period. Independent of max_budget; null is unlimited","title":"Token Limit"},"tpm_limit":{"anyOf":[{"maximum":2147483647,"minimum":1,"type":"integer"},{"type":"null"}],"description":"Tokens per minute for each user on this budget, counted on what requests used: a request is admitted while the user's minute is under the limit. Null is unlimited","title":"Tpm Limit"}},"title":"UpdateBudgetRequest","type":"object"},"BudgetResponse":{"description":"Response model for budget information.\n\n``max_budget``, ``token_limit`` and ``request_limit`` are the per-user\nceilings, each independent and each unlimited when null, and multiple users\ncan share one budget, so the usage rollup is an aggregate over the users\nassigned to this budget: how many there are and their combined ``spend`` /\n``reserved``.\nAssigning users to a budget is done through the users API (dashboard support\nlands with user management), so a fresh gateway reports zeros here.","properties":{"budget_duration_sec":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Budget Duration Sec"},"budget_id":{"title":"Budget Id","type":"string"},"created_at":{"title":"Created At","type":"string"},"max_budget":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Max Budget"},"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"},"organization_id":{"anyOf":[{"format":"uuid","type":"string"},{"type":"null"}],"title":"Organization Id"},"origin":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"'config' while config.yml declares this budget, in which case a start writes the declared values back over any change made through the API when the budget's entry in config.yml changed, and once on the first start after upgrading to a version that tracks this; null otherwise","title":"Origin"},"request_limit":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Request Limit"},"reset_alignment":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Reset Alignment"},"rpm_limit":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Rpm Limit"},"token_limit":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Token Limit"},"total_reserved":{"default":0,"title":"Total Reserved","type":"number"},"total_spend":{"default":0,"title":"Total Spend","type":"number"},"tpm_limit":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Tpm Limit"},"updated_at":{"title":"Updated At","type":"string"},"user_count":{"default":0,"title":"User Count","type":"integer"}},"required":["budget_id","organization_id","name","max_budget","token_limit","request_limit","budget_duration_sec","reset_alignment","created_at","updated_at"],"title":"BudgetResponse","type":"object"},"HTTPValidationError":{"properties":{"code":{"const":"invalid_request","description":"Stable error code, also sent as the Otari-Error-Code header.","title":"Code","type":"string"},"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"title":"Detail","type":"array"}},"title":"HTTPValidationError","type":"object"},"ValidationError":{"properties":{"ctx":{"title":"Context","type":"object"},"input":{"title":"Input"},"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"title":"Location","type":"array"},"msg":{"title":"Message","type":"string"},"type":{"title":"Error Type","type":"string"}},"required":["loc","msg","type"],"title":"ValidationError","type":"object"}}},"paths":{"/api/v1/budgets/{budget_id}":{"patch":{"description":"Update a budget.","operationId":"budgets-update_budget","parameters":[{"in":"path","name":"budget_id","required":true,"schema":{"title":"Budget Id","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateBudgetRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BudgetResponse"}}},"description":"Successful Response"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error"}},"summary":"Update Budget","tags":["budgets"]}}}}
```

## Delete Budget

> Delete a budget the deployment owns.\
> \
> Refused with 409 for an organization's budget: the operator may edit one\
> (\`\`PATCH\`\` retimes its ceilings) but deleting it would take a budget the\
> tenant defined out from under them.\
> \
> Refused with 409, too, while anything still names this budget: a workspace\
> handing it to its members, or a scoped ceiling enforcing it. The refusal says\
> which, and where.\
> \
> Gateway users assigned to the budget are left uncapped, as the dashboard's\
> confirmation says, its reset history is deleted with it, and it is taken off\
> every service key's \`\`end\_user\_budget\_ids\`\`. A budget that is a key's\
> \`\`end\_user\_budget\_id\`\` is refused (409) until that key's default changes.

```json
{"openapi":"3.1.0","info":{"title":"otari","version":"0.33.0"},"security":[{"ApiKeyAuth":[]},{"XApiKeyAuth":[]}],"components":{"securitySchemes":{"ApiKeyAuth":{"description":"Enter your API key here (sent as Otari-Key header).","in":"header","name":"Otari-Key","type":"apiKey"},"XApiKeyAuth":{"description":"Anthropic-native clients send credentials here (no Bearer prefix).","in":"header","name":"x-api-key","type":"apiKey"}},"schemas":{"HTTPValidationError":{"properties":{"code":{"const":"invalid_request","description":"Stable error code, also sent as the Otari-Error-Code header.","title":"Code","type":"string"},"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"title":"Detail","type":"array"}},"title":"HTTPValidationError","type":"object"},"ValidationError":{"properties":{"ctx":{"title":"Context","type":"object"},"input":{"title":"Input"},"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"title":"Location","type":"array"},"msg":{"title":"Message","type":"string"},"type":{"title":"Error Type","type":"string"}},"required":["loc","msg","type"],"title":"ValidationError","type":"object"}}},"paths":{"/api/v1/budgets/{budget_id}":{"delete":{"description":"Delete a budget the deployment owns.\n\nRefused with 409 for an organization's budget: the operator may edit one\n(``PATCH`` retimes its ceilings) but deleting it would take a budget the\ntenant defined out from under them.\n\nRefused with 409, too, while anything still names this budget: a workspace\nhanding it to its members, or a scoped ceiling enforcing it. The refusal says\nwhich, and where.\n\nGateway users assigned to the budget are left uncapped, as the dashboard's\nconfirmation says, its reset history is deleted with it, and it is taken off\nevery service key's ``end_user_budget_ids``. A budget that is a key's\n``end_user_budget_id`` is refused (409) until that key's default changes.","operationId":"budgets-delete_budget","parameters":[{"in":"path","name":"budget_id","required":true,"schema":{"title":"Budget Id","type":"string"}}],"responses":{"204":{"description":"Successful Response"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error"}},"summary":"Delete Budget","tags":["budgets"]}}}}
```

## List Budget Reset Logs

> List per-user reset events for a budget, newest first.

```json
{"openapi":"3.1.0","info":{"title":"otari","version":"0.33.0"},"security":[{"ApiKeyAuth":[]},{"XApiKeyAuth":[]}],"components":{"securitySchemes":{"ApiKeyAuth":{"description":"Enter your API key here (sent as Otari-Key header).","in":"header","name":"Otari-Key","type":"apiKey"},"XApiKeyAuth":{"description":"Anthropic-native clients send credentials here (no Bearer prefix).","in":"header","name":"x-api-key","type":"apiKey"}},"schemas":{"BudgetResetLogResponse":{"description":"Response model for one budget reset event (per user).","properties":{"budget_id":{"title":"Budget Id","type":"string"},"id":{"title":"Id","type":"integer"},"next_reset_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Next Reset At"},"previous_spend":{"title":"Previous Spend","type":"number"},"reset_at":{"title":"Reset At","type":"string"},"user_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"User Id"}},"required":["id","user_id","budget_id","previous_spend","reset_at","next_reset_at"],"title":"BudgetResetLogResponse","type":"object"},"HTTPValidationError":{"properties":{"code":{"const":"invalid_request","description":"Stable error code, also sent as the Otari-Error-Code header.","title":"Code","type":"string"},"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"title":"Detail","type":"array"}},"title":"HTTPValidationError","type":"object"},"ValidationError":{"properties":{"ctx":{"title":"Context","type":"object"},"input":{"title":"Input"},"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"title":"Location","type":"array"},"msg":{"title":"Message","type":"string"},"type":{"title":"Error Type","type":"string"}},"required":["loc","msg","type"],"title":"ValidationError","type":"object"}}},"paths":{"/api/v1/budgets/{budget_id}/reset-logs":{"get":{"description":"List per-user reset events for a budget, newest first.","operationId":"budgets-list_budget_reset_logs","parameters":[{"in":"path","name":"budget_id","required":true,"schema":{"title":"Budget Id","type":"string"}},{"in":"query","name":"skip","required":false,"schema":{"default":0,"minimum":0,"title":"Skip","type":"integer"}},{"in":"query","name":"limit","required":false,"schema":{"default":100,"maximum":1000,"minimum":1,"title":"Limit","type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/BudgetResetLogResponse"},"title":"Response Budgets-List Budget Reset Logs","type":"array"}}},"description":"Successful Response"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error"}},"summary":"List Budget Reset Logs","tags":["budgets"]}}}}
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.otari.ai/api-reference/budgets.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
