> 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/end-users.md).

# End users

## List End User Budgets

> List the budgets the calling service key may put its end users on, with how many end users each holds.\
> \
> Requires a service key. The counts cover the end users of the key's user, blocked ones included and deleted\
> ones not.

```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":{"EndUserBudgetPublic":{"description":"A budget a service key may put its end users on, and how many of them are on it.","properties":{"blocked_end_user_count":{"title":"Blocked End User Count","type":"integer"},"budget_id":{"title":"Budget Id","type":"string"},"end_user_count":{"description":"End users of the key's user on this budget, blocked ones included","title":"End User Count","type":"integer"},"is_default":{"description":"Whether a new end user starts here when its request names no budget","title":"Is Default","type":"boolean"}},"required":["budget_id","is_default","end_user_count","blocked_end_user_count"],"title":"EndUserBudgetPublic","type":"object"}}},"paths":{"/api/v1/end-user-budgets":{"get":{"description":"List the budgets the calling service key may put its end users on, with how many end users each holds.\n\nRequires a service key. The counts cover the end users of the key's user, blocked ones included and deleted\nones not.","operationId":"end-users-list_end_user_budgets","responses":{"200":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/EndUserBudgetPublic"},"title":"Response End-Users-List End User Budgets","type":"array"}}},"description":"Successful Response"}},"summary":"List End User Budgets","tags":["end-users"]}}}}
```

## List End Users

> List the end users of the calling service key, oldest first.\
> \
> Requires a service key. End users belong to the key's user, so every service key of one user lists the same\
> end users. A deleted end user is not listed. \`\`external\_id\`\` reads one end user by any id, one containing '/'\
> included, as a list of zero or one.

```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":{"EndUserPublic":{"description":"An end user of a service key, addressed by the id the service named it by.","properties":{"blocked":{"title":"Blocked","type":"boolean"},"budget_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Budget Id"},"budget_started_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Budget Started At"},"created_at":{"title":"Created At","type":"string"},"current_requests":{"title":"Current Requests","type":"integer"},"current_tokens":{"title":"Current Tokens","type":"integer"},"external_id":{"title":"External Id","type":"string"},"next_budget_reset_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Next Budget Reset At"},"owner_user_id":{"title":"Owner User Id","type":"string"},"reserved":{"title":"Reserved","type":"number"},"spend":{"title":"Spend","type":"number"},"user_id":{"title":"User Id","type":"string"}},"required":["user_id","external_id","owner_user_id","budget_id","blocked","spend","reserved","current_tokens","current_requests","budget_started_at","next_budget_reset_at","created_at"],"title":"EndUserPublic","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/end-users":{"get":{"description":"List the end users of the calling service key, oldest first.\n\nRequires a service key. End users belong to the key's user, so every service key of one user lists the same\nend users. A deleted end user is not listed. ``external_id`` reads one end user by any id, one containing '/'\nincluded, as a list of zero or one.","operationId":"end-users-list_end_users","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"}},{"description":"Only end users on this budget.","in":"query","name":"budget_id","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Only end users on this budget.","title":"Budget Id"}},{"description":"Only end users that are, or are not, blocked.","in":"query","name":"blocked","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"description":"Only end users that are, or are not, blocked.","title":"Blocked"}},{"description":"Only the end user the service names with this `user` value: zero or one.","in":"query","name":"external_id","required":false,"schema":{"anyOf":[{"minLength":1,"type":"string"},{"type":"null"}],"description":"Only the end user the service names with this `user` value: zero or one.","title":"External Id"}},{"description":"Also count every matching end user, in the Otari-Total-Count response header.","in":"query","name":"include_total","required":false,"schema":{"default":false,"description":"Also count every matching end user, in the Otari-Total-Count response header.","title":"Include Total","type":"boolean"}}],"responses":{"200":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/EndUserPublic"},"title":"Response End-Users-List End Users","type":"array"}}},"description":"Successful Response"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error"}},"summary":"List End Users","tags":["end-users"]}}}}
```

