OdiRouter Model API
Model API provides different invocation protocols for different model types. Multimodal models usually use an asynchronous task protocol: create a task, poll its status, and retrieve the result. Large language models usually use synchronous or streaming protocols, returning text or incremental output within a single request.
Confirmed routes
Section titled “Confirmed routes”| Capability | Method | Path | Notes |
|---|---|---|---|
| Model list | GET | /v1/models | List available models |
| Chat Completions | POST | /v1/chat/completions | OpenAI-compatible messages |
| Responses | POST | /v1/responses | Unified Responses API |
| Multimodal submit | POST | /model/v1/queue/{endpoint} | Creates a queue request for the endpoint |
| Task status | GET | /model/v1/queue/{endpoint}/requests/{request_id}/status | Returns the current task status |
| Result fetch | GET | /model/v1/queue/{endpoint}/requests/{request_id}/response | Returns the result after completion |
| Task cancellation | PUT | /model/v1/queue/{endpoint}/requests/{request_id}/cancel | Cancels the task when supported |
| Sora-style video | POST | /v1/videos | Separate multipart video endpoint |
OdiRouter LLM API is for Chat Completions and Responses API calls. Endpoints use the unified /v1 prefix, and the platform handles API Key authentication, balance checks, and request tracing.
Quick call
Section titled “Quick call”export BASE_URL="https://odirouter.ai/v1"export API_KEY="YOUR_API_KEY"
curl -sS "${BASE_URL}/chat/completions" \ -H "Authorization: Bearer ${API_KEY}" \ -H "Content-Type: application/json" \ -H "X-Request-Id: demo-$(date +%s)" \ -d '{ "model": "gpt-4.1", "messages": [ { "role": "user", "content": "Introduce OdiRouter LLM API in one sentence" } ], "temperature": 0.7 }'from openai import OpenAI
client = OpenAI( api_key="YOUR_API_KEY", base_url="https://odirouter.ai/v1",)
response = client.chat.completions.create( model="gpt-4.1", messages=[ { "role": "user", "content": "Introduce OdiRouter LLM API in one sentence", } ],)
print(response.choices[0].message.content)Multimodal models
Section titled “Multimodal models”Multimodal models use an asynchronous queue protocol: create a task, poll its status, and retrieve the result after completion. To stop execution, send a cancellation request. The endpoint in the URL directly uses the OdiRouter model ID, and the request body directly passes the model parameter object.
Lifecycle docs
Section titled “Lifecycle docs”Complete code example
Section titled “Complete code example”export BASE_URL="https://odirouter.ai/model"export ENDPOINT="nano_banana_2"export API_KEY="YOUR_API_KEY"
COMMON_HEADERS=( -H "Authorization: Bearer ${API_KEY}" -H "Content-Type: application/json")
SUBMIT_RESPONSE="$(curl -sS -X POST "${BASE_URL}/v1/queue/${ENDPOINT}" \ "${COMMON_HEADERS[@]}" \ -d '{ "prompt": "a cinematic photo of a cat astronaut" }')"
echo "${SUBMIT_RESPONSE}" | jq .
REQUEST_ID="$(echo "${SUBMIT_RESPONSE}" | jq -r '.request_id')"STATUS_URL="$(echo "${SUBMIT_RESPONSE}" | jq -r '.status_url')"RESPONSE_URL="$(echo "${SUBMIT_RESPONSE}" | jq -r '.response_url')"
while true; do STATUS_RESPONSE="$(curl -sS "${STATUS_URL}" "${COMMON_HEADERS[@]}")" echo "${STATUS_RESPONSE}" | jq .
STATUS="$(echo "${STATUS_RESPONSE}" | jq -r '.status')" ERROR="$(echo "${STATUS_RESPONSE}" | jq -r '.error // empty')"
if [ "${STATUS}" = "COMPLETED" ]; then if [ -n "${ERROR}" ]; then echo "task failed: ${ERROR}" exit 1 fi break fi
sleep 3done
curl -sS "${RESPONSE_URL}" "${COMMON_HEADERS[@]}" | jq .import timeimport requests
BASE_URL = "https://odirouter.ai/model"ENDPOINT = "nano_banana_2"API_KEY = "YOUR_API_KEY"
headers = { "Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json",}
submit_resp = requests.post( f"{BASE_URL}/v1/queue/{ENDPOINT}", headers=headers, json={ "prompt": "a cinematic photo of a cat astronaut", }, timeout=30,)submit_resp.raise_for_status()submit_body = submit_resp.json()
request_id = submit_body["request_id"]status_url = submit_body["status_url"]response_url = submit_body["response_url"]
while True: status_resp = requests.get(status_url, headers=headers, timeout=30) status_resp.raise_for_status() status_body = status_resp.json()
status = status_body["status"] if status == "COMPLETED": if "error" in status_body: raise RuntimeError(f"{status_body.get('error_type')}: {status_body['error']}") break
time.sleep(3)
result_resp = requests.get(response_url, headers=headers, timeout=30)result_resp.raise_for_status()result_body = result_resp.json()
print("request_id:", request_id)print("result:", result_body)