API reference
Estro speaks the OpenAI chat-completions dialect. Point any client, SDK, or IDE extension at it by changing the base URL and key.
Estro is available on your favorite platforms:
Pick a platform above to see its setup.
Authentication
Sign in to get a session token. Pass it as Authorization: Bearer <token> or X-Api-Key. Tokens last 30 days and can be revoked from your account page.
curl https://estro.help/api/auth/login \
-H "Content-Type: application/json" \
-d '{"username":"you","password":"yourpassword"}'
# Response:
# {"token":"eyJ...","user":{"id":1,"username":"you",...}}Models
GET /v1/models returns this list live.
| Model ID | Name | Best for |
|---|---|---|
kali-gamma | Kali Gamma | Deep reasoning, multi-step work, large codebases |
kali-beta | Kali Beta | Everyday coding, writing, extended context |
kali-epsilon | Kali Epsilon | Fast iteration, quick answers |
Chat completions
POST /v1/chat/completions takes the standard OpenAI request shape. Set stream: true for server-sent events.
curl -N https://estro.help/v1/chat/completions \
-H "Authorization: Bearer $ESTRO_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"model": "kali-gamma",
"stream": true,
"messages": [
{"role": "user", "content": "Refactor this function and explain the tradeoffs."}
]
}'Reasoning / chain-of-thought
When a model thinks before answering, stream chunks include reasoning_content deltas before the answer content. The chat UI renders these as a collapsible "Thought process" block.
# Reasoning deltas appear as "reasoning_content" in each chunk's delta.
# The full response includes a collapsible thought process.
curl -N https://estro.help/v1/chat/completions \
-H "Authorization: Bearer $ESTRO_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"model": "kali-beta",
"stream": true,
"messages": [{"role": "user", "content": "Prove that sqrt(2) is irrational."}]
}'
# Stream events include:
# {"choices":[{"delta":{"reasoning_content":"Let me think..."}}]}
# {"choices":[{"delta":{"content":"Here is the proof..."}}]}Request format
| Field | Type | Required | Description |
|---|---|---|---|
model | string | yes | kali-gamma, kali-beta, or kali-epsilon |
messages | array | yes | Array of {role, content} objects. Roles: system, user, assistant |
stream | boolean | no | Default false. When true, response is SSE with data: lines |
temperature | number | no | Sampling temperature, 0 to 2. Passed through to the model |
max_tokens | integer | no | Maximum tokens in the response |
top_p | number | no | Nucleus sampling threshold |
stop | string | array | no | Stop sequences |
Response format
Non-streaming responses return standard chat.completion JSON:
{
"id": "chatcmpl-abc123",
"object": "chat.completion",
"model": "kali-gamma",
"choices": [{
"index": 0,
"message": {
"role": "assistant",
"content": "Here is the refactored function...",
"reasoning_content": "Let me analyze the code..."
},
"finish_reason": "stop"
}],
"usage": {
"prompt_tokens": 42,
"completion_tokens": 128,
"total_tokens": 170
}
}Errors & limits
| Status | Code | Meaning |
|---|---|---|
400 | bad_request | Malformed JSON or empty messages |
401 | none | Missing or expired session token |
403 | email_unverified | Verify your email address first |
403 | banned | Account suspended by admin |
402 | billing_error | No active plan. The API and Kali Gamma and Beta need one; see pricing |
404 | model_not_found | Unknown model id |
429 | rate_limit_exceeded | Daily request cap reached (resets at midnight UTC) |
429 | usage_limit_reached | A 5-hour or weekly window is full; resets_in and Retry-After say when |
502 | none | The model provider is unavailable |
Error bodies follow the OpenAI shape: {"error":{"message":"...","type":"invalid_request_error","code":"..."}}
All endpoints
Chat & models
| Method | Path | Auth | Description |
|---|---|---|---|
POST | /v1/chat/completions | required | Chat completion (stream or JSON) |
GET | /v1/models | no | List available models |
GET | /api/models | no | Models with availability status |
GET | /api/usage | required | Your daily usage + limit |
Keys
Create a long-lived key from your account page or with these calls. A key works anywhere a session token does.
| Method | Path | Auth | Description |
|---|---|---|---|
POST | /api/auth/login | no | Sign in, returns a session token |
GET | /api/account/api-keys | required | List your keys (prefix only) |
POST | /api/account/api-keys | required | Create a key; the secret is returned once |
DELETE | /api/account/api-keys/:id | required | Revoke a key |
Rate limits
Model endpoints allow 120 requests a minute per account with a burst of 120, which is plenty for agent loops that fire many calls in sequence. Sign-in and password endpoints allow 10 a minute per IP. Over the limit you get 429 with a Retry-After header; the daily request cap is separate and resets at midnight UTC.