---
title: Responses
---

# Responses

`POST /v1/responses`

Send input to a model and get one complete response. The Responses endpoint organizes both input and output as structured "items", which keeps function-calling and multimodal flows cleaner.

<Callout type="info">
  This endpoint is compatible with the OpenAI Responses SDK. If you already have a project on the OpenAI SDK, just point `base_url` at CrossModel and set `model` to a CrossModel model ID — nothing else needs to change.
</Callout>

## Endpoint

```http
POST https://api.crossmodel.ai/v1/responses
Authorization: Bearer cm-YOUR_KEY
Content-Type: application/json
```

Every request must carry a `Bearer` API key in the `Authorization` header.

**Create response**

```bash
curl https://api.crossmodel.ai/v1/responses \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $CROSSMODEL_API_KEY" \
  -d '{
    "model": "openai/gpt-5-mini",
    "instructions": "You are a helpful assistant.",
    "input": "Hello!"
  }'
```

```typescript
import OpenAI from "openai";

const client = new OpenAI({
  apiKey: process.env.CROSSMODEL_API_KEY,
  baseURL: "https://api.crossmodel.ai/v1",
});

const response = await client.responses.create({
  model: "openai/gpt-5-mini",
  instructions: "You are a helpful assistant.",
  input: "Hello!",
});

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

```python
import os
from openai import OpenAI

client = OpenAI(
    api_key=os.environ["CROSSMODEL_API_KEY"],
    base_url="https://api.crossmodel.ai/v1",
)

response = client.responses.create(
    model="openai/gpt-5-mini",
    instructions="You are a helpful assistant.",
    input="Hello!",
)

print(response.output_text)
```

**Stream response**

```bash
curl https://api.crossmodel.ai/v1/responses \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $CROSSMODEL_API_KEY" \
  -d '{
    "model": "openai/gpt-5-mini",
    "input": "Tell me a short story.",
    "stream": true
  }'
```

```typescript
import OpenAI from "openai";

const client = new OpenAI({
  apiKey: process.env.CROSSMODEL_API_KEY,
  baseURL: "https://api.crossmodel.ai/v1",
});

const stream = await client.responses.create({
  model: "openai/gpt-5-mini",
  input: "Tell me a short story.",
  stream: true,
});

for await (const event of stream) {
  if (event.type === "response.output_text.delta") {
    process.stdout.write(event.delta);
  }
}
```

```python
import os
from openai import OpenAI

client = OpenAI(
    api_key=os.environ["CROSSMODEL_API_KEY"],
    base_url="https://api.crossmodel.ai/v1",
)

stream = client.responses.create(
    model="openai/gpt-5-mini",
    input="Tell me a short story.",
    stream=True,
)

for event in stream:
    if event.type == "response.output_text.delta":
        print(event.delta, end="")
```

**Call a function**

```bash
curl https://api.crossmodel.ai/v1/responses \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $CROSSMODEL_API_KEY" \
  -d '{
    "model": "openai/gpt-5-mini",
    "input": "What is the weather in Shanghai?",
    "tools": [
      {
        "type": "function",
        "name": "get_weather",
        "parameters": {
          "type": "object",
          "properties": {
            "city": { "type": "string" }
          },
          "required": ["city"]
        }
      }
    ]
  }'
```

```typescript
import OpenAI from "openai";

const client = new OpenAI({
  apiKey: process.env.CROSSMODEL_API_KEY,
  baseURL: "https://api.crossmodel.ai/v1",
});

const response = await client.responses.create({
  model: "openai/gpt-5-mini",
  input: "What is the weather in Shanghai?",
  tools: [
    {
      type: "function",
      name: "get_weather",
      parameters: {
        type: "object",
        properties: { city: { type: "string" } },
        required: ["city"],
      },
    },
  ],
});
```

```python
import os
from openai import OpenAI

client = OpenAI(
    api_key=os.environ["CROSSMODEL_API_KEY"],
    base_url="https://api.crossmodel.ai/v1",
)

