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 APIs for search, maps, email, speech, transcription, SEO data and image generation (the run API). Every response carries its price.

Base URLs

ClientBase 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

MethodPathNotes
POST/v1/messagesAnthropic Messages API, streamed or not
POST/v1/messages/count_tokensforwarded unmetered
POST/v1/chat/completions, /v1/responses, /v1/embeddingsOpenAI APIs
GET/v1/models, /v1/models/{vendor}/{model}public catalog with per-token prices, context, and modalities
GET/v1/endpoints, /v1/endpoints/{provider}/{endpoint}public run catalog, and one API with its input fields and limits
GET/v1/providersAPI provider list
POST/v1/run{provider, endpoint, input} → run object
GET/v1/runs/{runId}a run from the last hour
GET/v1/creditsbalance and total used
GET/v1/generation?id=one call's record: tokens and cost

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.

Failover

A model may be served from more than one place. The gateway tries them in its own order and fails over to the next 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. Which upstream serves a call is platform configuration, not a request option: OpenRouter's provider body field and Vercel's providerOptions.gateway are accepted and dropped before forwarding.

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; GET /v1/generation?id=<upstream id or call id> returns the record once it has landed.

Runs

text
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, 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 APIs (35 MB for audio uploads). Media outputs up to 20 MB inline. Per-key rate limits apply.