Radium API

How to call Radium directly. Authentication, models, environments, tool calling, and the errors you'll actually hit.

API quickstart

Call the Radium API. Anthropic-compatible Messages endpoint, authentication, model names, production and staging base URLs, and OpenAI-compatible Chat Completions.

Quickstart

Radium serves an Anthropic-compatible Messages API. If your application already speaks that shape, or you use Anthropic-style tool calling, or you run Claude Code, this is the endpoint you want and the change is a base URL and a model name.

An OpenAI-compatible Chat Completions endpoint is available as well, and it is covered further down for applications that expect it.

Your first request

Set your key once:

export RADIUM_API_KEY="YOUR_RADIUM_API_KEY"

Then send this:

curl -s https://api.radium.cloud/v1/messages \
  -H "content-type: application/json" \
  -H "anthropic-version: 2023-06-01" \
  -H "x-api-key: $RADIUM_API_KEY" \
  -d '{
    "model": "hal-1.0",
    "max_tokens": 2048,
    "messages": [
      { "role": "user", "content": "Say only: radium hal connected." }
    ]
  }'

That is the whole integration. Everything below is detail.

Authentication

Every request needs a key. The default header is x-api-key:

x-api-key: $RADIUM_API_KEY

Some deployments use a bearer token instead:

Authorization: Bearer $RADIUM_API_KEY

Use the mode Radium supplied with your key. If nobody specified one, start with x-api-key and you will almost certainly be right.

Models

Model Built for
hal-1.0 Higher-capability coding and agentic work. Used in the examples on this page.
clarke-1.0 General-purpose and structured work
tycho-1.0 Faster, lighter-weight tasks

Swap the identifier in the request body, or in your Claude Code configuration, and nothing else changes.

The Messages API

Base URL:

https://api.radium.cloud

Full endpoint:

POST https://api.radium.cloud/v1/messages

The request body is the standard Anthropic Messages shape.

curl

curl -s https://api.radium.cloud/v1/messages \
  -H "content-type: application/json" \
  -H "anthropic-version: 2023-06-01" \
  -H "x-api-key: $RADIUM_API_KEY" \
  -d '{
    "model": "hal-1.0",
    "max_tokens": 2048,
    "messages": [
      { "role": "user", "content": "Hello, Radium!" }
    ]
  }'

Python

import anthropic

client = anthropic.Anthropic(
    api_key="YOUR_RADIUM_API_KEY",
    base_url="https://api.radium.cloud",
)

message = client.messages.create(
    model="hal-1.0",
    max_tokens=1024,
    messages=[
        {"role": "user", "content": "Hello, Radium!"}
    ],
)

print(message.content[0].text)

TypeScript

import Anthropic from "@anthropic-ai/sdk";

const client = new Anthropic({
  apiKey: "YOUR_RADIUM_API_KEY",
  baseURL: "https://api.radium.cloud",
});

const message: Anthropic.Message = await client.messages.create({
  model: "hal-1.0",
  max_tokens: 1024,
  messages: [{ role: "user", content: "Hello, Radium!" }],
});

console.log(message.content[0].text);

Tool calling works through the same endpoint, and it has its own page. See tool calling.

Production and staging

Messages API base URLs

Environment Base URL Endpoint
Production https://api.radium.cloud POST /v1/messages
Staging https://stage.api.radium.cloud POST /v1/messages

Credentials do not cross over Staging needs staging credentials. A production key will not authenticate against the staging endpoint, and that is deliberate.

Dedicated deployments

Organisations running on a dedicated Radium deployment use the host supplied to them, and every endpoint pattern on this page applies unchanged. If you need one, talk to us.

OpenAI-compatible Chat Completions

Use this only when your application expects an OpenAI-compatible Chat Completions API. Anthropic-compatible clients should use POST /v1/messages above.

The base URL for this path includes /v1:

https://api.radium.cloud/v1
curl -s https://api.radium.cloud/v1/chat/completions \
  -H "content-type: application/json" \
  -H "x-api-key: $RADIUM_API_KEY" \
  -d '{
    "model": "hal-1.0",
    "max_tokens": 2048,
    "temperature": 0,
    "messages": [
      { "role": "user", "content": "Hello, Radium!" }
    ]
  }'

Bearer authentication works here too, and the model identifiers are the same three.

Every endpoint

Endpoint summary

Use case Method Endpoint
Messages, production POST https://api.radium.cloud/v1/messages
Messages, staging POST https://stage.api.radium.cloud/v1/messages
Chat Completions, production POST https://api.radium.cloud/v1/chat/completions
Chat Completions, staging POST https://stage.api.radium.cloud/v1/chat/completions

Claude Code

Claude Code points at the Anthropic-compatible base URL and adds the request path itself, so configure it with the base URL alone:

export ANTHROPIC_BASE_URL="https://api.radium.cloud"
export ANTHROPIC_MODEL="hal-1.0"
export ANTHROPIC_API_KEY="$RADIUM_API_KEY"

Check it:

claude --print --model hal-1.0 "Say only: radium hal connected."

The one that catches everybody Do not put /v1/messages into ANTHROPIC_BASE_URL. Claude Code appends it, and a base URL with the path already on it returns a 404 on every request.

The full setup, including the scripted install, model selection, and troubleshooting, is on Run Claude Code on Radium.

Next

Tool calling and MCP

