---
title: Compatible APIs | Runware Docs
url: https://runware.ai/docs/tools/compatible-apis
description: 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.
relatedDocuments:
  - https://runware.ai/docs/models-api/streaming
  - https://runware.ai/docs/models-api/authentication
  - https://runware.ai/docs/models-api/introduction
---
## 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 Chat Completions | [OpenAI API reference](https://platform.openai.com/docs/api-reference/chat/create) |
| [`/v1/responses`](#openai-responses) | OpenAI Responses | [OpenAI API reference](https://platform.openai.com/docs/api-reference/responses/create) |
| [`/v1/messages`](#anthropic-messages) | Anthropic Messages | [Claude API reference](https://platform.claude.com/docs/en/api/messages) |
| [`/v1/decisions`](#decisions) | TypeSafe decisions | [TypeSafe docs](https://docs.typesafe.ai/) |

Every endpoint reads your Runware API key from the `Authorization: Bearer` header, and takes 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.

> [!NOTE]
> If you need access to Runware-specific features like `taskUUID` tracking, `includeCost`, or the `async` delivery method, use the [native API](https://runware.ai/docs/models-api/streaming) 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:

```json
{
  "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](https://platform.openai.com/docs/api-reference/chat/create). 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**:

```bash
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
  }'
```

**Python**:

```python
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)
```

**TypeScript**:

```typescript
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`:

```json
{
  "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:

**Python**:

```python
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)
```

**TypeScript**:

```typescript
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**:

```bash
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.

```text
// 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]
```

### Tool calling

Pass your **function definitions** in `tools` and steer the choice with `tool_choice`, as in the OpenAI format. The calls arrive in `choices[0].message.tool_calls`, and you send each result back in a `tool` message that carries the matching `tool_call_id`.

> [!WARNING]
> Some OpenAI reasoning models reject function tools on this endpoint unless `reasoning_effort` is `none`, and not all of them accept that value. For tool calling with those models, use [`/v1/responses`](#openai-responses).

### 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) |

> [!NOTE]
> This endpoint uses **snake\_case** field names (`finish_reason`, `max_tokens`) to match the OpenAI convention. The [native API](https://runware.ai/docs/models-api/streaming) 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](https://runware.ai/docs/models/anthropic-claude-fable-5) | `anthropic:claude@fable-5` |
| Claude Fable 5.1 | `anthropic:claude@fable-5.1` |
| [Claude Haiku 4.5](https://runware.ai/docs/models/anthropic-claude-haiku-4-5) | `anthropic:claude@haiku-4.5` |
| Claude Haiku 5.5 | `anthropic:claude@haiku-5.5` |
| [Claude Opus 4.7](https://runware.ai/docs/models/anthropic-claude-opus-4-7) | `anthropic:claude@opus-4.7` |
| [Claude Opus 4.8](https://runware.ai/docs/models/anthropic-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](https://runware.ai/docs/models/anthropic-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](https://runware.ai/docs/models/google-gemini-3-flash) | `google:gemini@3-flash` |
| [Gemini 3.1 Flash Lite](https://runware.ai/docs/models/google-gemini-3-1-flash-lite) | `google:gemini@3.1-flash-lite` |
| [Gemini 3.1 Pro](https://runware.ai/docs/models/google-gemini-3-1-pro) | `google:gemini@3.1-pro` |
| [Gemini 3.5 Flash](https://runware.ai/docs/models/google-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](https://runware.ai/docs/models/google-gemma-4-31b) | `google:gemma@4-31b` |
| [GLM-5.1](https://runware.ai/docs/models/zai-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.4](https://runware.ai/docs/models/openai-gpt-5-4) | `openai:gpt@5.4` |
| [GPT-5.4 Mini](https://runware.ai/docs/models/openai-gpt-5-4-mini) | `openai:gpt@5.4-mini` |
| [GPT-5.4 Nano](https://runware.ai/docs/models/openai-gpt-5-4-nano) | `openai:gpt@5.4-nano` |
| [GPT-5.4 Pro](https://runware.ai/docs/models/openai-gpt-5-4-pro) | `openai:gpt@5.4-pro` |
| [GPT-5.5](https://runware.ai/docs/models/openai-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](https://runware.ai/docs/models/minimax-m2-7) | `minimax:m2.7@0` |
| [MiniMax M2.7 Highspeed](https://runware.ai/docs/models/minimax-m2-7-highspeed) | `minimax:m2.7@highspeed` |
| [MiniMax M3](https://runware.ai/docs/models/minimax-m3) | `minimax:m3@0` |
| Shieldstral 1.0 3B | `mistralai:shieldstral@1.0-3b` |

## OpenAI Responses

`https://api.runware.ai/v1/responses` takes the **OpenAI Responses format**. The request body reaches OpenAI unchanged, so function calling, structured outputs, image input and reasoning settings work as documented. With `"stream": true`, the response streams OpenAI's own server-sent events.

The OpenAI SDKs reach it through `client.responses`, with the same base URL and API key as Chat Completions.

**cURL**:

```bash
curl -X POST https://api.runware.ai/v1/responses \
  -H "Authorization: Bearer $RUNWARE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "openai:gpt@5.4-mini",
    "input": "What is the capital of France?",
    "max_output_tokens": 256
  }'
```

**Python**:

```python
from openai import OpenAI

client = OpenAI(
    api_key="your_runware_api_key",
    base_url="https://api.runware.ai/v1",
)

response = client.responses.create(
    model="openai:gpt@5.4-mini",
    input="What is the capital of France?",
    max_output_tokens=256,
)

print(response.output_text)
```

**TypeScript**:

```typescript
import OpenAI from 'openai';

const client = new OpenAI({
  apiKey: 'your_runware_api_key',
  baseURL: 'https://api.runware.ai/v1',
});

const response = await client.responses.create({
  model: 'openai:gpt@5.4-mini',
  input: 'What is the capital of France?',
  max_output_tokens: 256,
});

console.log(response.output_text);
```

Besides the AIR ID, `model` accepts the Runware model ID (`openai-gpt-5-4-mini`) and OpenAI's own model name (`gpt-5.4-mini`).

### Conversation state

**Each request stands alone**, and `previous_response_id` is not supported. To continue a conversation, send the earlier turns in `input` together with the new one. A function call works the same way: return the model's `function_call` item and your `function_call_output` as input items.

```json
{
  "model": "openai:gpt@5.4-mini",
  "input": [
    { "role": "user", "content": "What is the weather in Paris?" },
    {
      "type": "function_call",
      "call_id": "call_jvhN2xFwUysKw8YmcMT2xW71",
      "name": "get_weather",
      "arguments": "{\"city\":\"Paris\"}"
    },
    {
      "type": "function_call_output",
      "call_id": "call_jvhN2xFwUysKw8YmcMT2xW71",
      "output": "{\"temperature_c\":18,\"conditions\":\"light rain\"}"
    }
  ],
  "tools": [
    {
      "type": "function",
      "name": "get_weather",
      "description": "Get the current weather for a city.",
      "parameters": {
        "type": "object",
        "properties": { "city": { "type": "string" } },
        "required": ["city"]
      }
    }
  ]
}
```

### Models

| Model | Model ID |
| --- | --- |
| [GPT-5.4](https://runware.ai/docs/models/openai-gpt-5-4) | `openai:gpt@5.4` |
| [GPT-5.4 Mini](https://runware.ai/docs/models/openai-gpt-5-4-mini) | `openai:gpt@5.4-mini` |
| [GPT-5.4 Nano](https://runware.ai/docs/models/openai-gpt-5-4-nano) | `openai:gpt@5.4-nano` |
| [GPT-5.5](https://runware.ai/docs/models/openai-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` |

## 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**:

```bash
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?"}]
  }'
```

**Python**:

```python
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)
```

**TypeScript**:

```typescript
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](https://runware.ai/docs/models/anthropic-claude-fable-5) | `anthropic:claude@fable-5` |
| Claude Fable 5.1 | `anthropic:claude@fable-5.1` |
| [Claude Haiku 4.5](https://runware.ai/docs/models/anthropic-claude-haiku-4-5) | `anthropic:claude@haiku-4.5` |
| Claude Haiku 5.5 | `anthropic:claude@haiku-5.5` |
| [Claude Opus 4.7](https://runware.ai/docs/models/anthropic-claude-opus-4-7) | `anthropic:claude@opus-4.7` |
| [Claude Opus 4.8](https://runware.ai/docs/models/anthropic-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](https://runware.ai/docs/models/anthropic-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](https://docs.typesafe.ai/primitives) 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**:

```bash
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}
      }
    }
  }'
```

**Python**:

```python
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)
```

**TypeScript**:

```typescript
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` |