Skip to content
v0.8.4stable

Responses

POST /v1/responses  compatible  semantic operation generate  contract revision 2

State semantics: stateless by default; background=true defers one generation to a project-owned record with a 24 hour TTL and a 15 minute cool-off after first retrieval; the remaining stateful fields are rejected before provider I/O

Raw contract deviations

These statements are source-contract evidence. Use the examples, field table, and Profile coverage matrix for ordinary integration, and expand this list when investigating a compatibility boundary.

  • input_items, Conversations, and webhooks are unavailable; retrieval, cancellation and deletion serve deferred submissions alone
  • store defaults to false and store=true is rejected even alongside background=true, because store asserts that the provider retains the Response and Halro’s upstream retains nothing (ADR 0021)
  • background=true is enabled per Project and refused with unsupported_feature where the Project has not enabled it, because a deferred answer is written to disk and that is a decision about what the data directory holds
  • a background submission carries at most 256 KiB of request body, which is below the gateway’s own request ceiling: the same body sent synchronously is accepted and sent with background=true is refused, because the deferred body is stored rather than forwarded
  • a background submission does not survive a gateway restart: a deferred response has no upstream handle, so a request in flight when the process dies is failed and settled conservatively
  • a deferred answer larger than 1 MiB is failed rather than stored, and the request was still billed: the ceiling is on what may be kept, and nothing can measure an answer before the upstream produces it
  • a background submission whose Project is at its TPM or concurrency ceiling waits in the queue rather than being refused; only the queue depth and the 24 hour TTL bound that wait
  • one deferred attempt is bounded by the same route_total_timeout a synchronous attempt runs under; exceeding it fails the request, which was still billed
  • strict function tools, reasoning output, and streaming tools are rejected
  • tools[].type=web_search is the one hosted tool accepted; it is routed against the provider_executed_tools capability and served only by the OpenAI Responses profile, and code_interpreter and file_search stay rejected because both are provider-side state
  • request instructions, tool definitions, tool choice, and structured schema bodies are returned as conservative null, empty, or default response metadata because the original Responses object has not passed through outbound redaction
  • portable requests are translated through the selected profile’s existing generation primitive
  • unknown fields and unsupported item types are rejected before provider I/O

Requests are stateless by default: omitting store is equivalent to store: false. store=true, previous_response_id, and conversation are rejected before Provider I/O. When a Project explicitly enables deferred responses, background: true submits one generation to Halro’s bounded queue. Idempotency-Key is optional but strongly recommended. This is not a Provider-hosted Response and does not provide a multi-turn conversation.

Terminal window
curl https://halro.example.com/v1/responses \
-H "Authorization: Bearer $HALRO_GATEWAY_KEY" \
-H "Content-Type: application/json" \
-d '{ "model": "chat", "max_output_tokens": 256,
"input": "Explain Halro in one sentence" }'
  • Authorization
  • Content-Type
  • Idempotency-Key when submitting with background=true
Request fields
FieldProvider Profiles that do not support itCombination-level constraints
model1
input
input[].type
input[].role
input[].content
input[].call_id
input[].name
input[].arguments
input[].output
input[].content[].type
input[].content[].text
input[].content[].detailanthropic.messages.2023-06-01, bedrock.mantle.anthropic.messages.v1, minimax.anthropic.messages.v1, kimi.anthropic.messages.v1
instructions
reasoning2
stream
store
temperaturekimi.chat.v1, kimi.anthropic.messages.v1, kimi.responses.v13
top_pkimi.chat.v1, kimi.anthropic.messages.v1, kimi.responses.v14
max_output_tokens
toolsgemini.generate-content.text.v1beta, bedrock.runtime.converse.text.v1, bedrock.mantle.responses.v1, bedrock.mantle.openai.responses.v15
tools[].type6
tools[].name7
tools[].description8
tools[].parameters9
tools[].strict10
tool_choicegemini.generate-content.text.v1beta, bedrock.runtime.converse.text.v1, kimi.chat.v111
parallel_tool_callsdeepseek.chat.v1, gemini.generate-content.text.v1beta, bedrock.runtime.converse.text.v1, minimax.chat.v1, minimax.responses.v1, kimi.chat.v1, kimi.responses.v112
text.formatanthropic.messages.2023-06-01, deepseek.chat.v1, gemini.generate-content.text.v1beta, bedrock.runtime.converse.text.v1, bedrock.mantle.anthropic.messages.v1, minimax.anthropic.messages.v1, minimax.chat.v1, minimax.responses.v1, kimi.anthropic.messages.v113
text.format.type
text.format.name
text.format.description
text.format.schema
text.format.strict
useranthropic.messages.2023-06-01, gemini.generate-content.text.v1beta, bedrock.runtime.converse.text.v1, bedrock.mantle.anthropic.messages.v1, minimax.anthropic.messages.v1, minimax.chat.v1, minimax.responses.v1, kimi.chat.v1, kimi.anthropic.messages.v1, kimi.responses.v1
background

