> This page is for Gateway.

> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.merge.dev/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.merge.dev/_mcp/server.

# Multi-turn conversations

> Run multi-turn conversations on Gateway by sending the full history in input, or by storing a turn with store and resuming it with previous_response_id.

A conversation is multi-turn when the model needs what was already said. Send prior turns in `input` on every request, or have Gateway store a turn and continue from its ID.

## Send the conversation in `input`

This works on every model and route, needs no setup, and Gateway keeps nothing, so it's the right default.

**`cURL`**

```bash title="cURL"
curl https://api-gateway.merge.dev/v1/responses \
  -H "Authorization: Bearer $MERGE_GATEWAY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "openai/gpt-4o",
    "input": [
      {"type": "message", "role": "user", "content": "Say hello in one word."},
      {"type": "message", "role": "assistant", "content": "Hello"},
      {"type": "message", "role": "user", "content": "What word did you just say?"}
    ]
  }'
```

On most routes the repeated prefix is [cached](/merge-gateway/capabilities/prompt-caching) and billed at a lower rate.

## Let Gateway hold the conversation

Send `store: true` and Gateway saves the turn under the response `id`. Next time, pass that ID as `previous_response_id` with only the new input; Gateway replays the stored conversation ahead of it.

**`cURL`**

```bash title="cURL"
curl https://api-gateway.merge.dev/v1/responses \
  -H "Authorization: Bearer $MERGE_GATEWAY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "openai/gpt-4o",
    "previous_response_id": "resp_9754aec2adc6059b",
    "input": [{"type": "message", "role": "user", "content": "What word did you just say?"}],
    "store": true
  }'
```

Send `store: true` on every turn you want to resume from; a resumed turn without it runs but isn't saved.

> **Storing is off unless you ask**
>
> Omitting `store` stores nothing, unlike the OpenAI API, which defaults to `true`. A client that relies on the OpenAI default gets a 404 on `previous_response_id` until it sends `store: true`.

The store is best-effort (records can expire or fail to be stored), so keep your own transcript as the fallback. It doesn't lower token cost: the vendor still receives the full conversation. Only text and tool calls replay. Reasoning blocks, vendor-run tool results such as web search, and generated images are dropped, since the next turn may route to another vendor. `/v1/openai/responses` and `/v1/ai-sdk` accept `store` and `previous_response_id` too.

## Read or delete a stored response

**`cURL`**

```bash title="cURL"
curl https://api-gateway.merge.dev/v1/responses/resp_9754aec2adc6059b \
  -H "Authorization: Bearer $MERGE_GATEWAY_API_KEY"

curl -X DELETE https://api-gateway.merge.dev/v1/responses/resp_9754aec2adc6059b \
  -H "Authorization: Bearer $MERGE_GATEWAY_API_KEY"
```

`GET` returns an object with `object: "response.stored"` and the stored `input`, `output`, `previous_response_id`, and `vendor`. `DELETE` returns `{"id": "...", "object": "response.deleted", "deleted": true}` and ends the chain.

## Reference

| Behavior                                                           | Value                                                                                                                                                                    |
| ------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Expiry                                                             | 30 days after the turn is stored, matching OpenAI. `DELETE /v1/responses/{id}` removes it sooner.                                                                        |
| Maximum stored snapshot                                            | 8 MB. A larger turn isn't stored, and the chain ends there.                                                                                                              |
| Scope                                                              | Your organization, plus the project or customer your key is scoped to. The match is exact, so an organization-wide key can't read a turn stored by a project-scoped key. |
| [Zero data retention](/merge-gateway/security/zero-data-retention) | Nothing is stored, and `store: true` has no effect                                                                                                                       |
| Batch requests                                                     | `previous_response_id` isn't accepted                                                                                                                                    |

| Error                                                      | Cause                                                                                                 |
| ---------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- |
| `404 not_found_error`, `code: previous_response_not_found` | The ID expired, was never stored, or belongs to another scope. Send the full conversation in `input`. |
| `400 previous_response_id_unsupported`                     | Your organization has zero data retention on                                                          |
| `500 response_store_unavailable`                           | The store didn't answer in time. Retry, or send the full conversation.                                |
| `400 conversation_unsupported`                             | The request sent an OpenAI `conversation` object, which Gateway doesn't host                          |
| `404 response_not_found`                                   | `GET` or `DELETE` on an unknown ID                                                                    |

## Next steps

#### [Streaming](/merge-gateway/streaming)

Stream response events to your client

#### [Prompt caching](/merge-gateway/capabilities/prompt-caching)

Reuse context across requests