Compatible APIs
Call Runware with the OpenAI, Anthropic and TypeSafe request formats. Point an existing SDK at Runware by changing the base URL and the API key.
Introduction
Besides its native API, Runware accepts requests in three other providers' formats. If your code already uses one of their SDKs, point it at Runware by changing two values: the base URL and the API key. Requests and responses keep the provider's format, so the provider's documentation stays the reference for every parameter.
| Endpoint | Format | Reference |
|---|---|---|
/v1/chat/completions | OpenAI Chat Completions | OpenAI API reference |
/v1/messages | Anthropic Messages | Claude API reference |
/v1/decisions | TypeSafe decisions | TypeSafe docs |
All three read your Runware API key from the Authorization: Bearer header, and take a Runware AIR ID in model. Each section below lists the models its endpoint serves.
OpenAI Chat Completions
https://api.runware.ai/v1/chat/completions takes the OpenAI Chat Completions format. If you already use the OpenAI SDK or any tool that speaks the OpenAI protocol, it works without Runware-specific parsing.
If you need access to Runware-specific features like taskUUID tracking, includeCost, or the async delivery method, use the native API instead. The OpenAI-compatible endpoint focuses on broad compatibility with the standard OpenAI request and response format.
Quick start
Send a standard chat completion request to https://api.runware.ai/v1/chat/completions using your Runware API key and a Runware model ID:
{
"model": "minimax:m2.7@0",
"messages": [
{ "role": "user", "content": "What is the capital of France?" }
],
"max_completion_tokens": 256
}The request format is identical to the OpenAI Chat Completions API. The only difference is that model uses a Runware AIR ID (e.g., minimax:m2.7@0, google:gemini@3.1-pro) instead of an OpenAI model name.
curl -X POST https://api.runware.ai/v1/chat/completions \
-H "Authorization: Bearer $RUNWARE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "minimax:m2.7@0",
"messages": [{"role": "user", "content": "What is the capital of France?"}],
"max_completion_tokens": 256
}'from openai import OpenAI
client = OpenAI(
api_key="your_runware_api_key",
base_url="https://api.runware.ai/v1",
)
response = client.chat.completions.create(
model="minimax:m2.7@0",
messages=[{"role": "user", "content": "What is the capital of France?"}],
max_completion_tokens=256,
)
print(response.choices[0].message.content)import OpenAI from 'openai';
const client = new OpenAI({
apiKey: 'your_runware_api_key',
baseURL: 'https://api.runware.ai/v1',
});
const response = await client.chat.completions.create({
model: 'minimax:m2.7@0',
messages: [{ role: 'user', content: 'What is the capital of France?' }],
max_completion_tokens: 256,
});
console.log(response.choices[0].message.content);Streaming
Set "stream": true to receive tokens as they are generated, exactly as you would against the OpenAI API. To include token counts at the end of the stream, add stream_options:
{
"model": "minimax:m2.7@0",
"stream": true,
"stream_options": { "include_usage": true },
"messages": [
{ "role": "user", "content": "Tell me a joke" }
],
"max_completion_tokens": 512
}The SSE response format is identical to OpenAI's. Content arrives in choices[0].delta.content, and the stream ends with data: [DONE].
Streaming with OpenAI SDKs
The OpenAI Python and TypeScript SDKs handle all SSE parsing for you:
from openai import OpenAI
client = OpenAI(
api_key="your_runware_api_key",
base_url="https://api.runware.ai/v1",
)
with client.chat.completions.stream(
model="minimax:m2.7@0",
messages=[{"role": "user", "content": "Tell me a joke"}],
max_tokens=512,
) as stream:
for text in stream.text_stream:
print(text, end="", flush=True)import OpenAI from 'openai';
const client = new OpenAI({
apiKey: 'your_runware_api_key',
baseURL: 'https://api.runware.ai/v1',
});
const stream = await client.chat.completions.create({
model: 'minimax:m2.7@0',
messages: [{ role: 'user', content: 'Tell me a joke' }],
max_tokens: 512,
stream: true,
});
for await (const chunk of stream) {
const content = chunk.choices[0]?.delta?.content;
if (content) process.stdout.write(content);
}curl -N -X POST https://api.runware.ai/v1/chat/completions \
-H "Authorization: Bearer $RUNWARE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "minimax:m2.7@0",
"stream": true,
"stream_options": {"include_usage": true},
"messages": [{"role": "user", "content": "Tell me a joke"}],
"max_completion_tokens": 512
}'Reasoning models
Models with internal reasoning stream those tokens in choices[0].delta.reasoning_content before the final response appears in choices[0].delta.content, which is the same pattern OpenAI's reasoning models follow.
// First chunk - role assignment
data: {"id":"chatcmpl-e36b09e6-7a1c-4d8f-b5e2-9c4a3f6d8e1b","object":"chat.completion.chunk","model":"minimax:m2.7@0","choices":[{"index":0,"delta":{"role":"assistant"},"finish_reason":null}]}
// Reasoning chunks - choices[0].delta.reasoning_content
data: {"id":"chatcmpl-e36b09e6-7a1c-4d8f-b5e2-9c4a3f6d8e1b","object":"chat.completion.chunk","choices":[{"index":0,"delta":{"reasoning_content":"The user asks 2+2. Simple arithmetic."},"finish_reason":null}]}
// Actual response - switches to choices[0].delta.content
data: {"id":"chatcmpl-e36b09e6-7a1c-4d8f-b5e2-9c4a3f6d8e1b","object":"chat.completion.chunk","choices":[{"index":0,"delta":{"content":"4"},"finish_reason":null}]}
// Usage chunk (when stream_options.include_usage is set)
data: {"id":"chatcmpl-e36b09e6-7a1c-4d8f-b5e2-9c4a3f6d8e1b","object":"chat.completion.chunk","choices":[],"usage":{"prompt_tokens":51,"completion_tokens":38,"total_tokens":89,"cost":0.000134}}
// Final chunk - finish reason
data: {"id":"chatcmpl-e36b09e6-7a1c-4d8f-b5e2-9c4a3f6d8e1b","object":"chat.completion.chunk","choices":[{"index":0,"delta":{},"finish_reason":"stop"}]}
data: [DONE]Key differences from OpenAI
While the endpoint is fully compatible with the OpenAI protocol, there are a few things to be aware of:
| Aspect | OpenAI | Runware |
|---|---|---|
| Model IDs | gpt-4o, gpt-4o-mini | AIR format: minimax:m2.7@0, google:gemini@3.1-pro |
| Authentication | OpenAI API key | Runware API key (same Authorization: Bearer header) |
| Base URL | https://api.openai.com/v1 | https://api.runware.ai/v1 |
| Available models | OpenAI models only | Multiple providers: MiniMax, Google Gemini, and more |
| Naming convention | snake_case (finish_reason, reasoning_content) | snake_case (same as OpenAI on this endpoint) |
This endpoint uses snake_case field names (finish_reason, max_tokens) to match the OpenAI convention. The native API uses camelCase (finishReason, maxTokens).
Key differences from the native API
If you are choosing between the OpenAI-compatible endpoint and the native Runware API, here is how they compare:
| Native API | OpenAI-compatible | |
|---|---|---|
| Endpoint | https://api.runware.ai/v1 | https://api.runware.ai/v1/chat/completions |
| Request format | Array of task objects with taskType and taskUUID | Single object (standard OpenAI format) |
| Streaming trigger | "deliveryMethod": "stream" | "stream": true |
| Async support | Yes ("deliveryMethod": "async" with webhooks/polling) | No |
| Cost tracking | includeCost: true on the request | Included in the usage chunk when stream_options.include_usage is set |
| Usage tracking | includeUsage: true on the request | stream_options: { "include_usage": true } |
| Task tracking | taskUUID for request/response correlation | Standard id field on response chunks |
| Naming convention | camelCase | snake_case |
Use the OpenAI-compatible endpoint when you want the fastest integration path or are already working with the OpenAI SDK.
Use the native API when you want a consistent request format across all Runware modalities (images, video, audio, text, 3d) and access to features like async delivery and task-level tracking.
Models
| Model | Model ID |
|---|---|
| Claude Fable 5 | anthropic:claude@fable-5 |
| Claude Fable 5.1 | anthropic:claude@fable-5.1 |
| Claude Haiku 4.5 | anthropic:claude@haiku-4.5 |
| Claude Opus 4.7 | anthropic:claude@opus-4.7 |
| Claude Opus 4.8 | anthropic:claude@opus-4.8 |
| Claude Opus 5 | anthropic:claude@opus-5 |
| Claude Opus 5.5 | anthropic:claude@opus-5.5 |
| Claude Sonnet 4.6 | anthropic:claude@sonnet-4.6 |
| Claude Sonnet 5 | anthropic:claude@sonnet-5 |
| Claude Sonnet 5.5 | anthropic:claude@sonnet-5.5 |
| DeepSeek-V4-Flash-0731 | deepseek:v4@flash |
| DeepSeek-V4-Pro-0423 | deepseek:v4@pro |
| DeepSeek-V4.1-Flash | deepseek:v4.1@flash |
| Gemini 3 Flash | google:gemini@3-flash |
| Gemini 3.1 Flash Lite | google:gemini@3.1-flash-lite |
| Gemini 3.1 Pro | google:gemini@3.1-pro |
| Gemini 3.5 Flash | google:gemini@3.5-flash |
| Gemini 3.5 Flash-Lite | google:gemini@3.5-flash-lite |
| Gemini 3.6 Flash | google:gemini@3.6-flash |
| Gemini 3.7 Flash | google:gemini@3.7-flash |
| Gemini 3.8 Flash | google:gemini@3.8-flash |
| Gemma 4 31B | google:gemma@4-31b |
| GLM-5.1 | zai:glm@5.1 |
| GLM-5.2 | zai:glm@5.2 |
| GLM-5.3 | zai:glm@5.3 |
| GLM-5.3-Flash | zai:glm@5.3-flash |
| GPT-5 Mini | openai:gpt@5-mini |
| GPT-5 Nano | openai:gpt@5-nano |
| GPT-5.4 | openai:gpt@5.4 |
| GPT-5.4 Mini | openai:gpt@5.4-mini |
| GPT-5.4 Nano | openai:gpt@5.4-nano |
| GPT-5.4 Pro | openai:gpt@5.4-pro |
| GPT-5.5 | openai:gpt@5.5 |
| GPT-5.6 Luna | openai:gpt@5.6-luna |
| GPT-5.6 Sol | openai:gpt@5.6-sol |
| GPT-5.6 Terra | openai:gpt@5.6-terra |
| GPT-6 Astra | openai:gpt@6-astra |
| GPT-6 Luna | openai:gpt@6-luna |
| GPT-6 Sol | openai:gpt@6-sol |
| GPT-6.1 Sol | openai:gpt@6.1-sol |
| gpt-oss-120b | openai:gpt-oss@120b |
| gpt-oss-safeguard-20b | openai:gpt-oss-safeguard@20b |
| Grok 4.3 | xai:grok@4.3 |
| Grok 4.7 | xai:grok@4.7 |
| Kimi K2.6 | moonshotai:kimi@k2.6 |
| Kimi K3 | moonshotai:kimi@k3 |
| MiniMax M2.7 | minimax:m2.7@0 |
| MiniMax M2.7 Highspeed | minimax:m2.7@highspeed |
| MiniMax M3 | minimax:m3@0 |
| Shieldstral 1.0 3B | mistralai:shieldstral@1.0-3b |
Anthropic Messages
https://api.runware.ai/v1/messages takes the Anthropic Messages format. The request body reaches Anthropic unchanged, so every Messages parameter works as documented, including thinking, prompt caching, tool use and vision. With "stream": true, the response streams Anthropic's own server-sent events.
The Anthropic SDKs send the API key in an x-api-key header by default. Runware reads it from Authorization: Bearer, so pass your Runware API key as auth_token in Python or authToken in TypeScript, and set the base URL to https://api.runware.ai.
curl -X POST https://api.runware.ai/v1/messages \
-H "Authorization: Bearer $RUNWARE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "anthropic:claude@opus-5.5",
"max_tokens": 1024,
"messages": [{"role": "user", "content": "What is the capital of France?"}]
}'from anthropic import Anthropic
client = Anthropic(
auth_token="your_runware_api_key",
base_url="https://api.runware.ai",
)
message = client.messages.create(
model="anthropic:claude@opus-5.5",
max_tokens=1024,
messages=[{"role": "user", "content": "What is the capital of France?"}],
)
print(message.content[0].text)import Anthropic from '@anthropic-ai/sdk';
const client = new Anthropic({
authToken: 'your_runware_api_key',
baseURL: 'https://api.runware.ai',
});
const message = await client.messages.create({
model: 'anthropic:claude@opus-5.5',
max_tokens: 1024,
messages: [{ role: 'user', content: 'What is the capital of France?' }],
});
console.log(message.content[0].text);Besides the AIR ID, model accepts the Runware model ID (anthropic-claude-opus-5-5) and Anthropic's own model name (claude-opus-5-5).
Models
| Model | Model ID |
|---|---|
| Claude Fable 5 | anthropic:claude@fable-5 |
| Claude Fable 5.1 | anthropic:claude@fable-5.1 |
| Claude Haiku 4.5 | anthropic:claude@haiku-4.5 |
| Claude Opus 4.7 | anthropic:claude@opus-4.7 |
| Claude Opus 4.8 | anthropic:claude@opus-4.8 |
| Claude Opus 5 | anthropic:claude@opus-5 |
| Claude Opus 5.5 | anthropic:claude@opus-5.5 |
| Claude Sonnet 4.6 | anthropic:claude@sonnet-4.6 |
| Claude Sonnet 5 | anthropic:claude@sonnet-5 |
| Claude Sonnet 5.5 | anthropic:claude@sonnet-5.5 |
Decisions
https://api.runware.ai/v1/decisions takes the TypeSafe decisions format. Instead of generating text, a decision model reads a state and answers a set of typed questions with probabilities and a confidence. The TypeSafe docs describe the question types.
The TypeSafe SDKs work by pointing the base URL at https://api.runware.ai with your Runware API key. Set model on every request, because the SDK's own default is not a Runware model ID.
curl -X POST https://api.runware.ai/v1/decisions \
-H "Authorization: Bearer $RUNWARE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "typesafe:jev@1",
"state": "I was charged twice. Please fix this ASAP.",
"questions": {
"category": {
"type": "choice",
"instructions": "What is this ticket about?",
"criteria": {"billing": null, "technical": null, "other": null}
}
}
}'from typesafe_sdk import Choice, TypeSafeClient
client = TypeSafeClient(
api_key="your_runware_api_key",
base_url="https://api.runware.ai",
)
response = client.system_one(
model="typesafe:jev@1",
state={"document": "I was charged twice. Please fix this ASAP."},
questions={
"category": Choice(
instructions="What is this ticket about?",
criteria={"billing": None, "technical": None, "other": None},
),
},
)
print(response.answers["category"].choice)import { choice, TypeSafeClient } from '@typesafe-ai/sdk';
const client = new TypeSafeClient({
apiKey: 'your_runware_api_key',
baseURL: 'https://api.runware.ai',
});
const response = await client.systemOne({
model: 'typesafe:jev@1',
state: { document: 'I was charged twice. Please fix this ASAP.' },
questions: {
category: choice('What is this ticket about?', {
billing: null,
technical: null,
other: null,
}),
},
});
console.log(response.answers.category.choice);Each answer arrives under answers, keyed by the question's name.
Models
| Model | Model ID |
|---|---|
| Jev | typesafe:jev@1 |
| Laya | runware:laya@1 |