# Create a model response

> OpenAI's Responses API (`client.responses.create` in the OpenAI SDKs) over the same chat models as `POST /v1/chat/completions`, with the same keys, prices and limits.

Source: https://docs.serenityedge.ai/docs/api/edge/create-response/

`POST https://api.serenityedge.ai/v1/responses`

OpenAI's Responses API (`client.responses.create` in the OpenAI SDKs) over the same chat models as `POST /v1/chat/completions`, with the same keys, prices and limits.

**Stateless.** Nothing is stored, so the whole conversation goes in `input` on every request. `store: true`, `previous_response_id`, `conversation`, `background: true` and stored `prompt` templates are refused with 400, every response says `"store": false`, and the routes under `/v1/responses/` (retrieve, delete, cancel, input items, compact, input tokens) answer 404.

**Served:**

- text and inline images, `instructions`, and the items of earlier turns;
- function tools (`tools`, `tool_choice`, `parallel_tool_calls`);
- `text.format` (`text`, `json_object`, `json_schema`);
- `reasoning.effort`, with the reasoning returned in plain text in a `reasoning` item;
- `max_output_tokens`, `temperature`, `top_p`.

**Streaming.** With `stream: true` the body is a `text/event-stream` of Responses events (`event:` line plus JSON with `type` and `sequence_number`), in this order:

1. `response.created`, then `response.in_progress`;
2. each output item: `response.output_item.added`, its content part, the deltas (`response.output_text.delta`, `response.reasoning_text.delta`, `response.function_call_arguments.delta`) and the matching `done` events;
3. exactly one of `response.completed`, `response.incomplete` or `response.failed`, carrying the full response.

