OpenAI-compatible chat completions, with video that is actually read end to end. If your client already speaks the OpenAI API, the only change is the base URL.
Endpoint not yet accepting public traffic
The semantics below are what the origin implements today; the public host comes online with our OpenRouter listing. Everything on this page is behaviour you can hold us to at that point — including the parts most providers leave unsaid, like what happens when we are full.
POST https://api.costplusiq.com/v1/chat/completions
Authorization: Bearer $COSTPLUSIQ_API_KEY
Content-Type: application/json
Keys are issued per caller, so one can be rotated without
disturbing anyone else. GET /models and GET /health
are public; everything else needs the bearer token.
Pass a video_url content part — either an https
URL we fetch, or the clip inlined as a data: URL. The clip is
decoded at the model's native 2 fps across its whole duration, so
prompt tokens scale with length (~64 tokens per second of 360p video, ~38,000
for a 10-minute clip).
curl https://api.costplusiq.com/v1/chat/completions \
-H "Authorization: Bearer $COSTPLUSIQ_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "Qwen/Qwen3.6-27B",
"stream": true,
"messages": [{"role": "user", "content": [
{"type": "video_url", "video_url": {"url": "https://example.com/clip.mp4"}},
{"type": "text", "text": "Describe every step the operator performs."}
]}]
}'
The same call from the OpenAI Python SDK:
from openai import OpenAI
client = OpenAI(base_url="https://api.costplusiq.com/v1",
api_key=os.environ["COSTPLUSIQ_API_KEY"])
stream = client.chat.completions.create(
model="Qwen/Qwen3.6-27B", stream=True,
messages=[{"role": "user", "content": [
{"type": "video_url", "video_url": {"url": clip_url}},
{"type": "text", "text": "Describe every step the operator performs."},
]}])
for chunk in stream:
print(chunk.choices[0].delta.content or "", end="")
Long video is prefill-dominated: on a 10-minute clip the first output token can be tens of seconds away, and until then a normal SSE connection carries nothing at all. Intermediaries drop connections that look idle, so we send SSE comment frames while the prefill runs:
: keep-alive
: keep-alive
data: {"id":"chatcmpl-…","choices":[{"delta":{"content":"The operator"}}]}
: is skipped
rather than treated as a frame. Prefer stream: true for
video. A non-streaming request is supported, but it holds one connection
silent for the whole prefill, and proxies between us may not wait.If the upstream fails after a stream has started, the error
arrives as an SSE frame — data: {"error":{"code":502,…}} followed
by data: [DONE] — because the HTTP status was already sent.
| limit | value | why |
|---|---|---|
| clip duration | 685 s | 1,370 frames at the model's native 2 fps |
| inline media | 256 MB | a base64 body of ~341 MB; larger clips go by URL |
| request body | 384 MiB | hard ceiling; past it you get 413 |
| context | 262,144 tokens | the longest accepted clip fits with room to spare |
| output | 32,768 tokens | per response |
| concurrency | 16 in flight | published in /models, and enforced |
We refuse rather than queue. A request that arrives with every slot busy
gets 429 with Retry-After immediately, instead of
sitting in a queue and returning slowly. A queue would flatter our error rate
and wreck the latency you actually experience, and latency is the thing worth
optimising for.
Capacity is judged by what the GPUs report running, not by what we happen to have dispatched — so a busy box is never sold as an idle one.
| status | meaning |
|---|---|
401 | missing or unknown bearer token |
404 | that model is not served here — see /models |
413 | body past the inline-media ceiling; send a URL instead |
429 | at declared concurrency; retry after the header says |
502 | upstream failure. Transport failures are already retried once on another GPU before you see this |
503 | no healthy capacity at all |
Errors use the OpenAI shape:
{"error":{"type":…,"message":…}}.
Prompts, media and completions are processed in memory and never persisted, never logged, and never trained on. What we keep is the metadata a bill is made of: which key called, when, the model, the status, and token counts.
| route | auth | returns |
|---|---|---|
GET /models | public | the provider document: models, pricing, published capacity, compliance |
GET /v1/models | bearer | the OpenAI-shaped model list |
GET /health | public | readiness of the endpoint |