Skip to navigation

Multi-turn conversations

Continue a conversation by sending it back, or let Gateway hold it for you

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

BehaviorValue
Expiry30 days after the turn is stored, matching OpenAI. DELETE /v1/responses/{id} removes it sooner.
Maximum stored snapshot8 MB. A larger turn isn’t stored, and the chain ends there.
ScopeYour 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 retentionNothing is stored, and store: true has no effect
Batch requestsprevious_response_id isn’t accepted
ErrorCause
404 not_found_error, code: previous_response_not_foundThe ID expired, was never stored, or belongs to another scope. Send the full conversation in input.
400 previous_response_id_unsupportedYour organization has zero data retention on
500 response_store_unavailableThe store didn’t answer in time. Retry, or send the full conversation.
400 conversation_unsupportedThe request sent an OpenAI conversation object, which Gateway doesn’t host
404 response_not_foundGET or DELETE on an unknown ID

Next steps