## Put End User By Query

> Put the end user named by \`\`external\_id\`\` on a budget from the key's list, creating it if needed.\
> \
> The same as \`\`PUT /end-users/{external\_id}\`\`, for any id, one containing '/' included.

```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":{"EndUserPut":{"description":"Create an end user ahead of its first request, or move one, onto a budget on the key's list.","properties":{"budget_id":{"description":"A budget on the key's end_user_budget_ids","minLength":1,"title":"Budget Id","type":"string"}},"required":["budget_id"],"title":"EndUserPut","type":"object"},"EndUserPublic":{"description":"An end user of a service key, addressed by the id the service named it by.","properties":{"blocked":{"title":"Blocked","type":"boolean"},"budget_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Budget Id"},"budget_started_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Budget Started At"},"created_at":{"title":"Created At","type":"string"},"current_requests":{"title":"Current Requests","type":"integer"},"current_tokens":{"title":"Current Tokens","type":"integer"},"external_id":{"title":"External Id","type":"string"},"next_budget_reset_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Next Budget Reset At"},"owner_user_id":{"title":"Owner User Id","type":"string"},"reserved":{"title":"Reserved","type":"number"},"spend":{"title":"Spend","type":"number"},"user_id":{"title":"User Id","type":"string"}},"required":["user_id","external_id","owner_user_id","budget_id","blocked","spend","reserved","current_tokens","current_requests","budget_started_at","next_budget_reset_at","created_at"],"title":"EndUserPublic","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/end-users":{"put":{"description":"Put the end user named by ``external_id`` on a budget from the key's list, creating it if needed.\n\nThe same as ``PUT /end-users/{external_id}``, for any id, one containing '/' included.","operationId":"end-users-put_end_user_by_query","parameters":[{"description":"The id the service names the end user by in a request's user field, any id, '/' included","in":"query","name":"external_id","required":true,"schema":{"description":"The id the service names the end user by in a request's user field, any id, '/' included","minLength":1,"title":"External Id","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EndUserPut"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EndUserPublic"}}},"description":"Successful Response"},"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EndUserPublic"}}},"description":"The end user was created"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error"}},"summary":"Put End User By Query","tags":["end-users"]}}}}
```

## Update End User By Query

> Block, unblock or move the end user named by \`\`external\_id\`\`.\
> \
> The same as \`\`PATCH /end-users/{external\_id}\`\`, for any id, one containing '/' included.

```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":{"EndUserUpdate":{"description":"Block, unblock or move an end user. An omitted field is left as it is.","properties":{"blocked":{"anyOf":[{"type":"boolean"},{"type":"null"}],"description":"Whether the end user is refused","title":"Blocked"},"budget_id":{"anyOf":[{"minLength":1,"type":"string"},{"type":"null"}],"description":"A budget on the key's end_user_budget_ids to move the end user to","title":"Budget Id"}},"title":"EndUserUpdate","type":"object"},"EndUserPublic":{"description":"An end user of a service key, addressed by the id the service named it by.","properties":{"blocked":{"title":"Blocked","type":"boolean"},"budget_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Budget Id"},"budget_started_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Budget Started At"},"created_at":{"title":"Created At","type":"string"},"current_requests":{"title":"Current Requests","type":"integer"},"current_tokens":{"title":"Current Tokens","type":"integer"},"external_id":{"title":"External Id","type":"string"},"next_budget_reset_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Next Budget Reset At"},"owner_user_id":{"title":"Owner User Id","type":"string"},"reserved":{"title":"Reserved","type":"number"},"spend":{"title":"Spend","type":"number"},"user_id":{"title":"User Id","type":"string"}},"required":["user_id","external_id","owner_user_id","budget_id","blocked","spend","reserved","current_tokens","current_requests","budget_started_at","next_budget_reset_at","created_at"],"title":"EndUserPublic","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/end-users":{"patch":{"description":"Block, unblock or move the end user named by ``external_id``.\n\nThe same as ``PATCH /end-users/{external_id}``, for any id, one containing '/' included.","operationId":"end-users-update_end_user_by_query","parameters":[{"description":"The id the service names the end user by in a request's user field, any id, '/' included","in":"query","name":"external_id","required":true,"schema":{"description":"The id the service names the end user by in a request's user field, any id, '/' included","minLength":1,"title":"External Id","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EndUserUpdate"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EndUserPublic"}}},"description":"Successful Response"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error"}},"summary":"Update End User By Query","tags":["end-users"]}}}}
```

## Delete End Users

> Delete one end user of the calling service key, or a page of those created before a time.\
> \
> Requires a service key, and exactly one of \`\`external\_id\`\` and \`\`created\_before\`\`. \`\`external\_id\`\` deletes that\
> end user, any id, one containing '/' included, and answers 404 when it has none. \`\`created\_before\`\` deletes up\
> to \`\`limit\`\` of the oldest end users created before then; call again until \`\`deleted\`\` is 0. An end user's\
> telemetry and agent traces are erased with it. The end user's row and spend are kept: a request naming it again\
> revives it with what it had spent, so deleting one cannot clear its budget. A deleted end user is neither listed\
> nor counted.

```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":{"EndUsersDeleted":{"description":"How many end users a delete removed.","properties":{"deleted":{"description":"End users deleted by this call. A page as full as the limit may leave more.","title":"Deleted","type":"integer"}},"required":["deleted"],"title":"EndUsersDeleted","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/end-users":{"delete":{"description":"Delete one end user of the calling service key, or a page of those created before a time.\n\nRequires a service key, and exactly one of ``external_id`` and ``created_before``. ``external_id`` deletes that\nend user, any id, one containing '/' included, and answers 404 when it has none. ``created_before`` deletes up\nto ``limit`` of the oldest end users created before then; call again until ``deleted`` is 0. An end user's\ntelemetry and agent traces are erased with it. The end user's row and spend are kept: a request naming it again\nrevives it with what it had spent, so deleting one cannot clear its budget. A deleted end user is neither listed\nnor counted.","operationId":"end-users-delete_end_users","parameters":[{"description":"Delete the end user the service names with this `user` value.","in":"query","name":"external_id","required":false,"schema":{"anyOf":[{"minLength":1,"type":"string"},{"type":"null"}],"description":"Delete the end user the service names with this `user` value.","title":"External Id"}},{"description":"Delete the end users created before this time, oldest first, up to `limit` of them.","in":"query","name":"created_before","required":false,"schema":{"anyOf":[{"format":"date-time","type":"string"},{"type":"null"}],"description":"Delete the end users created before this time, oldest first, up to `limit` of them.","title":"Created Before"}},{"description":"The most end users one call deletes with `created_before`.","in":"query","name":"limit","required":false,"schema":{"default":100,"description":"The most end users one call deletes with `created_before`.","maximum":1000,"minimum":1,"title":"Limit","type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EndUsersDeleted"}}},"description":"Successful Response"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error"}},"summary":"Delete End Users","tags":["end-users"]}}}}
```

## Get End User

> Get an end user of the calling service key by the id the service names it by.\
> \
> Requires a service key. An id no end user of the key's user goes by answers 404. An id with a '.' or '..'\
> segment is refused with 400; \`\`GET /end-users?external\_id=\`\` reads any end user.

```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":{"EndUserPublic":{"description":"An end user of a service key, addressed by the id the service named it by.","properties":{"blocked":{"title":"Blocked","type":"boolean"},"budget_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Budget Id"},"budget_started_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Budget Started At"},"created_at":{"title":"Created At","type":"string"},"current_requests":{"title":"Current Requests","type":"integer"},"current_tokens":{"title":"Current Tokens","type":"integer"},"external_id":{"title":"External Id","type":"string"},"next_budget_reset_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Next Budget Reset At"},"owner_user_id":{"title":"Owner User Id","type":"string"},"reserved":{"title":"Reserved","type":"number"},"spend":{"title":"Spend","type":"number"},"user_id":{"title":"User Id","type":"string"}},"required":["user_id","external_id","owner_user_id","budget_id","blocked","spend","reserved","current_tokens","current_requests","budget_started_at","next_budget_reset_at","created_at"],"title":"EndUserPublic","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/end-users/{external_id}":{"get":{"description":"Get an end user of the calling service key by the id the service names it by.\n\nRequires a service key. An id no end user of the key's user goes by answers 404. An id with a '.' or '..'\nsegment is refused with 400; ``GET /end-users?external_id=`` reads any end user.","operationId":"end-users-get_end_user","parameters":[{"description":"The id the service names the end user by in a request's user field","in":"path","name":"external_id","required":true,"schema":{"description":"The id the service names the end user by in a request's user field","title":"External Id","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EndUserPublic"}}},"description":"Successful Response"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error"}},"summary":"Get End User","tags":["end-users"]}}}}
```

## Put End User

> Put an end user of the calling service key on a budget from the key's list, creating it if needed.\
> \
> Requires a service key. Answers 201 when the end user was created. An end user already on the budget keeps its\
> current period, so repeating the call changes nothing. A budget that is not on the key's \`\`end\_user\_budget\_ids\`\`\
> is refused with 403 and \`\`end\_user\_budget\_not\_allowed\`\`. An id with a '.' or '..' segment is refused with 400;\
> \`\`PUT /end-users?external\_id=\`\` takes any id.

```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":{"EndUserPut":{"description":"Create an end user ahead of its first request, or move one, onto a budget on the key's list.","properties":{"budget_id":{"description":"A budget on the key's end_user_budget_ids","minLength":1,"title":"Budget Id","type":"string"}},"required":["budget_id"],"title":"EndUserPut","type":"object"},"EndUserPublic":{"description":"An end user of a service key, addressed by the id the service named it by.","properties":{"blocked":{"title":"Blocked","type":"boolean"},"budget_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Budget Id"},"budget_started_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Budget Started At"},"created_at":{"title":"Created At","type":"string"},"current_requests":{"title":"Current Requests","type":"integer"},"current_tokens":{"title":"Current Tokens","type":"integer"},"external_id":{"title":"External Id","type":"string"},"next_budget_reset_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Next Budget Reset At"},"owner_user_id":{"title":"Owner User Id","type":"string"},"reserved":{"title":"Reserved","type":"number"},"spend":{"title":"Spend","type":"number"},"user_id":{"title":"User Id","type":"string"}},"required":["user_id","external_id","owner_user_id","budget_id","blocked","spend","reserved","current_tokens","current_requests","budget_started_at","next_budget_reset_at","created_at"],"title":"EndUserPublic","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/end-users/{external_id}":{"put":{"description":"Put an end user of the calling service key on a budget from the key's list, creating it if needed.\n\nRequires a service key. Answers 201 when the end user was created. An end user already on the budget keeps its\ncurrent period, so repeating the call changes nothing. A budget that is not on the key's ``end_user_budget_ids``\nis refused with 403 and ``end_user_budget_not_allowed``. An id with a '.' or '..' segment is refused with 400;\n``PUT /end-users?external_id=`` takes any id.","operationId":"end-users-put_end_user","parameters":[{"description":"The id the service names the end user by in a request's user field","in":"path","name":"external_id","required":true,"schema":{"description":"The id the service names the end user by in a request's user field","title":"External Id","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EndUserPut"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EndUserPublic"}}},"description":"Successful Response"},"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EndUserPublic"}}},"description":"The end user was created"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error"}},"summary":"Put End User","tags":["end-users"]}}}}
```

## Update End User

> Block, unblock or move an end user of the calling service key.\
> \
> Requires a service key. A move restarts the end user's period on the new budget but keeps what it has spent and\
> used so far. The budget must be on the key's \`\`end\_user\_budget\_ids\`\`, or the move is refused with 403 and\
> \`\`end\_user\_budget\_not\_allowed\`\`. An id with a '.' or '..' segment is refused with 400;\
> \`\`PATCH /end-users?external\_id=\`\` takes any id.

```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":{"EndUserUpdate":{"description":"Block, unblock or move an end user. An omitted field is left as it is.","properties":{"blocked":{"anyOf":[{"type":"boolean"},{"type":"null"}],"description":"Whether the end user is refused","title":"Blocked"},"budget_id":{"anyOf":[{"minLength":1,"type":"string"},{"type":"null"}],"description":"A budget on the key's end_user_budget_ids to move the end user to","title":"Budget Id"}},"title":"EndUserUpdate","type":"object"},"EndUserPublic":{"description":"An end user of a service key, addressed by the id the service named it by.","properties":{"blocked":{"title":"Blocked","type":"boolean"},"budget_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Budget Id"},"budget_started_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Budget Started At"},"created_at":{"title":"Created At","type":"string"},"current_requests":{"title":"Current Requests","type":"integer"},"current_tokens":{"title":"Current Tokens","type":"integer"},"external_id":{"title":"External Id","type":"string"},"next_budget_reset_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Next Budget Reset At"},"owner_user_id":{"title":"Owner User Id","type":"string"},"reserved":{"title":"Reserved","type":"number"},"spend":{"title":"Spend","type":"number"},"user_id":{"title":"User Id","type":"string"}},"required":["user_id","external_id","owner_user_id","budget_id","blocked","spend","reserved","current_tokens","current_requests","budget_started_at","next_budget_reset_at","created_at"],"title":"EndUserPublic","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/end-users/{external_id}":{"patch":{"description":"Block, unblock or move an end user of the calling service key.\n\nRequires a service key. A move restarts the end user's period on the new budget but keeps what it has spent and\nused so far. The budget must be on the key's ``end_user_budget_ids``, or the move is refused with 403 and\n``end_user_budget_not_allowed``. An id with a '.' or '..' segment is refused with 400;\n``PATCH /end-users?external_id=`` takes any id.","operationId":"end-users-update_end_user","parameters":[{"description":"The id the service names the end user by in a request's user field","in":"path","name":"external_id","required":true,"schema":{"description":"The id the service names the end user by in a request's user field","title":"External Id","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EndUserUpdate"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EndUserPublic"}}},"description":"Successful Response"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error"}},"summary":"Update End User","tags":["end-users"]}}}}
```

## Delete End User

> Delete an end user of the calling service key by the id the service names it by.\
> \
> Requires a service key. An id no live end user of the key's user goes by answers 404. The end user's telemetry\
> and agent traces are erased; its row and spend are kept, so a request naming it again revives it with what it had\
> spent. An id with a '.' or '..' segment is refused with 400; \`\`DELETE /end-users?external\_id=\`\` takes any id.

```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/end-users/{external_id}":{"delete":{"description":"Delete an end user of the calling service key by the id the service names it by.\n\nRequires a service key. An id no live end user of the key's user goes by answers 404. The end user's telemetry\nand agent traces are erased; its row and spend are kept, so a request naming it again revives it with what it had\nspent. An id with a '.' or '..' segment is refused with 400; ``DELETE /end-users?external_id=`` takes any id.","operationId":"end-users-delete_end_user","parameters":[{"description":"The id the service names the end user by in a request's user field","in":"path","name":"external_id","required":true,"schema":{"description":"The id the service names the end user by in a request's user field","title":"External Id","type":"string"}}],"responses":{"204":{"description":"Successful Response"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error"}},"summary":"Delete End User","tags":["end-users"]}}}}
```


---

# 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/end-users.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.