response = client.responses.create(
    model="openai/gpt-5-mini",
    input="What is the weather in Shanghai?",
    tools=[
        {
            "type": "function",
            "name": "get_weather",
            "parameters": {
                "type": "object",
                "properties": {"city": {"type": "string"}},
                "required": ["city"],
            },
        }
    ],
)
```

## Request parameters

| Parameter | Type | Required | Notes |
|------|------|------|------|
| `model` | string | Yes | The model ID to use, e.g. `openai/gpt-5-mini`. Call `/v1/models` for the full list. |
| `input` | string or array | No | The model input. Either a string, or an array of input items (see [Input items](#input-items)). |
| `instructions` | string | No | System-level instructions that set the model's overall behavior; prepended to the input at the highest priority. |
| `max_output_tokens` | integer | No | Max tokens to generate for this response. |
| `temperature` | number | No | Sampling temperature, typically `0`–`2`. Higher is more random and varied. |
| `top_p` | number | No | Nucleus-sampling threshold. Usually adjust either `temperature` or `top_p`, not both. |
| `tools` | array | No | The tools the model may call. See [Function tools](#function-tools) below. |
| `tool_choice` | string or object | No | Controls whether and how the model calls tools: `auto`, `none`, `required`, or an object naming a specific function. |
| `reasoning` | object | No | Reasoning config. `effort` controls how much reasoning the model spends before answering: `none`, `minimal`, `low`, `medium`, `high`, `xhigh`. The effect depends on whether the model is a reasoning model. |
| `safety_identifier` | string | No | A stable identifier for your end user, for safety and abuse detection. Pass a hashed user ID. |
| `metadata` | object | No | Custom key-value pairs attached to the request. |
| `stream` | boolean | No | Whether to stream the result. Default `false`. |
| `user` | string | No | Legacy alias for `safety_identifier`. When both are present, `safety_identifier` wins. |

## Input items

When `input` is a string, it's treated as one user message. When it's an array, each element is an input item with a `type` field:

| type | Fields | Notes |
|------|------|------|
| `message` | `role`, `content` | A message. `role` is `user`, `assistant`, `system`, or `developer`; `content` is a string or an array of content blocks. |
| `function_call` | `call_id`, `name`, `arguments` | A record of a function call. `arguments` is a JSON string. |
| `function_call_output` | `call_id`, `output` | The result of running a function; `call_id` points at the corresponding `function_call`. |

When a message's `content` is an array, these content blocks are supported:

| type | Fields | Notes |
|------|------|------|
| `input_text` | `text` | Text input. |
| `input_image` | `image_url`, `detail` | Image input. `image_url` can be a public image URL or a `data:image/...;base64,...` data URL. |
| `input_file` | `file_id` or `file_url` | File input; supported on some models only. |

## Function tools

Declare functions the model can call via the `tools` field. The model returns a structured call request when needed.

```json
{
  "tools": [
    {
      "type": "function",
      "name": "get_weather",
      "description": "Get current weather for a city.",
      "parameters": {
        "type": "object",
        "properties": {
          "city": { "type": "string" }
        },
        "required": ["city"]
      }
    }
  ]
}
```

| Field | Type | Required | Notes |
|------|------|------|------|
| `type` | string | Yes | Tool type; currently `function`. |
| `name` | string | Yes | The function name. |
| `description` | string | No | What the function does. A clear description helps the model decide when to call it. |
| `parameters` | object | No | JSON Schema for the function's parameters. |
| `strict` | boolean | No | Whether to require the model to generate arguments strictly matching the schema. |

<Callout type="warning">
  The following fields — used for multi-turn state and other advanced behavior — aren't part of CrossModel's official support surface yet. Whether they work depends on the model: some accept them, others return an `unsupported_responses_feature` error. For cross-model portability, avoid relying on them: `previous_response_id`, `conversation`, `store`, `background`, `include`, `prompt`, `prompt_cache_key`, `prompt_cache_retention`, `context_management`, `max_tool_calls`, `service_tier`, `verbosity`, `stream_options`, `parallel_tool_calls`.
</Callout>

## Example request

```bash
curl https://api.crossmodel.ai/v1/responses \
  -H "Authorization: Bearer cm-YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "openai/gpt-5-mini",
    "instructions": "You are a helpful assistant.",
    "input": "Hello!"
  }'
