API Reference
Authentication
All endpoints require a valid JWT in the Authorization header:
Authorization: Bearer <token>Tokens are issued by ShellApps OAuth and verified by the auth middleware.
POST /api/chat
Streaming and non-streaming chat completions.
Request Body
{
"messages": [
{ "role": "system", "content": "You are a helpful assistant." },
{ "role": "user", "content": "Hello!" }
],
"model": "gpt-4o",
"temperature": 0.7,
"maxTokens": 4096,
"stream": true
}| Field | Type | Required | Default | Description |
|---|---|---|---|---|
messages | Array<{role, content}> | Yes | — | Chat messages. Roles: system, user, assistant |
model | string | No | gpt-4o | Model identifier |
temperature | number | No | — | Sampling temperature (0-2) |
maxTokens | number | No | — | Maximum tokens in response |
stream | boolean | No | false | Enable SSE streaming |
Response (Non-Streaming)
{
"content": "Hello! How can I help you today?",
"model": "gpt-4o",
"usage": {
"promptTokens": 25,
"completionTokens": 10
},
"requestId": "550e8400-e29b-41d4-a716-446655440000"
}Response (Streaming)
SSE events:
data: {"content": "Hello"}
data: {"content": "!"}
data: {"content": " How"}
data: {"usage": {"promptTokens": 25, "completionTokens": 10}}
data: [DONE]POST /api/complete
Non-streaming chat completions only. Same request/response format as /api/chat without the stream field.
GET /api/models
List available models for the current provider.
Response
{
"models": [
{ "id": "gpt-4o", "name": "GPT-4o" },
{ "id": "gpt-4o-mini", "name": "GPT-4o Mini" }
],
"provider": "openai"
}GET /api/usage
Per-user token usage statistics.
Query Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
days | number | 30 | Days to look back (1-90) |
Response
{
"success": true,
"data": {
"totalPromptTokens": 150000,
"totalCompletionTokens": 50000,
"totalRequests": 250,
"byModel": {
"gpt-4o": { "promptTokens": 100000, "completionTokens": 35000, "requests": 150 },
"gpt-4o-mini": { "promptTokens": 50000, "completionTokens": 15000, "requests": 100 }
},
"byDay": [
{ "date": "2026-02-20", "promptTokens": 5000, "completionTokens": 2000, "requests": 10 }
]
}
}Error Responses
All endpoints return errors in this format:
{
"error": "Bad Request",
"message": "messages must be a non-empty array of { role, content } objects",
"requestId": "550e8400-e29b-41d4-a716-446655440000"
}| Status | Meaning |
|---|---|
400 | Invalid request body or parameters |
401 | Missing or invalid authentication |
429 | Rate limit exceeded |
500 | Internal server error |