Orux AI Documentation
One API, every leading model
OpenAI SDK compatible, with unified authentication, unified Credits billing, and automatic model-based routing for speed and reliability.
Quickstart
Get your API key and make your first request in a few minutes.
1. Create an API key
Sign up and open the API Keys page in your dashboard, then create a new key. The key is shown in full only once — copy it somewhere safe. You can view or copy it again later from the same page, and revoke it at any time.
Keys are prefixed with sk- and should be treated like a password: never commit them to source control or expose them in client-side code.
2. Make your first request
Orux AI speaks the OpenAI API protocol. Point any OpenAI-compatible client at https://orux.top/api/v1 and pass your key as a bearer token — no other code changes are required.
curl
curl https://orux.top/api/v1/chat/completions \
-H "Authorization: Bearer sk-xxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-5.4",
"messages": [{ "role": "user", "content": "Hello!" }]
}'Python
from openai import OpenAI
client = OpenAI(
base_url="https://orux.top/api/v1",
api_key="sk-xxxxxxxx",
)
response = client.chat.completions.create(
model="gpt-5.4",
messages=[{"role": "user", "content": "Hello!"}],
)
print(response.choices[0].message.content)Node.js
import OpenAI from "openai";
const client = new OpenAI({
baseURL: "https://orux.top/api/v1",
apiKey: process.env.ORUX_API_KEY,
});
const response = await client.chat.completions.create({
model: "gpt-5.4",
messages: [{ role: "user", content: "Hello!" }],
});
console.log(response.choices[0].message.content);3. Where to go next
- Authentication — how bearer tokens are validated and best practices for storing keys.
- Chat — streaming and non-streaming chat completions.
- Embeddings — vector embeddings for search and retrieval.
- Images — synchronous image generation.
- Async tasks — video and audio/music generation, which run as background jobs.
- Models — how to list the models currently available to your key.
Authentication
How to pass your API key and how the gateway validates it.
Bearer token
Every request to /api/v1/* (except GET /api/v1/models) must include your API key in the Authorization header as a bearer token:
header
Authorization: Bearer sk-xxxxxxxxKey lifecycle
Keys are created and managed from your dashboard. Unlike some providers, Orux AI lets you reveal and copy the full key again after creation — you do not need to regenerate it if you lose it, though you can revoke and rotate at any time.
A key can optionally be scoped to a specific model allowlist. If your key is restricted and you call a model outside that list, the request is rejected before it reaches any upstream provider.
Authentication errors
Missing, malformed, or invalid keys all return HTTP 401 with an OpenAI-compatible error body:
response
{
"error": {
"message": "Invalid API key",
"type": "invalid_request_error",
"code": "invalid_api_key"
}
}Security recommendations
- Never embed your key in frontend/browser code — proxy requests through your own backend.
- Use a separate key per environment (dev / staging / production) so you can revoke one without affecting others.
- Set a model allowlist on keys that only need access to a subset of models.
- Rotate a key immediately if you suspect it has leaked.
Chat
POST /api/v1/chat/completions — OpenAI-compatible chat completions, with streaming support.
Request
Send a model name and a list of messages. This endpoint mirrors the OpenAI Chat Completions API, so any parameter your OpenAI client supports is passed through.
curl (non-streaming)
curl https://orux.top/api/v1/chat/completions \
-H "Authorization: Bearer sk-xxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-5.4",
"messages": [{ "role": "user", "content": "Hello!" }],
"stream": false
}'response
{
"id": "chatcmpl-...",
"choices": [
{ "index": 0, "message": { "role": "assistant", "content": "Hello! How can I help you today?" } }
],
"usage": { "prompt_tokens": 12, "completion_tokens": 9, "total_tokens": 21 }
}Streaming (SSE)
Set "stream": true to receive incremental output as Server-Sent Events. Each event is a JSON chunk with a choices[0].delta field; the stream ends with a literal data: [DONE] line. If the client disconnects mid-stream, the gateway stops forwarding immediately.
Pass "stream_options": { "include_usage": true } to receive one extra chunk at the end of the stream containing token usage for the whole response.
curl (streaming)
curl https://orux.top/api/v1/chat/completions \
-H "Authorization: Bearer sk-xxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-5.4",
"messages": [{ "role": "user", "content": "Write a haiku about the sea" }],
"stream": true,
"stream_options": { "include_usage": true }
}'event stream
data: {"choices":[{"index":0,"delta":{"role":"assistant","content":""}}]}
data: {"choices":[{"index":0,"delta":{"content":"Waves"}}]}
data: {"choices":[{"index":0,"delta":{"content":" crash"}}]}
data: {"choices":[{"index":0,"delta":{}}],"usage":{"prompt_tokens":14,"completion_tokens":7,"total_tokens":21}}
data: [DONE]Python (streaming)
from openai import OpenAI
client = OpenAI(base_url="https://orux.top/api/v1", api_key="sk-xxxxxxxx")
stream = client.chat.completions.create(
model="gpt-5.4",
messages=[{"role": "user", "content": "Write a haiku about the sea"}],
stream=True,
)
for chunk in stream:
delta = chunk.choices[0].delta.content or ""
print(delta, end="", flush=True)Supported request fields
- model (required) — the model alias, see the Models page for how to list available values.
- messages (required) — array of { role, content }; content can be a string or a content-part array for multimodal models.
- stream — set true for SSE streaming.
- stream_options.include_usage — append a final usage-only chunk when streaming.
- temperature, max_tokens, and other OpenAI-compatible parameters are passed through to the upstream model where supported.
Billing
Chat requests are billed in Credits based on prompt and completion token usage, only on success. Failed requests are not charged.
Embeddings
POST /api/v1/embeddings — OpenAI-compatible vector embeddings.
Request
Send one string or an array of strings as input, along with an embedding model alias. The response mirrors the OpenAI Embeddings API shape.
curl
curl https://orux.top/api/v1/embeddings \
-H "Authorization: Bearer sk-xxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"model": "text-embedding-3-large",
"input": ["Orux AI is a unified model gateway"]
}'Python
from openai import OpenAI
client = OpenAI(base_url="https://orux.top/api/v1", api_key="sk-xxxxxxxx")
response = client.embeddings.create(
model="text-embedding-3-large",
input=["Orux AI is a unified model gateway"],
)
print(response.data[0].embedding[:5])response (truncated)
{
"object": "list",
"data": [{ "object": "embedding", "index": 0, "embedding": [0.0023, -0.009, "..."] }],
"model": "text-embedding-3-large",
"usage": { "prompt_tokens": 8, "total_tokens": 8 }
}Supported request fields
- model (required) — an embedding-capable model alias.
- input (required) — a string or array of strings.
- encoding_format — optional, passed through to the upstream model.
Images
POST /api/v1/images/generations — synchronous image generation, OpenAI-compatible.
Request
This endpoint returns image URLs synchronously once generation completes. It is intended for fast image models; slower or video-adjacent generation should go through the async Tasks API instead.
curl
curl https://orux.top/api/v1/images/generations \
-H "Authorization: Bearer sk-xxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-image-2",
"prompt": "A cat sitting on a windowsill at sunset",
"n": 1,
"size": "1024x1024"
}'Python
from openai import OpenAI
client = OpenAI(base_url="https://orux.top/api/v1", api_key="sk-xxxxxxxx")
response = client.images.generate(
model="gpt-image-2",
prompt="A cat sitting on a windowsill at sunset",
n=1,
size="1024x1024",
)
print(response.data[0].url)response
{ "data": [{ "url": "https://cdn.orux.top/....png" }] }Supported request fields
- model (required) — an image-capable model alias.
- prompt (required) — text description of the desired image.
- n — number of images to generate, 1–10.
- size — image dimensions, model-dependent.
- response_format — optional, passed through to the upstream model.
Billing
Billed in Credits per generated image, only on success.
Async tasks
POST /api/v1/tasks and GET /api/v1/tasks/{taskId} — the unified entry point for video, audio/music, and other long-running generations.
Why async tasks
Video and audio/music generation are not exposed as OpenAI-compatible synchronous endpoints (there is no /api/v1/videos/generations or /api/v1/audio/*). These modalities can take anywhere from several seconds to several minutes, so the gateway exposes them through a single async task queue: you submit a job, then poll for its result.
1. Submit a task
POST a model alias and a model-specific input object. input is passed through to the underlying model as-is (for example a video model expects a prompt and duration; a music model expects a prompt and lyrics). An optional callback URL can be provided to receive a webhook when the task finishes, instead of polling.
curl
curl https://orux.top/api/v1/tasks \
-H "Authorization: Bearer sk-xxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"model": "veo-3.1",
"input": {
"prompt": "A slow sunrise over calm ocean waves",
"duration": 8
}
}'response (202 Accepted)
{
"task_id": "tk_1a2b3c4d5e6f7a8b9c0d1e2f",
"status": "QUEUED",
"created_at": 1755000000,
"model": "veo-3.1"
}2. Poll for the result
Use the returned task_id to check status. Poll at a reasonable interval (a few seconds) until the task reaches a terminal state.
curl
curl https://orux.top/api/v1/tasks/tk_1a2b3c4d5e6f7a8b9c0d1e2f \
-H "Authorization: Bearer sk-xxxxxxxx"response (still running)
{
"task_id": "tk_1a2b3c4d5e6f7a8b9c0d1e2f",
"status": "RUNNING",
"model": "veo-3.1",
"created_at": 1755000000,
"updated_at": 1755000012,
"result": null,
"error": null
}response (success)
{
"task_id": "tk_1a2b3c4d5e6f7a8b9c0d1e2f",
"status": "SUCCESS",
"model": "veo-3.1",
"created_at": 1755000000,
"updated_at": 1755000090,
"result": ["https://cdn.orux.top/....mp4"],
"error": null
}response (failed)
{
"task_id": "tk_1a2b3c4d5e6f7a8b9c0d1e2f",
"status": "FAILED",
"model": "veo-3.1",
"created_at": 1755000000,
"updated_at": 1755000030,
"result": null,
"error": { "code": "task_failed", "message": "Task failed" }
}Task status values
- QUEUED — accepted, waiting to start.
- RUNNING — in progress upstream.
- SUCCESS — finished; result contains one or more output URLs.
- FAILED — finished with an error; see error.code and error.message.
- EXPIRED — the task result window elapsed before it was retrieved.
Submit request fields
- model (required) — an async-capable model alias (video, audio, or async image).
- input (required) — a model-specific object, passed through to the underlying model.
- callback — optional URL to receive a webhook on completion instead of polling.
Billing
Billed in Credits when the task reaches SUCCESS. Failed or expired tasks are not charged.
Video generation: No /api/v1/videos/generations endpoint
There is no synchronous video endpoint. Submit video generation jobs through POST /api/v1/tasks with a video-capable model alias, then poll GET /api/v1/tasks/{taskId} — see the Async tasks page for the full request/response cycle and status machine.
curl
curl https://orux.top/api/v1/tasks \
-H "Authorization: Bearer sk-xxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"model": "veo-3.1",
"input": { "prompt": "A slow sunrise over calm ocean waves", "duration": 8 }
}'Audio & music generation: No /api/v1/audio/* endpoint
There is no synchronous audio or music endpoint. Submit music generation jobs through POST /api/v1/tasks with a music-capable model alias, then poll GET /api/v1/tasks/{taskId} — see the Async tasks page for the full request/response cycle and status machine.
curl
curl https://orux.top/api/v1/tasks \
-H "Authorization: Bearer sk-xxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"model": "suno-v5",
"input": { "prompt": "An upbeat lo-fi track", "instrumental": false }
}'Models
GET /api/v1/models — list the models currently available to your key.
Listing models
Model availability changes over time as providers are added or updated, so do not hardcode a model list in your application — call this endpoint (or check the Models catalog page) instead. The endpoint does not require authentication and mirrors the OpenAI /v1/models response shape.
curl
curl https://orux.top/api/v1/modelsresponse (truncated)
{
"object": "list",
"data": [
{ "id": "gpt-5.4", "object": "model", "created": 1755000000, "owned_by": "orux" },
{ "id": "gpt-image-2", "object": "model", "created": 1755000000, "owned_by": "orux" }
]
}Full catalog with pricing
For a browsable catalog with descriptions and Credit pricing per model, see the Models page in the main site navigation.
Example response
| alias | Modality | Vendor | Streaming |
|---|---|---|---|
| gpt-5.4 | CHAT | OpenAI | Yes |
| gemini-3.6-flash | CHAT | Yes | |
| gpt-image-2 | IMAGE | OpenAI | No |
| seedream-5-lite | IMAGE | ByteDance | No |
| kling-v3 | VIDEO | Kuaishou | No |
| suno-v5 | AUDIO | Suno | No |
Rate limits & concurrency
Requests are subject to per-key and per-account concurrency and rate limits.
How limits are applied
Limits are enforced at multiple levels: per API key, and per account across all of your keys combined. Exact numeric limits depend on your plan and are shown in your dashboard rather than fixed in this documentation, since they can be adjusted per account.
- Per-key concurrency — the maximum number of in-flight requests for a single API key.
- Per-account concurrency — the maximum combined in-flight requests across all keys under your account.
- Rate limit (requests per time window) — enforced per key.
What happens when you hit a limit
Depending on the endpoint, an over-limit request is either rejected immediately with HTTP 429, held briefly in a wait queue, or (for async task submission) queued for later processing. A 429 response includes an OpenAI-compatible error body with code rate_limit or concurrency_limit_exceeded — back off and retry.
Checking your current limits
See the Usage / Plan section of your dashboard for the concurrency and rate limits attached to your account and each key.
Errors
All errors use the OpenAI-compatible { error: { message, type, code } } response shape.
Error response shape
response
{
"error": {
"message": "human-readable description",
"type": "invalid_request_error",
"code": "param_error"
}
}Troubleshooting tips
- 401 invalid_api_key — check the Authorization header format and that the key has not been revoked.
- 400 param_error / invalid_messages — validate your request body against the field lists on each endpoint page.
- 400 model_not_routed / model_not_allowed — the model alias does not exist, is not enabled, or is outside your key’s allowlist; check GET /api/v1/models.
- 429 rate_limit / concurrency_limit_exceeded — you have hit your concurrency or rate limit; retry with backoff.
- 429 quota_exceeded — your account or key has insufficient Credits or has hit a spending limit.
- 5xx / upstream errors — transient upstream failure; safe to retry with backoff for idempotent requests.
- task_failed / task_expired / task_not_found — see the Async tasks page for the task status machine.
Billing
How usage is converted into Credits.
All usage is metered and billed in Credits, deducted from your account balance only after a request succeeds. Failed requests are never charged.
- Chat and embeddings — billed per token, with input (prompt) and output (completion) tokens priced separately; streaming responses are billed the same way as non-streaming once the stream completes.
- Images — billed per successfully generated image.
- Async tasks (video, audio/music) — billed once when the task reaches the SUCCESS status; tasks that fail or expire are not charged.
- Exact Credit prices per model are shown on the Models page and in your dashboard before you commit to a request.
- You can track balance and per-request cost breakdowns from the Usage section of your dashboard.