AI Gatewayevery model, one key, one bill.
An OpenAI-compatible endpoint for the models a Space allows, called with a Space key and billed to the Space wallet.
The AI Gateway lets any OpenAI-compatible client (the OpenAI SDKs, LangChain, Cursor, your own code) use Wakato as its model provider. You call it with a Space API key, the models are the ones the Space allows, and every call is charged to the Space wallet and shows up in its usage.
| OpenAI base URL | https://api.wakato.io/functions/v1/gateway-endpoint/v1 |
| Anthropic base URL | https://api.wakato.io/functions/v1/gateway-endpoint |
| Auth | Authorization: Bearer wks_live_… or x-api-key: wks_live_… |
| Scope | ai:run ("Space Gateway" in the key dialog) |
Make a key in Space → Settings → API Keys with the Space Gateway ticked. See Keys and scopes.
Chat completions
import OpenAI from "openai";
const ai = new OpenAI({
baseURL: "https://api.wakato.io/functions/v1/gateway-endpoint/v1",
apiKey: process.env.WAKATO_SPACE_KEY, // wks_live_…
});
const res = await ai.chat.completions.create({
model: "anthropic/claude-sonnet-4.6",
messages: [{ role: "user", content: "Write 3 ad headlines for a linen apron" }],
});
console.log(res.choices[0].message.content);import os
from openai import OpenAI
ai = OpenAI(
base_url="https://api.wakato.io/functions/v1/gateway-endpoint/v1",
api_key=os.environ["WAKATO_SPACE_KEY"],
)
res = ai.chat.completions.create(
model="anthropic/claude-sonnet-4.6",
messages=[{"role": "user", "content": "Write 3 ad headlines for a linen apron"}],
)
print(res.choices[0].message.content)curl https://api.wakato.io/functions/v1/gateway-endpoint/v1/chat/completions \
-H "Authorization: Bearer $WAKATO_SPACE_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "anthropic/claude-sonnet-4.6",
"messages": [{ "role": "user", "content": "Write 3 ad headlines for a linen apron" }]
}'temperature, max_tokens (or max_completion_tokens), tools and
tool_choice are passed through. Model names are vendor/model; take them from
the model list below rather than guessing.
List models
curl https://api.wakato.io/functions/v1/gateway-endpoint/v1/models \
-H "Authorization: Bearer $WAKATO_SPACE_KEY"The answer is an OpenAI-style list. Each entry's id is the string to send as
model, plus a few extras most clients ignore: display_name, category
(text, image, video, audio, embedding…), context_window,
max_output_tokens, supports_tools, supports_vision. It lists only what
this key may call in this Space.
Which models a Space may use
- A Space with no model list allows every active Wakato model.
- Once the owner or an admin adds models to the Space's list, only those are
allowed. A call to another model gets
403with a sentence saying it is not on in this Space. - A key can be narrowed further to selected models in its own settings. A
model outside the key's list is refused with
403, naming the allowed ones.
Streaming
stream: true is accepted and answers with standard server-sent events, so
streaming clients work unchanged. The gateway completes the call first and then
replays it as a stream: the text arrives at the end, not token by token. Plan
timeouts accordingly; a single call may take up to about two minutes.
const stream = await ai.chat.completions.create({
model: "anthropic/claude-sonnet-4.6",
messages: [{ role: "user", content: "Summarise this week's orders" }],
stream: true,
});
for await (const chunk of stream) process.stdout.write(chunk.choices[0]?.delta?.content ?? "");Other routes
All under the same base, same key and scope:
| Method | Path | What it does |
|---|---|---|
| POST | /v1/embeddings | OpenAI-compatible embeddings |
| POST | /v1/images/generations | Image generation |
| POST | /v1/audio/speech | Text to speech; answers JSON with the audio URL |
| POST | /v1/audio/transcriptions | Speech to text: a multipart file, or JSON audio_url / audio |
| POST | /v1/evaluations | Judging: typed questions about a text, answered with probabilities |
| POST | /v1/generations | Video, music and other media: { model, input } |
| GET | /v1/generations/:job_id | Poll a media job |
| POST | /v1/messages | Anthropic-compatible messages (streaming supported) |
| POST | /v1/messages/count_tokens | A rough token count |
Media generation is asynchronous by default: /v1/generations answers 202
with an id and a poll path. Send "wait": true only for fast models.
Clients built on the Anthropic SDK point their base URL at
https://api.wakato.io/functions/v1/gateway-endpoint and use the same key.
Billing and spend limits
Every call is charged to the Space wallet, tagged with the key, so the Space's usage shows what each key cost. Calls stop when money runs out:
- The wallet cannot cover the call:
402, codeINSUFFICIENT_BALANCE. - A spending cap set on the Space was reached:
402, codeSPACE_BUDGET_EXCEEDED. - When the key belongs to one of the Space's agents, that agent's own daily,
weekly or monthly cap also applies:
402, codeAGENT_SPEND_CAP.
A 402 always means the Space's money or limits, never a provider problem.
Errors
Errors use OpenAI's envelope (Anthropic's on /v1/messages):
{
"error": {
"message": "Wakato's model service is temporarily unavailable. Please try again in a few minutes.",
"type": "api_error",
"code": "PROVIDER_DOWN"
}
}| Status | Code | Meaning | What to do |
|---|---|---|---|
| 400 | REQUEST_TOO_LONG | Too long for the model | Shorten the input |
| 400 | PROVIDER_REJECTED | The model could not process the request | Check the input |
| 401 | Missing, wrong, expired or revoked key | Check the key | |
| 402 | INSUFFICIENT_BALANCE, SPACE_BUDGET_EXCEEDED, AGENT_SPEND_CAP | Money or a cap | Top up or raise the cap |
| 403 | No ai:run scope, or the model is not allowed | Edit the key or the Space's models | |
| 404 | MODEL_NOT_FOUND | Unknown model | Use an id from /v1/models |
| 429 | PROVIDER_BUSY | The model is busy | Retry with backoff |
| 503 | PROVIDER_DOWN | Temporarily unavailable | Retry in a few minutes |
Messages are Wakato's own sentences and safe to show to a person. Retry 429
and 503; do not retry 400, 402 or 403 without changing something.
From an app or an agent
Inside a Space App, use wakato.gateway.llm() and friends instead; see the
App SDK. Agents connected over MCP reach the same models
through the AI tools.