Skip to content
Radient LogoRadient Documentation

Chat API Usage Guide

Radient's Chat API is OpenAI-compatible: point an existing OpenAI client at https://api.radienthq.com/v1, use your Radient API key, and calls are billed to your Radient Pass.

The examples below were executed against the API; where a body is trimmed, a … marks the cut and the surrounding figures are as returned.

#Send a chat completion request

bash
curl https://api.radienthq.com/v1/chat/completions \
  -H "Authorization: Bearer $RADIENT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "auto",
    "max_tokens": 16,
    "messages": [
      { "role": "user", "content": "Reply with the single word: pong" }
    ]
  }'
json
{
  "id": "gen-…",
  "object": "chat.completion",
  "created": 1791564194,
  "model": "…",
  "choices": [
    {
      "index": 0,
      "message": { "role": "assistant", "content": "pong" },
      "finish_reason": "stop"
    }
  ],
  "usage": {
    "prompt_tokens": 1402,
    "completion_tokens": 45,
    "total_tokens": 1447,
    "prompt_tokens_details": { "cached_tokens": 0 },
    "completion_tokens_details": { "reasoning_tokens": 18 },
    "cost": 0.0001627
  },
  "cost": {
    "v": 1,
    "amount_usd": 0.0001627,
    "basis": "billed",
    "units": 1447,
    "unit": "token",
    "provider": "openrouter",
    "model": "openai/gpt-6-luna-pro",
    "usage_record_id": "6ac9dfbf705ad8633a87dfc4"
  },
  "provider": "…"
}

model and provider are trimmed above: they identify the model that served the request and its serving endpoint (see Radient Automatic).

#Request

POST /v1/chat/completions accepts the standard OpenAI chat parameters:

FieldTypeNotes
modelstring"auto" (recommended) or a model id from GET /v1/models
messagesarray{role, content} objects; role is system, user, assistant or tool; content is a string or a list of content parts (text, image_url, …)
max_tokens / max_completion_tokensintegerOutput cap
temperature, top_p, frequency_penalty, presence_penaltynumberSampling controls
stop, n, seed, logprobs, top_logprobs, logit_bias—As per the OpenAI API
response_formatobjecte.g. {"type": "json_object"}
streambooleanSSE streaming — see below
stream_optionsobject{"include_usage": true} adds a final usage frame
tools, tool_choice, parallel_tool_calls—Function calling — see below
reasoning_effort / reasoningstring / object"auto" is a Radient-defined special value; other values pass through — see Radient Automatic

Notes:

  • There is no server-side range checking; invalid values are forwarded to the serving model and fail there.
  • Unknown fields are ignored.
  • POST /v1/completions (the legacy text-completion endpoint) is also available. With model: "auto" it always uses the default model — the router has no chat content to classify — so prefer the chat endpoint.

#Response

FieldMeaning
id, object, createdRequest metadata (object is chat.completion)
modelThe model that served the request
providerThe serving endpoint
choices[]{index, message: {role, content, …}, finish_reason}; finish_reason is stop, length, tool_calls, …
usageprompt_tokens, completion_tokens, total_tokens, optional prompt_tokens_details.cached_tokens and completion_tokens_details, and cost in USD
costThe versioned cost object for this call — the amount deducted from your balance, with the usage-record id it lands on. See Cost reporting.

The cost object states what the call was charged; usage.cost mirrors the same figure. Some serving models add their own fields inside message (for example reasoning text); treat unknown fields as informational.

#Streaming

Set "stream": true to receive Server-Sent Events:

bash
curl -N https://api.radienthq.com/v1/chat/completions \
  -H "Authorization: Bearer $RADIENT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "auto",
    "stream": true,
    "stream_options": { "include_usage": true },
    "max_tokens": 16,
    "messages": [{ "role": "user", "content": "Say pong" }]
  }'

Each event is a chat.completion.chunk; the stream ends with data: [DONE]:

text
data: {"id":"gen-…","object":"chat.completion.chunk","created":…,"model":"…","choices":[{"index":0,"delta":{"content":"pong","role":"assistant"},"finish_reason":null}]}