Halro rejects these fields before any Provider I/O:

  • store=true
  • previous_response_id
  • conversation
  • background=true with stream=true
  • prompt
  • metadata
  • include
  • context_management
  • service_tier
  • truncation
  • max_tool_calls
  • prompt_cache_key
  • prompt_cache_options
  • prompt_cache_retention
  • safety_identifier
  • stream_options
  • top_logprobs
  • reasoning
  • input[].id
  • input[].type=unsupported
  • tools[].type!=function
  • tools[].strict=true
  • stream=true with tools

id object created_at completed_at status background error incomplete_details instructions max_output_tokens model output output[].id output[].type output[].status output[].role output[].content output[].call_id output[].name output[].arguments output[].content[].type output[].content[].text output[].content[].refusal output[].content[].annotations output[].content[].logprobs parallel_tool_calls previous_response_id reasoning store temperature text tool_choice tools top_p truncation usage usage.input_tokens usage.output_tokens usage.total_tokens

response.created response.in_progress response.output_item.added response.content_part.added response.output_text.delta response.output_text.done response.content_part.done response.output_item.done response.completed response.incomplete error

Provider Profile contract coverage and current availability

Section titled “Provider Profile contract coverage and current availability”
Provider Profile contract coverage and current availability
Provider ProfileMaturityCurrent buildUnsupported request fields
openai.chat-embeddings.v1compatiblecreatableundeclared
openai.responses.v1compatiblecreatableundeclared
anthropic.messages.2023-06-01compatiblecreatabletext.format, user, input[].content[].detail
azure-openai.chat-embeddings.v1compatiblecreatableundeclared
deepseek.chat.v1compatiblecreatableparallel_tool_calls, text.format
openai-compatible.chat-embeddings.v1compatiblecreatableundeclared
gemini.generate-content.text.v1betacompatiblecreatabletools, tool_choice, parallel_tool_calls, text.format, user
bedrock.runtime.converse.text.v1compatiblewithheld (cannot create)tools, tool_choice, parallel_tool_calls, text.format, user
bedrock.mantle.chat.v1compatiblecreatableundeclared
bedrock.mantle.openai.chat.v1compatiblecreatableundeclared
bedrock.mantle.responses.v1compatiblecreatabletools
bedrock.mantle.openai.responses.v1compatiblecreatabletools
bedrock.mantle.anthropic.messages.v1compatiblecreatabletext.format, user, input[].content[].detail
minimax.anthropic.messages.v1compatiblecreatabletext.format, user, input[].content[].detail
minimax.chat.v1compatiblecreatableparallel_tool_calls, text.format, user
minimax.responses.v1compatiblecreatableparallel_tool_calls, text.format, user
kimi.chat.v1compatiblecreatabletemperature, top_p, parallel_tool_calls, user, tool_choice
kimi.anthropic.messages.v1compatiblecreatabletemperature, top_p, text.format, user, input[].content[].detail
kimi.responses.v1compatiblewithheld (cannot create)temperature, top_p, parallel_tool_calls, user
openai.chat-embeddings.v1
  • Responses items are mapped through the OpenAI Chat Completions ProviderPrimitive
openai.responses.v1
  • stateless Responses are sent directly with store=false
  • tools[].type=web_search requires the selected connection to declare provider_executed_tools
  • url_citation annotations are carried back on the output text
