Service Accounts
Use this if you want to create Virtual Keys that are not owned by a specific user but instead created for production projects
Why use a service account key?
- Prevent key from being deleted when user is deleted.
- Apply team limits, not team member limits to key.
Service Account vs Regular Keys
| Feature | Regular Key | Service Account Key |
|---|---|---|
user_id | Optional | Always null |
team_id | Optional | Required |
| Applied limits | User + Team limits | Team limits only |
| Key deleted when user is deleted? | Yes | No — persists |
service_account_id in metadata | Not set | Immutable once set |
team_member_key_duration | Inherits | Does not inherit |
Budgets & Limits
Service account keys apply budgets and rate limits at the team level — not per user or per key member.
- Set
max_budget,tpm_limit,rpm_limiton the key itself, or inherit them from the team. team_member_key_duration(an enterprise feature that controls how long team-member keys last) does not apply to service account keys.
Usage
Use the /key/service-account/generate endpoint to generate a service account key.
curl -L -X POST 'http://localhost:4000/key/service-account/generate' \
-H 'Authorization: Bearer sk-1234' \
-H 'Content-Type: application/json' \
-d '{
"team_id": "my-unique-team"
}'
service_account_id field
You can optionally provide a service_account_id inside metadata to give the key a stable, human-readable identifier:
curl -L -X POST 'http://localhost:4000/key/service-account/generate' \
-H 'Authorization: Bearer sk-1234' \
-H 'Content-Type: application/json' \
-d '{
"team_id": "my-unique-team",
"metadata": {
"service_account_id": "my-ci-pipeline"
}
}'
Immutability rules — once service_account_id is set, it cannot be changed:
| Operation | Result |
|---|---|
| Overwrite with a different value | 400 error |
Set to null explicitly | 400 error |
Send metadata: null (would clear it) | 400 error |
Omit metadata entirely on update | Safe — existing value is preserved |
| Resend the same value | Allowed (no-op) |
Example - require user param for all service account requests
1. Set settings for Service Accounts
Set service_account_settings if you want to create settings that only apply to service account keys
general_settings:
service_account_settings:
enforced_params: ["user"] # this means the "user" param is enforced for all requests made through any service account keys
2. Create Service Account Key on LiteLLM Proxy Admin UI
3. Test Service Account Key
- Unsuccessful call
- Successful call
curl --location 'http://localhost:4000/chat/completions' \
--header 'Authorization: Bearer <sk-your-service-account>' \
--header 'Content-Type: application/json' \
--data '{
"model": "gpt-3.5-turbo",
"messages": [
{
"role": "user",
"content": "hello"
}
]
}'
Expected Response
{
"error": {
"message": "BadRequest please pass param=user in request body. This is a required param for service account",
"type": "bad_request_error",
"param": "user",
"code": "400"
}
}
curl --location 'http://localhost:4000/chat/completions' \
--header 'Authorization: Bearer <sk-your-service-account>' \
--header 'Content-Type: application/json' \
--data '{
"model": "gpt-3.5-turbo",
"messages": [
{
"role": "user",
"content": "hello"
}
],
"user": "test-user"
}'
Expected Response
{
"id": "chatcmpl-ad9595c7e3784a6783b469218d92d95c",
"choices": [
{
"finish_reason": "stop",
"index": 0,
"message": {
"content": "\n\nHello there, how may I assist you today?",
"role": "assistant",
"tool_calls": null,
"function_call": null
}
}
],
"created": 1677652288,
"model": "gpt-3.5-turbo-0125",
"object": "chat.completion",
"system_fingerprint": "fp_44709d6fcb",
"usage": {
"completion_tokens": 12,
"prompt_tokens": 9,
"total_tokens": 21,
"completion_tokens_details": null
},
"service_tier": null
}