Call your endpoint from code

2 min read · updated

Every deployment exposes the OpenAI chat completions API at its own base URL, which already ends in /v1. The official SDKs work against it; the only things that change are the base URL and the key.

What you need

  • The base URL, from the Endpoint section of the deployment page.
  • The deployment API key, shown once when you created the deployment. Rotate it from the same page if you no longer have it.
  • A source address on the allowlist. Requests from anywhere else are dropped by the firewall before they reach the model, whatever key they carry.

A first request

curl https://<your-endpoint>/v1/chat/completions \
  -H "Authorization: Bearer $KVRUN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "qwen3.5-9b",
    "messages": [{ "role": "user", "content": "Write a haiku about GPUs" }]
  }'

If you want to confirm the endpoint is up, authenticated and serving the model id you expect, ask it:

curl https://<your-endpoint>/v1/models \
  -H "Authorization: Bearer $KVRUN_API_KEY"

From Python

from openai import OpenAI

client = OpenAI(
    base_url="https://<your-endpoint>/v1",
    api_key="<YOUR_API_KEY>",
)

resp = client.chat.completions.create(
    model="qwen3.5-9b",
    messages=[{"role": "user", "content": "Write a haiku about GPUs"}],
)
print(resp.choices[0].message.content)

From JavaScript

import OpenAI from "openai";

const client = new OpenAI({
  baseURL: "https://<your-endpoint>/v1",
  apiKey: "<YOUR_API_KEY>",
});

const resp = await client.chat.completions.create({
  model: "qwen3.5-9b",
  messages: [{ role: "user", content: "Write a haiku about GPUs" }],
});

console.log(resp.choices[0].message.content);

Streaming

Set stream and you get server-sent events as tokens are produced, which is what keeps a chat interface feeling immediate on long answers.

stream = client.chat.completions.create(
    model="qwen3.5-9b",
    messages=[{"role": "user", "content": "Write a haiku about GPUs"}],
    stream=True,
)

for chunk in stream:
    delta = chunk.choices[0].delta.content
    if delta:
        print(delta, end="", flush=True)

Images, for models that take them

Vision models accept OpenAI-style image content parts, by URL or as a base64 data URI. The deployment page marks a model as Vision when this applies, and the examples on that page gain an image tab.

Isolate the cache per end user

If your application serves many of your own users through one deployment, send a tenant header and each user's cached context is sealed separately. Requests from different tenants never reuse each other's cache, even when the prompts are identical.

X-KV-Tenant: <your-user-id>

This is the control that makes a shared deployment safe for multi-tenant products. The governed KV cache explains what it does underneath.

Connect a coding agent

Tools that speak the OpenAI API need three values: the base URL, the key, and the model id. The deployment page has copyable setup for the common ones.

ToolWhere it goes
CursorSettings, Models, OpenAI API key, then override the base URL and add the model id as a custom model
Continue.devA model entry in ~/.continue/config.json with provider: openai and apiBase set to your endpoint
Anything else OpenAI-compatibleWhatever it calls base URL, API key and model

Use HTTPS before you send anything real

A fresh deployment answers over plain HTTP at the instance's IP, so the key and the prompts travel unencrypted. Add a custom domain from the deployment page: it serves the same endpoint over HTTPS with a certificate that is issued and renewed for you. Note that changing the domain issues a new API key.

Questions

Is it really the OpenAI API?
It is the same request and response shapes, so the official SDKs work by changing the base URL and key. Model-specific features vary with the model you deployed.
Why is my request being refused?
Check both locks: the key must be the deployment's current key, and your source address must be on the firewall allowlist. Rotating the key or changing the domain invalidates the old one.
What is the context limit?
32,000 tokens unless the model sets its own, because decryption scratch space is sized for the longest prompt a deployment will see.
How do I use the key in an app?
As a server-side secret. Never ship a deployment key to a browser or a mobile client; put your own service in front.