anthropic.messages.2023-06-01
  • Responses items are mapped through the Anthropic Messages ProviderPrimitive
azure-openai.chat-embeddings.v1
  • Responses items are mapped through the Azure Chat Completions ProviderPrimitive
deepseek.chat.v1
  • Responses items are mapped through the DeepSeek Chat ProviderPrimitive
  • max_output_tokens is carried as DeepSeek’s max_tokens: it is a completion budget that counts reasoning, and this endpoint rejects the reasoning request field outright, so nothing served here thinks and the two bound the same tokens
  • parallel_tool_calls is value-dependent: true is what omitting the member already means, and only a request to run tools one at a time is rejected
  • text.format is value-dependent: DeepSeek has json_object and no schema mode, so a schema is rejected before provider I/O
  • user is carried as DeepSeek’s user_id
openai-compatible.chat-embeddings.v1
  • Responses items are mapped through the compatible Chat Completions ProviderPrimitive
gemini.generate-content.text.v1beta
  • instructions are mapped to a developer message and merged into Gemini system_instruction
bedrock.runtime.converse.text.v1
  • instructions are mapped to a developer message
  • Bedrock stop reasons are normalized to Responses status
bedrock.mantle.chat.v1
  • Responses items are mapped through Bedrock Mantle Chat Completions
bedrock.mantle.openai.chat.v1
  • Responses items are mapped through Bedrock Mantle Chat Completions
bedrock.mantle.responses.v1
  • stateless Responses are sent directly with store=false
bedrock.mantle.openai.responses.v1
  • stateless Responses are sent directly with store=false
bedrock.mantle.anthropic.messages.v1
  • an Anthropic image source is base64, url, or file and has no member for the OpenAI fidelity hint, so detail is rejected before provider I/O at any value other than auto rather than dropped from a request that paid for it
  • Responses items are mapped through Bedrock Mantle Anthropic Messages
minimax.anthropic.messages.v1
  • Responses items are mapped through MiniMax’s Anthropic Messages ProviderPrimitive
  • an Anthropic image source is base64, url, or file and has no member for the OpenAI fidelity hint, so detail is rejected before provider I/O at any value other than auto rather than dropped from a request that paid for it
minimax.chat.v1
  • Responses items are mapped through the MiniMax Chat ProviderPrimitive
  • max_output_tokens is carried as MiniMax’s max_completion_tokens, which is the same quantity: this endpoint rejects the reasoning request field outright, so nothing served here thinks
  • parallel_tool_calls is value-dependent: true is what omitting the member already means
minimax.responses.v1
  • stateless Responses are sent directly with store=false
  • reasoning is rejected before provider I/O because the canonical response mapper cannot preserve the reasoning items MiniMax returns
kimi.chat.v1
  • Responses items are mapped through the Kimi Chat ProviderPrimitive
  • tool_choice is value-dependent: a named function together with a reasoning depth is refused by every Kimi model and is routed away before provider I/O
  • Kimi does not model temperature or top_p as request members and pins each to one value per model, so they are rejected before provider I/O rather than sent or silently replaced
  • max_output_tokens is carried as Kimi’s max_completion_tokens, which Kimi documents as the same bound
  • parallel_tool_calls is value-dependent: true is what omitting the member already means
  • text.format is carried: the Kimi Chat face documents the json_schema response format alongside json_object
kimi.anthropic.messages.v1
  • Responses items are mapped through Kimi’s Anthropic Messages ProviderPrimitive
  • an Anthropic image source is base64, url, or file and has no member for the OpenAI fidelity hint, so detail is rejected before provider I/O at any value other than auto rather than dropped from a request that paid for it
  • temperature and top_p are rejected because Kimi pins each per model
  • text.format is value-dependent: this face takes a schema through output_config.format and enforces it, so a schema-less request is routed away
kimi.responses.v1
  • stateless Responses are sent directly
  • Kimi does not model temperature or top_p as request members on this face either
  • reasoning is rejected before provider I/O because the canonical response mapper cannot preserve the reasoning items Kimi returns
  • text.format carries a schema; the schema-less json_object mode is routed away by the absent json_object capability rather than by field, because Kimi’s Responses face accepts the json_schema type alone
  • this endpoint serves kimi-k3 alone, which the model catalogue records per model

