# Responses (/docs/api/responses)

`POST /v1/responses` speaks the OpenAI Responses protocol, the one Codex and the OpenAI SDK's `client.responses` use. Every chat model works here, and `previous_response_id` works on all of them, Claude and Gemini included. The full schema is in the [endpoint reference](/docs/api/chat/createResponse).

| | |
|---|---|
| Endpoint | `POST https://api.ohmygpt.com/v1/responses` |
| SDK base URL | `https://api.ohmygpt.com/v1` |
| Auth | `Authorization: Bearer $OHMYGPT_API_KEY` |

```python tab="Python"
import os
from openai import OpenAI

client = OpenAI(
    base_url="https://api.ohmygpt.com/v1",
    api_key=os.environ["OHMYGPT_API_KEY"],
)

response = client.responses.create(
    model="openai/gpt-5.4-nano",
    input="Explain QUIC in two sentences.",
)
print(response.output_text)
```

```bash tab="cURL"
curl https://api.ohmygpt.com/v1/responses \
  -H "Authorization: Bearer $OHMYGPT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model": "openai/gpt-5.4-nano", "input": "Explain QUIC in two sentences."}'
```

To point Codex at OhMyGPT, see [Codex CLI](/docs/code-cli/codex).

GPT models receive your request as sent, with every Responses field the vendor supports. Other models answer in the same Responses shape. `background`, `conversation`, `max_tool_calls`, `truncation`, and `prompt` apply to GPT models; see [Protocols](/docs/api/protocols#other-protocols).

Set reasoning with `reasoning.effort`; see [Thinking](/docs/api/thinking).

## Stored responses [#stored-responses]

OhMyGPT stores each successful response for every model and returns a `resp_` ID. `store` defaults to `true`; send `store: false` to skip storage. Stored responses are kept for 30 days and are visible only to your account.

| Route | Does |
|---|---|
| `GET /v1/responses/{id}` | Return a stored response |
| `GET /v1/responses/{id}/input_items` | List its input items (`limit`, `after`, `order`) |
| `DELETE /v1/responses/{id}` | Delete it |
| `GET /v1/responses` | List your stored responses, newest first (`limit`, `after`) |
| `POST /v1/responses/{id}/cancel` | Mark an in-progress response as cancelled |

Pass a stored ID as `previous_response_id` to continue a conversation on any model. The model sees the earlier turns followed by your new `input`, and the earlier turns count as input tokens:

```python
first = client.responses.create(model="ohmygpt/mock", input="ping")
follow = client.responses.create(
    model="ohmygpt/mock",
    input="again",
    previous_response_id=first.id,
)
items = client.responses.input_items.list(follow.id)
print([item.type for item in items.data])  # ['message', 'message', 'message']
```

Use the `resp_` IDs of stored responses. Any other ID, including one from a request sent with `store: false`, returns 404:

```json
{
  "error": {
    "type": "not_found_error",
    "code": "not_found",
    "param": null,
    "message": "No response found with this `previous_response_id`."
  }
}
```

## Codex tool items [#codex-tool-items]

Codex sends item types beyond the core Responses vocabulary: `custom_tool_call`, `custom_tool_call_output`, `agent_message`, and `additional_tools`. They work with every chat model, so you can run Codex on Claude, Gemini, or any other model in the catalog.

## Streaming [#streaming]

`stream: true` returns Responses events that end with `response.completed`, `response.incomplete`, or `response.failed`. A `: x-cost-credits` comment line comes right before the final event. If the model fails after the stream has started, the stream ends with `response.failed` and the error in `response.error`. See [Streaming](/docs/api/streaming).