No `[DONE]` follows. See the [Responses API guide](https://docs.serenityedge.ai/docs/responses-api).

## Request body (`application/json`)

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `model` | string | yes | Id or alias of a chat model, as on `POST /v1/chat/completions`. |
| `input` | one of string, array of one of ResponseInputMessage (object), ResponseFunctionCall (object), ResponseFunctionCallOutput (object), ResponseReasoningItem (object) | yes | The conversation: a string (one user message) or an array of input items. Send every earlier turn: nothing is stored between requests. |
| `instructions` | string | no | System message for this request. Every `system` and `developer` message of `input` is added to it, in order. |
| `tools` | array of one of ResponseFunctionTool (object), ResponseNamespaceTool (object) | no | Function tools, alone or grouped in `namespace` tools (as Codex groups the tools of its plugins and MCP servers). Hosted tools are refused. |
| `tools[] (ResponseFunctionTool).type` | string | yes | Always `function`. |
| `tools[] (ResponseFunctionTool).name` | string | yes |  |
| `tools[] (ResponseFunctionTool).description` | string | no |  |
| `tools[] (ResponseFunctionTool).parameters` | object | no | JSON schema of the arguments. |
| `tools[] (ResponseFunctionTool).strict` | boolean | no |  |
| `tools[] (ResponseNamespaceTool).type` | string | yes | Always `namespace`. |
| `tools[] (ResponseNamespaceTool).name` | string | yes |  |
| `tools[] (ResponseNamespaceTool).description` | string | no |  |
| `tools[] (ResponseNamespaceTool).tools` | array of ResponseFunctionTool (object) | yes | Function tools only. |
| `tools[] (ResponseNamespaceTool).tools[].type` | string | yes | Always `function`. |
| `tools[] (ResponseNamespaceTool).tools[].name` | string | yes |  |
| `tools[] (ResponseNamespaceTool).tools[].description` | string | no |  |
| `tools[] (ResponseNamespaceTool).tools[].parameters` | object | no | JSON schema of the arguments. |
| `tools[] (ResponseNamespaceTool).tools[].strict` | boolean | no |  |
| `tool_choice` | one of string, object | no | `auto` (default), `none`, `required`, or `{"type": "function", "name": "..."}`. |
| `tool_choice.type` | string | yes | Always `function`. |
| `tool_choice.name` | string | yes |  |
| `parallel_tool_calls` | boolean | no | Whether the model may call several functions at once. Default `true`. |
| `text` | ResponseTextConfig (object) | no |  |
| `text.format` | one of object, object | no | `text` (default), `json_object`, or `json_schema` with `name` and `schema`, as `response_format` on chat. |
| `text.format.type` | string | yes | One of `text`, `json_object`. |
| `text.format.type` | string | yes | Always `json_schema`. |
| `text.format.name` | string | yes |  |
| `text.format.schema` | object | yes |  |
| `text.format.description` | string | no |  |
| `text.format.strict` | boolean | no |  |
| `text.verbosity` | string | no | Accepted; no effect. One of `low`, `medium`, `high`. |
| `reasoning` | object | no |  |
| `reasoning.effort` | string | no | `none` (default) turns reasoning off; any other value turns it on. One of `none`, `minimal`, `low`, `medium`, `high`, `xhigh`. |
| `reasoning.summary` | string | no | Accepted; no summary is produced. The reasoning comes back in plain text. |
| `max_output_tokens` | integer | no | Cap on generated tokens, reasoning included. Capped at the model's output limit. A response cut by it has `status: "incomplete"`. At least 1. |
| `temperature` | number | no | At least 0. At most 2. |
| `top_p` | number | no | At least 0. At most 1. |
| `stream` | boolean | no | Stream Responses events. Default `false`. |
| `store` | boolean | no | Only `false` (or omitted): responses are never stored. Always `false`. |
| `include` | array of string | no | Accepted values; neither changes the answer. `message.output_text.logprobs` is refused. |
| `truncation` | string | no | Input longer than the context window is refused, never cut. Always `disabled`. |
| `metadata` | object | no | Repeated in the response; not stored. |
| `user` | string | no | Repeated in the response; not stored. |
| `client_metadata` | object | no | Client identifiers, as Codex sends them. Accepted and dropped: they reach neither the model nor the response. |

Example:

```json
{
  "model": "orion-plus",
  "instructions": "Answer in one sentence.",
  "input": "Why does EU data residency matter for a SaaS company?"
}
```

## Responses

### 200: The response. With `stream: true`, a `text/event-stream` of `ResponseStreamEvent` objects instead, ending with `response.completed`, `response.incomplete` or `response.failed`.

Body (`application/json`): `Response`

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `id` | string | no | `resp_` and 32 hex digits. Never stored: it cannot be retrieved. |
| `object` | string | no | Always `response`. |
| `created_at` | integer | no |  |
| `status` | string | no | One of `completed`, `incomplete`, `failed`, `in_progress`. |
| `error` | one of null, object | no | Set when `status` is `failed` (only in a stream's `response.failed`). |
| `error.code` | string | no |  |
| `error.message` | string | no |  |
| `incomplete_details` | one of null, object | no | `{"reason": "max_output_tokens"}` when the answer was cut. |
| `incomplete_details.reason` | string | no | One of `max_output_tokens`, `content_filter`. |
| `model` | string | no |  |
| `output` | array of one of ResponseReasoningItem (object), ResponseOutputMessage (object), ResponseFunctionCall (object) | no |  |
| `output[] (ResponseReasoningItem).id` | string | no |  |
| `output[] (ResponseReasoningItem).type` | string | yes | Always `reasoning`. |
| `output[] (ResponseReasoningItem).status` | string | no |  |
| `output[] (ResponseReasoningItem).summary` | array of object | no | Always empty in output. |
| `output[] (ResponseReasoningItem).content` | array of object | no | The reasoning, in plain text. |
| `output[] (ResponseReasoningItem).content[].type` | string | no | Always `reasoning_text`. |
| `output[] (ResponseReasoningItem).content[].text` | string | no |  |
| `output[] (ResponseReasoningItem).encrypted_content` | null | no | Always `null`: the reasoning is returned in plain text. |
| `output[] (ResponseOutputMessage).id` | string | no |  |
| `output[] (ResponseOutputMessage).type` | string | no | Always `message`. |
| `output[] (ResponseOutputMessage).status` | string | no | One of `completed`, `incomplete`, `in_progress`. |
| `output[] (ResponseOutputMessage).role` | string | no | Always `assistant`. |
| `output[] (ResponseOutputMessage).content` | array of ResponseOutputText (object) | no |  |
| `output[] (ResponseOutputMessage).content[].type` | string | yes | Always `output_text`. |
| `output[] (ResponseOutputMessage).content[].text` | string | yes |  |
| `output[] (ResponseOutputMessage).content[].annotations` | array of object | no |  |
| `output[] (ResponseOutputMessage).content[].logprobs` | array of object | no |  |
| `output[] (ResponseFunctionCall).id` | string | no |  |
| `output[] (ResponseFunctionCall).type` | string | yes | Always `function_call`. |
| `output[] (ResponseFunctionCall).status` | string | no |  |
| `output[] (ResponseFunctionCall).call_id` | string | yes | Answer it with a `function_call_output` with the same `call_id`. |
| `output[] (ResponseFunctionCall).name` | string | yes |  |
| `output[] (ResponseFunctionCall).namespace` | string | no | Set on a call to a function of a `namespace` tool: the namespace's name. Send it back as it came. |
| `output[] (ResponseFunctionCall).arguments` | string | yes | The arguments as a JSON string. |
| `store` | boolean | no | Always `false`. |
| `usage` | ResponseUsage (object) | no |  |
| `usage.input_tokens` | integer | no |  |
| `usage.input_tokens_details` | object | no |  |
| `usage.input_tokens_details.cached_tokens` | integer | no |  |
| `usage.output_tokens` | integer | no | Generated tokens, reasoning included. |
| `usage.output_tokens_details` | object | no |  |
| `usage.output_tokens_details.reasoning_tokens` | integer | no | 0 when the model does not report it. |
| `usage.total_tokens` | integer | no |  |

Body (`text/event-stream`): `ResponseStreamEvent`

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `type` | string | yes | One of `response.created`, `response.in_progress`, `response.output_item.added`, `response.content_part.added`, `response.output_text.delta`, `response.output_text.done`, `response.reasoning_text.delta`, `response.reasoning_text.done`, `response.function_call_arguments.delta`, `response.function_call_arguments.done`, `response.content_part.done`, `response.output_item.done`, `response.completed`, `response.incomplete`, `response.failed`. |
| `sequence_number` | integer | yes | Counts from 0 within a stream. |
| `response` | Response (object) | no | A response. The request's parameters (`instructions`, `tools`, `tool_choice`, `text`, `reasoning`, `temperature`, `top_p`, `max_output_tokens`, `metadata`, `user`) are repeated as sent, or with OpenAI's defaults. |
| `response.id` | string | no | `resp_` and 32 hex digits. Never stored: it cannot be retrieved. |
| `response.object` | string | no | Always `response`. |
| `response.created_at` | integer | no |  |
| `response.status` | string | no | One of `completed`, `incomplete`, `failed`, `in_progress`. |
| `response.error` | one of null, object | no | Set when `status` is `failed` (only in a stream's `response.failed`). |
| `response.error.code` | string | no |  |
| `response.error.message` | string | no |  |
| `response.incomplete_details` | one of null, object | no | `{"reason": "max_output_tokens"}` when the answer was cut. |
| `response.incomplete_details.reason` | string | no | One of `max_output_tokens`, `content_filter`. |
| `response.model` | string | no |  |
| `response.output` | array of one of ResponseReasoningItem (object), ResponseOutputMessage (object), ResponseFunctionCall (object) | no |  |
| `response.output[] (ResponseReasoningItem).id` | string | no |  |
| `response.output[] (ResponseReasoningItem).type` | string | yes | Always `reasoning`. |
| `response.output[] (ResponseReasoningItem).status` | string | no |  |
| `response.output[] (ResponseReasoningItem).summary` | array of object | no | Always empty in output. |
| `response.output[] (ResponseReasoningItem).content` | array of object | no | The reasoning, in plain text. |
| `response.output[] (ResponseReasoningItem).content[].type` | string | no | Always `reasoning_text`. |
| `response.output[] (ResponseReasoningItem).content[].text` | string | no |  |
| `response.output[] (ResponseReasoningItem).encrypted_content` | null | no | Always `null`: the reasoning is returned in plain text. |
| `response.output[] (ResponseOutputMessage).id` | string | no |  |
| `response.output[] (ResponseOutputMessage).type` | string | no | Always `message`. |
| `response.output[] (ResponseOutputMessage).status` | string | no | One of `completed`, `incomplete`, `in_progress`. |
| `response.output[] (ResponseOutputMessage).role` | string | no | Always `assistant`. |
| `response.output[] (ResponseOutputMessage).content` | array of ResponseOutputText (object) | no |  |
| `response.output[] (ResponseOutputMessage).content[].type` | string | yes | Always `output_text`. |
| `response.output[] (ResponseOutputMessage).content[].text` | string | yes |  |
| `response.output[] (ResponseOutputMessage).content[].annotations` | array of object | no |  |
| `response.output[] (ResponseOutputMessage).content[].logprobs` | array of object | no |  |
| `response.output[] (ResponseFunctionCall).id` | string | no |  |
| `response.output[] (ResponseFunctionCall).type` | string | yes | Always `function_call`. |
| `response.output[] (ResponseFunctionCall).status` | string | no |  |
| `response.output[] (ResponseFunctionCall).call_id` | string | yes | Answer it with a `function_call_output` with the same `call_id`. |
| `response.output[] (ResponseFunctionCall).name` | string | yes |  |
| `response.output[] (ResponseFunctionCall).namespace` | string | no | Set on a call to a function of a `namespace` tool: the namespace's name. Send it back as it came. |
| `response.output[] (ResponseFunctionCall).arguments` | string | yes | The arguments as a JSON string. |
| `response.store` | boolean | no | Always `false`. |
| `response.usage` | ResponseUsage (object) | no |  |
| `response.usage.input_tokens` | integer | no |  |
| `response.usage.input_tokens_details` | object | no |  |
| `response.usage.input_tokens_details.cached_tokens` | integer | no |  |
| `response.usage.output_tokens` | integer | no | Generated tokens, reasoning included. |
| `response.usage.output_tokens_details` | object | no |  |
| `response.usage.output_tokens_details.reasoning_tokens` | integer | no | 0 when the model does not report it. |
| `response.usage.total_tokens` | integer | no |  |

### 400: The request was refused before reaching the model. Causes: - a stateful parameter: `store: true`, `previous_response_id`, `conversation`, `background: true`, `prompt` or an `item_reference` item. The API is stateless; - a hosted tool (`web_search`, `file_search`, `code_interpreter`, `computer_use`, `image_generation`, `mcp`, custom tools) or its items in `input`. In Codex, turn web search off with `web_search = "disabled"` in `config.toml`; - a file input, or an image by URL or file id: images must be inline base64 data URLs; - logprobs, `truncation: "auto"`, `context_management` (compaction) or an unknown parameter (such as chat's `messages`); - more images than the model reads, counted over the whole `input`: from 1 to 8 depending on the model (`code: too_many_images`, `param: input`); - any invalid value, or input longer than the context window (`context_length_exceeded`). `param` names the field at fault in the Responses API's terms (`input`, `max_output_tokens`, `tools[0].type`).

Body (`application/json`): `ErrorResponse`

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `error` | Error (object) | yes | OpenAI-style error object. |
| `error.message` | string | yes | Human-readable description of the problem. |
| `error.type` | string | yes | Error category. One of `invalid_request_error`, `authentication_error`, `permission_error`, `not_found_error`, `rate_limit_error`, `server_error`. |
| `error.code` | string or null | no | Machine-readable error code, when available. |
| `error.param` | string or null | no | The request parameter the error refers to, when applicable. |

### 401: Missing or invalid API key.

Body (`application/json`): `ErrorResponse`, the same fields as under 400.

### 404: The requested model does not exist or is not available to this key.

Body (`application/json`): `ErrorResponse`, the same fields as under 400.

### 413: The request body is larger than the gateway accepts (4 MB).

Body (`application/json`): `ErrorResponse`, the same fields as under 400.

### 429: Rate limit exceeded, or the service is temporarily at capacity for this model. Wait for the number of seconds in the `Retry-After` header before retrying.

Header `Retry-After`: Seconds to wait before retrying.

Body (`application/json`): `ErrorResponse`, the same fields as under 400.

### 500: Unexpected server error: the model service returned an unexpected response (`upstream_error`), the request got no answer within 600 seconds (`timeout`), or an error in the gateway. Retry with backoff.

Body (`application/json`): `ErrorResponse`, the same fields as under 400.

### 503: The model service is temporarily unavailable. Retry later and check the status page at https://status.serenityedge.ai.

Body (`application/json`): `ErrorResponse`, the same fields as under 400.
