API Gateway
https://gateway.agentsky.dev serves the Anthropic Messages API and the OpenAI Chat Completions, Responses and Embeddings APIs behind one AgentSky key, plus a run API for non-model endpoints (search, maps, email, speech, transcription, SEO data, image generation). Every response carries its price.
Base URLs
| Client | Base URL |
|---|---|
Anthropic SDK, Claude Code (ANTHROPIC_BASE_URL) | https://gateway.agentsky.dev |
OpenAI SDK, Codex (OPENAI_BASE_URL) | https://gateway.agentsky.dev/v1 |
Authenticate with an AgentSky API key (ast_…, created under Settings → API keys) as x-api-key or Authorization: Bearer. Model calls and runs need the write scope; catalog and account reads need read.
Routes
| Method | Path | Notes |
|---|---|---|
| POST | /v1/messages | Anthropic Messages API, streamed or not |
| POST | /v1/messages/count_tokens | forwarded unmetered |
| POST | /v1/chat/completions, /v1/responses, /v1/embeddings | OpenAI APIs |
| GET | /v1/models, /v1/models/{vendor}/{model} | public catalog with per-token prices and providers |
| GET | /v1/endpoints, /v1/providers | public run catalog and provider list |
| POST | /v1/run | {provider, endpoint, input} → run object |
| GET | /v1/runs/{runId} | a run from the last hour |
| GET | /v1/credits | balance and total used |
| GET | /v1/generation?id= | one call's record: tokens, cost, provider |
Model ids
Use the catalog id (anthropic/claude-sonnet-5, qwen/qwen-max), an accepted alias (glm/glm-5.2, kimi/k3), or the bare id (claude-sonnet-5). A vendor prefix that matches nothing is a 404.
Provider routing and failover
A model may be served by several providers. The gateway tries them in its default order and fails over to the next allowed provider when one is unreachable, times out before the first byte, or answers 408, 429, 401, 403 or 5xx; any other reply is returned as-is, and nothing is retried once response bytes have been sent.
- Request header
x-agentsky-provider: bedrock,anthropic— the allowed providers, in order (works on every wire and in Claude Code viaANTHROPIC_CUSTOM_HEADERS). - Body
provider: { "order": [...], "only": [...], "sort": "cost" }(OpenRouter's field) orproviderOptions.gateway(Vercel's). Accepted on both wires, stripped before forwarding. - Response header
x-agentsky-providernames the provider that served the call;x-agentsky-provider-attemptslists skipped providers with their status. OpenAI-wire bodies also carry a top-levelproviderfield. - A restriction no provider can meet is
400 provider_not_availablenaming the model's providers.
Cost in the response
Model calls: usage.cost (USD) on the final usage object (the usage-only last chunk of an OpenAI stream, response.completed on the Responses API, message_delta on the Anthropic wire, or the JSON body). Runs: price.amount plus billing.calculatedCost, billing.actualCost and billing.reportedCost. Prices are per token or per unit as listed in the catalog and may differ per provider; GET /v1/generation?id=<upstream id or call id> returns the record once it has landed.
Runs
POST /v1/run
{ "provider": "exa", "endpoint": "search", "input": { "query": "agent gateways", "numResults": 5 } }
200 { "runId": "run_…", "status": "COMPLETED", "provider": "exa", "endpoint": "search",
"output": { … vendor response … },
"price": { "type": "PER_CALL", "amount": { "value": 0.014, "currency": "USD" } },
"billing": { "calculatedCost": { "value": 0.007, … }, "actualCost": { … }, "reportedCost": { "value": null, … } },
"providerResponse": { "httpStatus": 200 }, … }Every endpoint is synchronous. Binary outputs (audio, images) come back inline as { "data": "<base64>", "mediaType": "audio/mpeg", "bytes": n }. A failed run has status: FAILED or TIMED_OUT, error: { code, message } with the vendor's message, and is not charged.
Errors
Errors take the shape of the wire: Anthropic { "type": "error", "error": { "type", "message" } }, OpenAI { "error": { "message", "type", "param", "code" } }, and { "error": { "code", "message" } } on run and account routes. Codes you will see: model_not_found, endpoint_not_found, provider_not_available, pricing_unavailable (503, the SKU has no rate yet), upstream_unavailable, insufficient_credits / insufficient_quota (spend gate), rate_limited.
Limits
Request bodies up to 10 MB on the model wires and 1 MB on most run endpoints (35 MB for audio uploads). Media outputs up to 20 MB inline. Per-key rate limits apply.