```

## Response

A non-streaming request returns a `response` object.

```json
{
  "id": "resp_abc123",
  "object": "response",
  "status": "completed",
  "model": "openai/gpt-5-mini",
  "output": [
    {
      "type": "message",
      "id": "msg_abc123",
      "role": "assistant",
      "status": "completed",
      "content": [
        { "type": "output_text", "text": "Hello! How can I help?" }
      ]
    }
  ],
  "usage": {
    "input_tokens": 18,
    "output_tokens": 14,
    "total_tokens": 32
  }
}
```

| Field | Type | Notes |
|------|------|------|
| `id` | string | A unique ID for this response. |
| `object` | string | Always `response`. |
| `status` | string | The response status; `completed` on success. |
| `model` | string | The model ID used for this request. |
| `output` | array | The generated output items. |
| `usage` | object | Token usage for this request, used for billing. |

### Output items

Each element of `output` is an item with a `type` field:

| type | Fields | Notes |
|------|------|------|
| `message` | `id`, `role`, `status`, `content` | A generated message. `content` is an array of `output_text` blocks. |
| `function_call` | `id`, `call_id`, `name`, `arguments`, `status` | A function call issued by the model. `arguments` is a JSON string. |

### The usage object

| Field | Type | Notes |
|------|------|------|
| `input_tokens` | integer | Input tokens. |
| `output_tokens` | integer | Output tokens. |
| `input_tokens_details.cached_tokens` | integer | Input tokens that hit the cache. |
| `output_tokens_details.reasoning_tokens` | integer | Tokens spent on reasoning. |
| `total_tokens` | integer | Input plus output tokens. |

## Streaming response

Set `stream` to `true` and the endpoint returns `text/event-stream`. Each event starts with `data: ` and carries an event object with a `type` field:

| Event | Notes |
|------|------|
| `response.created` | The response begins. |
| `response.output_item.added` | A new output item is added. |
| `response.output_text.delta` | An incremental piece of text. |
| `response.function_call_arguments.delta` | An incremental piece of function-call arguments. |
| `response.output_item.done` | An output item is complete. |
| `response.completed` | The response ends, carrying the full `output` and `usage`. |

The stream ends with a `response.completed` event.

```bash
curl https://api.crossmodel.ai/v1/responses \
  -H "Authorization: Bearer cm-YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "openai/gpt-5-mini",
    "input": "Hi",
    "stream": true
  }'
```

## Errors

Errors use one shared format:

```json
{
  "error": {
    "message": "Responses field 'store' is not supported in this release.",
    "type": "invalid_request_error",
    "param": "store",
    "code": "unsupported_responses_feature"
  }
}
```

| HTTP status | `type` | Common `code` | Notes |
|------------|--------|-------------|------|
| `400` | `invalid_request_error` | `invalid_json`, `invalid_responses_input`, `unsupported_responses_feature` | Malformed body JSON, `input` structure, or fields. |
| `401` | `authentication_error` | `missing_api_key`, `invalid_api_key` | API key missing or invalid. |
| `402` | `billing_error` | `insufficient_balance` | Account out of balance. |
| `404` | `invalid_request_error` | `model_not_found` | The requested model doesn't exist or is currently unavailable. |
| `429` | `rate_limit_error` | `rate_limit_exceeded`, `provider_rate_limited` | Too many requests — rate limited. |
| `502` | `provider_error` | `provider_error` | The model service returned an error or an abnormal response. |
| `503` | `api_error` | `model_unavailable` | Model temporarily unavailable — retry shortly. |
| `500` | `api_error` | `internal_error` | A CrossModel internal error. |
