LLM API
Authentication
The LLM API authenticates with a project-scoped inference key, sent as a bearer token.
Create a key
Inference keys are created in the Console under Inference API → Keys, scoped to a project. The full secret is shown only once at creation, so copy it immediately and store it in a secret manager. See Inference keys for the full lifecycle (rotation, revocation, archiving).
Treat keys like passwords
A key carries the permissions of its project. Never commit one to source control or expose it in client-side code. If a key leaks, revoke it in the Console and issue a new one.Send the key
Pass the key in the Authorization header as a bearer token. The SDKs do this for you when you set api_key.
Authorization: Bearer $UPGREAT_API_KEYKeep the key in an environment variable rather than inline:
export UPGREAT_API_KEY="sk-..."
curl https://llm.upgreat.ai/v1/models \
-H "Authorization: Bearer $UPGREAT_API_KEY"Errors
A missing, malformed or revoked key returns 401 Unauthorized with an OpenAI-style error envelope:
{
"error": {
"message": "invalid token",
"type": "authentication_error",
"code": "invalid_token"
}
}A 400 indicates the request body failed validation (for example a missing model or messages field). The error.message names the offending field.
A 403 with code model_not_allowed means the model is not available to this key: either the key's own model list excludes it, or your organization does not have access to it. The Console lists the models your organization can use.
Rate limits and capacity
A 429 Too Many Requests carries a Retry-After header (seconds) and one of these codes:
rate_limit_exceeded,token_rate_limit_exceeded— the requests or tokens per minute allowed for the key, or for your organization across all its keys.token_quota_exceeded— the token quota of the key or the organization for the current period is used up.model_overloaded— the model is at capacity. Requests above capacity wait briefly in a queue shared fairly between organizations; this code means no slot became free in time.
{
"error": {
"message": "deepseek-v4.1-flash is at capacity, retry shortly",
"type": "rate_limit_error",
"code": "model_overloaded"
}
}Retrying
Wait the number of seconds inRetry-After, then retry with exponential backoff and a little jitter. For large batch jobs, cap your own concurrency rather than sending everything at once: requests are served faster and you avoid model_overloaded.