Reference
API Reference
One gateway, compatible with both OpenAI and Anthropic — just change the base URL and keep your code.
Base URLs
OpenAI clients append paths to {base}/v1. The Anthropic base has no /v1 — the SDK adds /v1/messages automatically.
Authentication
Send the gateway key in either header. If you send both, Authorization wins.
Authorization: Bearer sk-xxxxxxxxxxxx
x-api-key: sk-xxxxxxxxxxxxNo key → 401 missing_api_key. Invalid/expired/revoked key → 401 invalid_api_key. Out of credit → 402 quota_exhausted.
Endpoints
| Method | Path | Purpose |
|---|---|---|
| GET | /v1 | Health check and endpoint discovery |
| GET | /v1/models | List models the key may use |
| GET | /v1/usage | Remaining quota and credit |
| POST | /v1/chat/completions | Chat completions (OpenAI format) |
| POST | /v1/responses | Responses (OpenAI format) |
| POST | /v1/messages | Messages (Anthropic format) |
| POST | /v1/images/generations | Image generation (OpenAI format) |
Models
All model ids are listed below. For the live list your key is allowed to use, call GET /v1/models.
| Model | Provider | Family | Input / Output |
|---|---|---|---|
claude-opus-4-8 | anthropic | opus | text · vision in |
claude-opus-4-7 | anthropic | opus | text · vision in |
claude-sonnet-5 | anthropic | sonnet | text · vision in |
claude-sonnet-4-6 | anthropic | sonnet | text · vision in |
claude-haiku-4-5 | anthropic | haiku | text · vision in |
gpt-5.5 | openai | codex | text · vision in |
gpt-5.4 | openai | codex | text · vision in |
gpt-5.4-mini | openai | codex | text · vision in |
gpt-4o | openai | other | text · vision in |
gpt-4 | openai | other | text |
gpt-image-1 | openai | image | text · image out |
dall-e-3 | openai | image | text · image out |
auto → claude-opus-4-8; dotted forms like claude-opus-4.8 resolve to claude-opus-4-8. An unknown model → 404 invalid_model.Requests
Chat completions · OpenAI
curl https://api.anajaklabs.dev/v1/chat/completions \
-H "Authorization: Bearer sk-xxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"model": "claude-opus-4-8",
"messages": [{ "role": "user", "content": "Hello" }]
}'Messages · Anthropic
curl https://api.anajaklabs.dev/v1/messages \
-H "x-api-key: sk-xxxxxxxxxxxx" \
-H "anthropic-version: 2023-06-01" \
-H "Content-Type: application/json" \
-d '{
"model": "claude-opus-4-8",
"max_tokens": 1024,
"messages": [{ "role": "user", "content": "Hello" }]
}'Image generation · OpenAI
curl https://api.anajaklabs.dev/v1/images/generations \
-H "Authorization: Bearer sk-xxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-image-1",
"prompt": "a glowing node graph, neon yellow",
"size": "1024x1024"
}'Streaming
Set "stream": true — the gateway sends text/event-stream with no buffering (no-transform). If an error occurs after the stream has started (HTTP 200 already sent) it arrives as a frame:
event: error
data: {"error":{"message":"...","type":"api_error","code":"upstream_error"}}Usage
GET /v1/usage returns the quota for the key you send:
{
"label": "team-key",
"tokens_total": 1000000,
"tokens_used": 12480,
"tokens_remaining": 987520,
"expires_at": "2026-12-31T00:00:00.000Z",
"status": "active",
"rate": { "khr_per_usd": 4000 }
}Errors
Every error uses one envelope shape. The code also comes back as the header x-gateway-error-code. Provider error text is never leaked.
{
"error": {
"message": "Missing API key. Add header: Authorization: Bearer <your-key>",
"type": "authentication_error",
"code": "missing_api_key"
}
}| Code | HTTP | Type | Meaning |
|---|---|---|---|
missing_api_key | 401 | authentication_error | No API key in the header |
invalid_api_key | 401 | authentication_error | Key invalid / expired / revoked |
permission_denied | 403 | permission_error | Key not allowed for this model |
quota_exhausted | 402 | invalid_request_error | Out of credit |
rate_limit_exceeded | 429 | rate_limit_error | Too many requests — over the rate limit |
context_length_exceeded | 400 | invalid_request_error | Context longer than allowed |
content_policy_violation | 400 | invalid_request_error | Content violates policy |
invalid_model | 404 | invalid_request_error | Model doesn't exist or key not allowed |
payload_too_large | 413 | invalid_request_error | Request body too large (default 25MB) |
invalid_json | 400 | invalid_request_error | Body is not valid JSON |
service_unavailable | 503 | api_error | Service busy — please try again |
gateway_timeout | 504 | api_error | Timed out reaching the provider |
upstream_error | 502 | api_error | The provider returned an error |
internal_error | 500 | api_error | Unexpected gateway error |