data: {"id":"gen-…","object":"chat.completion.chunk","created":…,"model":"…","choices":[{"index":0,"delta":{"content":""},"finish_reason":"stop"}],"usage":{"prompt_tokens":1407,"completion_tokens":54,"total_tokens":1461,"cost":0.0001677,…},"cost":{"v":1,"amount_usd":0.0001677,"basis":"billed","units":1461,"unit":"token","provider":"openrouter","model":"openai/gpt-6-luna-pro","usage_record_id":"6aca94d457c97c7ea474387c"}}

data: [DONE]

(Trimmed. Chunks carry model, provider and other metadata on each frame; the last frame before [DONE] carries usage — and the cost object — when the stream reports usage.)

Behaviour worth knowing:

  • The usage chunk arrives only if include_usage is requested — or when the route always reports usage, as auto does today. The billed amount is in the cost object on the last usage frame (earlier frames state their own running figures). A frame that states no figure and has no platform rate to derive one from is forwarded as-is and carries no object, and a stream that reports no usage frame carries no object anywhere — reconcile either through the usage surface. Billing happens regardless. See Cost reporting.
  • Streaming is subject to a 5-minute server-side cap per request; long generations should chunk their work.
  • The 200 text/event-stream status is sent before the serving model is contacted. A failure after that point cannot change the status: the client sees an empty or truncated stream. Validate content and watch for a missing [DONE].
  • Accept: text/event-stream is not required.

#Tool calls (function calling)

tools with a tool_choice works on chat completions (including auto). When the model decides to call a function, finish_reason is tool_calls and message.tool_calls lists the calls; return the result as a role: "tool" message with tool_call_id, then call again.

json
{
  "choices": [
    {
      "index": 0,
      "message": {
        "role": "assistant",
        "content": null,
        "tool_calls": [
          {
            "id": "call_…",
            "type": "function",
            "function": { "name": "get_weather", "arguments": "{\"city\":\"Paris\"}" }
          }
        ]
      },
      "finish_reason": "tool_calls"
    }
  ]
}

(Trimmed.) arguments is a JSON string — parse it before use.

#Python example

python
import requests

RADIENT_API_KEY = "YOUR_RADIENT_API_KEY"
RADIENT_BASE_URL = "https://api.radienthq.com/v1"

headers = {
    "Authorization": f"Bearer {RADIENT_API_KEY}",
    "Content-Type": "application/json",
}

payload = {
    "model": "auto",
    "messages": [
        {"role": "system", "content": "You are a witty assistant that loves to tell jokes."},
        {"role": "user", "content": "Tell me a joke about programming."},
    ],
    "temperature": 0.7,
    "max_tokens": 150,
}

response = requests.post(f"{RADIENT_BASE_URL}/chat/completions", headers=headers, json=payload)
response.raise_for_status()
completion_data = response.json()

print("Assistant:", completion_data["choices"][0]["message"]["content"])
print("Cost (USD):", completion_data["cost"]["amount_usd"])

#Errors

StatusBodyCause
400{"error":"Invalid request format"}The body is not valid JSON
401{"error":"missing Authorization header"} (no credential) · invalid API key format · invalid API key · API key is not a Radient keyCredential problems — see Authentication
402{"error":"insufficient credits"}The credit gate refused the call — see the credit gate
500{"error":"Failed to process chat completions request"}Every serving failure — unknown model, empty messages, upstream errors — is flattened into this one response. The upstream's own message is logged, not returned.

There is no request-rate limit on this route; it is bounded only by the credit gate and by the serving model's own limits. The API does not emit 429s here. When retrying, inspect the error body rather than assuming a rate limit.

#Billing

Each call's charge is stated in the response's cost object — the amount deducted from your Radient Pass balance, at the serving model's own rate with no markup. On chat, usage.cost mirrors the same figure. A failed call records a zero-cost usage entry, so failures do not consume credits. See Cost reporting.

#Managing conversation history

Include previous turns in messages — the API is stateless:

python
payload = {
    "model": "auto",
    "messages": [
        {"role": "system", "content": "You are a helpful assistant."},
        {"role": "user", "content": "What is the capital of France?"},
        {"role": "assistant", "content": "The capital of France is Paris."},
        {"role": "user", "content": "What is it famous for?"},
    ],
}

See also: Radient Automatic · Embeddings API · Usage and credits API · API Reference.