Verified evidence: gateway_contract, provider_transport_fixture, sdk_blackbox

openai-go, openai-node, openai-python

See deferred Responses and stream interruption.


Fields, coverage, transformations, and deviations are generated from Halro 8f185de7674c (scripts/generate-api-pages-en.mjs; synchronized manifest digest 8e5e7a0a794721aa…). The synchronized copy contains 1 recorded accuracy correction(s); source manifest digest b321ee18ad2e38f3…. The contract currently carries field names, not complete types, required relationships, or value semantics.

  1. Combination constraints for model:

    • kimi.chat.v1: tool_choice is value-dependent: a named function together with a reasoning depth is refused by every Kimi model and is routed away before provider I/O
    • kimi.chat.v1: Kimi does not model temperature or top_p as request members and pins each to one value per model, so they are rejected before provider I/O rather than sent or silently replaced
    • kimi.anthropic.messages.v1: temperature and top_p are rejected because Kimi pins each per model
  2. Combination constraints for reasoning:

    • minimax.responses.v1: reasoning is rejected before provider I/O because the canonical response mapper cannot preserve the reasoning items MiniMax returns
    • kimi.chat.v1: tool_choice is value-dependent: a named function together with a reasoning depth is refused by every Kimi model and is routed away before provider I/O
    • kimi.responses.v1: reasoning is rejected before provider I/O because the canonical response mapper cannot preserve the reasoning items Kimi returns
  3. Combination constraints for temperature:

    • kimi.chat.v1: Kimi does not model temperature or top_p as request members and pins each to one value per model, so they are rejected before provider I/O rather than sent or silently replaced
    • kimi.anthropic.messages.v1: temperature and top_p are rejected because Kimi pins each per model
  4. Combination constraints for top_p:

    • kimi.chat.v1: Kimi does not model temperature or top_p as request members and pins each to one value per model, so they are rejected before provider I/O rather than sent or silently replaced
    • kimi.anthropic.messages.v1: temperature and top_p are rejected because Kimi pins each per model
  5. Combination constraints for tools:

    • deepseek.chat.v1: parallel_tool_calls is value-dependent: true is what omitting the member already means, and only a request to run tools one at a time is rejected
  6. Combination constraints for tools[].type:

    • deepseek.chat.v1: parallel_tool_calls is value-dependent: true is what omitting the member already means, and only a request to run tools one at a time is rejected
  7. Combination constraints for tools[].name:

    • deepseek.chat.v1: parallel_tool_calls is value-dependent: true is what omitting the member already means, and only a request to run tools one at a time is rejected
  8. Combination constraints for tools[].description:

    • deepseek.chat.v1: parallel_tool_calls is value-dependent: true is what omitting the member already means, and only a request to run tools one at a time is rejected
  9. Combination constraints for tools[].parameters:

    • deepseek.chat.v1: parallel_tool_calls is value-dependent: true is what omitting the member already means, and only a request to run tools one at a time is rejected
  10. Combination constraints for tools[].strict:

    • deepseek.chat.v1: parallel_tool_calls is value-dependent: true is what omitting the member already means, and only a request to run tools one at a time is rejected
  11. Combination constraints for tool_choice:

    • kimi.chat.v1: tool_choice is value-dependent: a named function together with a reasoning depth is refused by every Kimi model and is routed away before provider I/O
  12. Combination constraints for parallel_tool_calls:

    • deepseek.chat.v1: parallel_tool_calls is value-dependent: true is what omitting the member already means, and only a request to run tools one at a time is rejected
  13. Combination constraints for text.format:

    • deepseek.chat.v1: text.format is value-dependent: DeepSeek has json_object and no schema mode, so a schema is rejected before provider I/O
    • kimi.anthropic.messages.v1: text.format is value-dependent: this face takes a schema through output_config.format and enforces it, so a schema-less request is routed away
    • kimi.responses.v1: text.format carries a schema; the schema-less json_object mode is routed away by the absent json_object capability rather than by field, because Kimi’s Responses face accepts the json_schema type alone