Skip to content

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/v1

Authenticate 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

Endpoints

PathMethodAuth
/v1/chat/completionsPOSTAPI key
/v1/responsesPOSTAPI key
/v1/completionsPOSTAPI key
/v1/embeddingsPOSTAPI key
/v1/video/generationsPOSTAPI key
/v1/video/generations/{id}GETAPI key
/v1/images/generationsPOSTAPI key
/v1/images/editsPOSTAPI key
/v1/audio/speechPOSTAPI key
/v1/modelsGETnone
/v1/pricingGETnone

Streaming is supported on every text endpoint with "stream": true, in the same server-sent-event format the OpenAI SDK already parses.