Documentation
An OpenAI-compatible API. If your code already speaks to the OpenAI SDK, the only change is a base URL.
Base URL
https://router.xark.io/api/v1Authenticate with Authorization: Bearer sk-…. Create a key from the dashboard.
Three endpoint families
Text generation
Synchronous and streamable, billed per token with a separate cached-input rate that applies automatically to a repeated prefix. The Responses API and legacy completions exist so an older integration does not have to be rewritten before it can be pointed here.
/v1/chat/completions · /v1/responses · /v1/completions · /v1/embeddings
Media generation
Video is asynchronous — submit, then poll the job id — and billed as a flat price per clip at a fixed 5-second duration, so a request for any other length is refused rather than billed at a rate you did not agree to. Images and speech are synchronous and billed per image and per request.
/v1/video/generations · /v1/images/generations · /v1/images/edits · /v1/audio/speech
Catalogue and pricing
Unauthenticated and safe to poll. The model list carries every id, licence, context window, our rate, the official rate and a prices_updated_at stamp, which makes it the machine-readable way to detect a catalogue or price change.
/v1/models · /v1/pricing
What differs from OpenAI
Request shapes, streaming frames, the usage block and the error envelope all match. These are the places where a working OpenAI integration needs to know it is talking to us.
- Model ids are namespaced provider/model-name — z-ai/glm-5.2, not glm-5.2. The bare name and the site's URL slug still resolve, so an older integration keeps working, but the namespaced id is what we echo back.
- There is no automatic cross-model fallback. A failing upstream returns an error you can branch on rather than a different model's answer, because a substitution changes the output, the price and the licence of what you receive.
- 429 carries two unrelated meanings, separated by error.code: insufficient_credits means top up, rate_limit_exceeded means back off. Your prepaid balance is a hard ceiling, so the first of those is a normal end state rather than an incident.
- Some catalogued models are not served. A request for one returns no available channel instead of silently routing elsewhere — the catalogue marks which is which before you write the call.
- Cached input is automatic and has no header. A repeated prefix is billed at the published cached rate, and on an agent workload that is usually the largest line on the bill, which is why it has its own pricing column.
- Failed requests are not billed, including the request that discovers your balance is empty.
Where to go next
Migrating from another provider
Change a base URL and a key. Includes the model-id mapping and the three behaviours that differ from OpenAI.
Video, image and speech
Asynchronous video generation, OpenAI-compatible images and editing, and speech synthesis. Paths, parameters and the error table.
Model catalogue
Every model, its id, its licence and its published rate. Also available as JSON from GET /api/v1/models.
Pricing
Per-model rates with the official rate printed alongside, and the cached-input rate in its own column.
Licensing and compliance
Model licences, data handling, security practices and vulnerability disclosure.
Endpoints
| Path | Method | Auth |
|---|---|---|
| /v1/chat/completions | POST | API key |
| /v1/responses | POST | API key |
| /v1/completions | POST | API key |
| /v1/embeddings | POST | API key |
| /v1/video/generations | POST | API key |
| /v1/video/generations/{id} | GET | API key |
| /v1/images/generations | POST | API key |
| /v1/images/edits | POST | API key |
| /v1/audio/speech | POST | API key |
| /v1/models | GET | none |
| /v1/pricing | GET | none |
Streaming is supported on every text endpoint with "stream": true, in the same server-sent-event format the OpenAI SDK already parses.