Anthropic-compatible tool calling on the Radium Messages API, with the full tool_use and tool_result round trip, and where MCP fits alongside it.

Tool calling and MCP

Radium supports Anthropic-compatible tool calling on the Messages API. MCP is handled by the client application, and when that client is pointed at Radium it can expose MCP-provided tools to the model through the ordinary tool-calling flow.

These two things arrive together in most conversations, and they sit at different levels of the stack, so this page covers tool calling first and then places MCP against it.

Two different layers

Tool calling — API feature Your client sends tool definitions with the request, the model returns a tool_use block asking for one, your client runs it, and your client sends the output back as tool_result. This happens between your application and Radium.

MCP — client-side protocol The Model Context Protocol connects an application such as Claude Code to external tool servers. Those servers expose tools, and the client decides how to present them to the model. This happens on your side, before any request reaches Radium.

┌─────────────────────── runs on your side ──────────────────────────┐
│                                                                    │
│   ┌────────────────┐        MCP         ┌─────────────────────┐    │
│   │   MCP server    │◄─────────────────►│     Your client     │    │
│   │ yours, exposing │                   │  application or     │    │
│   │      tools      │                   │    Claude Code      │    │
│   └────────────────┘                    └──────────┬──────────┘    │
│                                                    │               │
└────────────────────────────────────────────────────┼───────────────┘
                                                     │  tools
                                                     │  tool_use
                                                     │  tool_result
                                                     ▼
                                         ┌─────────────────────┐
                                         │       Radium        │
                                         │  POST /v1/messages  │
                                         └─────────────────────┘

MCP runs horizontally, on your infrastructure, between your client and your tool servers. Tool calling runs vertically, between your client and Radium. Radium answers the model half and never talks to your MCP server.

What is supported

All of it on the same endpoint you are already calling.

The round trip

Three turns. Your client does two of them.

Turn one — send the request with your tool definitions

curl -s https://api.radium.cloud/v1/messages \
  -H "content-type: application/json" \
  -H "anthropic-version: 2023-06-01" \
  -H "x-api-key: $RADIUM_API_KEY" \
  -d '{
    "model": "hal-1.0",
    "max_tokens": 2048,
    "tools": [
      {
        "name": "get_weather",
        "description": "Get current weather for a city",
        "input_schema": {
          "type": "object",
          "properties": {
            "city": { "type": "string" }
          },
          "required": ["city"]
        }
      }
    ],
    "messages": [
      { "role": "user", "content": "What is the weather in Tokyo?" }
    ]
  }'

Turn two — the model asks for the tool

If it decides to call get_weather, the response carries a tool_use block:

{
  "type": "tool_use",
  "id": "toolu_...",
  "name": "get_weather",
  "input": {
    "city": "Tokyo"
  }
}

Radium has no idea what get_weather does and does not run it. That part is yours.

Turn three — run the tool and send the output back

Append the assistant turn containing the tool_use block, then a user turn containing the matching tool_result:

curl -s https://api.radium.cloud/v1/messages \
  -H "content-type: application/json" \
  -H "anthropic-version: 2023-06-01" \
  -H "x-api-key: $RADIUM_API_KEY" \
  -d '{
    "model": "hal-1.0",
    "max_tokens": 2048,
    "tools": [
      {
        "name": "get_weather",
        "description": "Get current weather for a city",
        "input_schema": {
          "type": "object",
          "properties": {
            "city": { "type": "string" }
          },
          "required": ["city"]
        }
      }
    ],
    "messages": [
      { "role": "user", "content": "What is the weather in Tokyo?" },
      {
        "role": "assistant",
        "content": [
          {
            "type": "tool_use",
            "id": "toolu_123",
            "name": "get_weather",
            "input": { "city": "Tokyo" }
          }
        ]
      },
      {
        "role": "user",
        "content": [
          {
            "type": "tool_result",
            "tool_use_id": "toolu_123",
            "content": "Tokyo is 24 C and clear."
          }
        ]
      }
    ]
  }'

The one to get right The tool_use_id on your result has to match the id the model issued. Send the tool definitions again with the follow-up, because the conversation is stateless and the model needs them on every turn.

The loop repeats for as long as the model keeps asking.

Several tools at once

Put as many definitions in the tools array as the work needs, and the model picks. Each one needs a name, a description the model can reason about, and an input_schema. The description carries more weight than people expect, because it is the only thing telling the model when a tool applies.

Streaming

Streaming works with tools on the same endpoint, so an agent loop can render output while it runs. Behaviour under streaming is worth checking against your own client before you depend on it, since every framework assembles the stream a little differently.

Where MCP sits

There is no separate Radium MCP endpoint to call, and there is nothing to configure on our side. MCP servers run on your infrastructure, your client connects to them and discovers what they expose, and the resulting tool definitions travel to Radium through the Messages API as ordinary tools.

From the model's position, a tool that arrived over MCP and a tool you hard-coded look the same. That is the point of the design, and it is why MCP support is a property of your client rather than a property of your inference provider.

MCP with Claude Code

Claude Code connects to MCP servers, discovers their tools, and passes the definitions through the model API. Radium answers the model half of that exchange. So:

Before production

Every MCP server exposes its own schemas and its own permissions, and models differ in how they handle an unfamiliar tool surface. Run a small smoke test of the specific workflow you intend to rely on, with the model you intend to use, before you put it in front of anyone.

Compatibility gets the request through. The smoke test tells you it works.

Next