본문으로 건너뛰기

Responses (OpenAI)

OpenAI Responses-format inbound adapter. OpenAI's Codex CLI only speaks /v1/responses, so this endpoint lets Codex and the Responses SDK attach.

OpenAI's Codex CLI only speaks the /v1/responses format. PleumRouter accepts requests in this format as-is, so you can attach Codex CLI (and the OpenAI Responses SDK) to PleumRouter.

POST/v1/responses

Connecting#

Set the base URL to https://apirouter.pleum.ai/v1 and the API key to your plm_ key. In Codex, set wire_api = "responses" so it calls this endpoint.

responses.ts

OpenAI Responses API (Codex)

import OpenAI from "openai";

const client = new OpenAI({
  apiKey: "plm_xxxxxxxxxxxxxxxx",
  baseURL: "https://apirouter.pleum.ai/v1",
});

const response = await client.responses.create({
  model: "gpt-5.5",
  input: "Why is the sky blue?",
});

console.log(response.output_text);
POST/v1/responses/{request_id}/feedback
POST /v1/responses/{request_id}/feedback is a separate routing-feedback endpoint, not Responses creation. It requires a dashboard-session JWT; an inference plm_ key cannot call it. request_id is the value of the X-Request-Id response header, and the body must include the required field rating (1 for a thumbs-up, -1 for a thumbs-down).
feedback
curl https://apirouter.pleum.ai/v1/responses/$REQUEST_ID/feedback \
  -H "Authorization: Bearer $PLEUM_SESSION_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"rating": 1}'

# -> {"ok": true}

Request body#

ParameterTypeRequiredDescription
modelstringRequiredModel ID. See the full list at GET /v1/models.
inputstring | arrayRequiredA string, or an array of items (message / function_call / function_call_output).
instructionsstringOptionalPrepended as a system message.
max_output_tokensintegerOptionalDefault 4096. A value above the model's maximum output (max_output) is lowered to that maximum instead of failing. The request returns 400 only when input plus output cannot fit the context window.
temperaturenumberOptionalSampling temperature.
top_pnumberOptionalNucleus sampling.
streambooleanOptionalIf true, returns a Responses SSE streaming response.
toolsarrayOptionalResponses flat function tools ({type:"function", name, description, parameters}) are converted. Non-function tools (e.g. web_search) are silently dropped.
tool_choicestring | objectOptionalString auto | none | required, or {type:"function", name}.
parallel_tool_callsbooleanOptionalWhether parallel tool calls are allowed.
metadataobjectOptionalAccepted but not used.
modelstringRequired
inputstring | InputItem[]Required
typestringOptional
rolestringOptional
contentstring | Part[]Optional
call_idstringOptional
namestringOptional
argumentsstringOptional
outputstring | object[]Optional
instructionsstringOptional
max_output_tokensintegerOptional

Minimum 1. There is no global upper bound. A value above the model's max_output is lowered to that maximum instead of failing; a 400 is returned only when input plus output cannot fit the context window.

default: 4096

temperaturenumberOptional
top_pnumberOptional
streambooleanOptional

default: false

toolsobject[]Optional
typestringOptional
namestringOptional
parametersobjectOptional
tool_choicestring | objectOptional
parallel_tool_callsbooleanOptional
metadataobjectOptional

Accepted but not used.

reasoningobjectOptional
effortstringOptional
modestringOptional

enum: standard pro

reasoning_effortstringOptional
reasoning_modestringOptional

enum: standard pro

service_tierstringOptional

Passed only to OpenAI-family providers. Models that support it list service_tier in supported_parameters on GET /v1/models.

enum: auto default flex background priority fast ultrafast

request
curl https://apirouter.pleum.ai/v1/responses \
  -H "Authorization: Bearer $PLEUM_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "gpt-5.5",
    "instructions": "You are a helpful assistant.",
    "input": [
      {
        "type": "message",
        "role": "user",
        "content": "Hello"
      }
    ],
    "max_output_tokens": 4096,
    "stream": false
  }'

Response#

A non-streaming response returns the assistant message in the output array. Each message's content consists of output_text parts, and usage includes input_tokens / output_tokens / total_tokens. Cost is returned in the X-Cost-Krw / X-Cost-Usd response headers, not the body. reasoning and prompt_cache_key are applied to the request. The other extra fields Codex sends (text, store, previous_response_id, include) are accepted but ignored.

200 OK
{
  "id": "resp_9f3c2b7a5e1d4c8a9b0e6d7f1a2b3c4d",
  "object": "response",
  "created_at": 1735689600,
  "status": "completed",
  "model": "gpt-5.5",
  "output": [
    {
      "id": "msg_abc123",
      "type": "message",
      "status": "completed",
      "role": "assistant",
      "content": [
        {"type": "output_text", "text": "Hi!", "annotations": []}
      ]
    }
  ],
  "usage": {
    "input_tokens": 12,
    "output_tokens": 5,
    "total_tokens": 17
  }
}

Streaming#

With stream: true, Responses SSE events are sent — response.created, then response.in_progress, then response.output_item.added / response.content_part.added / response.output_text.delta, then response.output_text.done / response.output_item.done, and finally response.completed with the full usage. Codex reads completed items from response.output_item.done and determines termination from response.completed. There are no cost headers on a stream.

Responses SSE stream
event: response.created
data: {"type":"response.created","sequence_number":0,"response":{"id":"resp_abc","object":"response","status":"in_progress","model":"gpt-5.5","output":[]}}

event: response.in_progress
data: {"type":"response.in_progress","sequence_number":1,"response":{"id":"resp_abc","object":"response","status":"in_progress","model":"gpt-5.5","output":[]}}

event: response.output_item.added
data: {"type":"response.output_item.added","sequence_number":2,"output_index":0,"item":{"id":"msg_abc","type":"message","status":"in_progress","role":"assistant","content":[]}}

event: response.content_part.added
data: {"type":"response.content_part.added","sequence_number":3,"item_id":"msg_abc","output_index":0,"content_index":0,"part":{"type":"output_text","text":"","annotations":[]}}

event: response.output_text.delta
data: {"type":"response.output_text.delta","sequence_number":4,"item_id":"msg_abc","output_index":0,"content_index":0,"delta":"Hi"}

event: response.output_text.delta
data: {"type":"response.output_text.delta","sequence_number":5,"item_id":"msg_abc","output_index":0,"content_index":0,"delta":"!"}

event: response.output_text.done
data: {"type":"response.output_text.done","sequence_number":6,"item_id":"msg_abc","output_index":0,"content_index":0,"text":"Hi!"}

event: response.content_part.done
data: {"type":"response.content_part.done","sequence_number":7,"item_id":"msg_abc","output_index":0,"content_index":0,"part":{"type":"output_text","text":"Hi!","annotations":[]}}

event: response.output_item.done
data: {"type":"response.output_item.done","sequence_number":8,"output_index":0,"item":{"id":"msg_abc","type":"message","status":"completed","role":"assistant","content":[{"type":"output_text","text":"Hi!","annotations":[]}]}}

event: response.completed
data: {"type":"response.completed","sequence_number":9,"response":{"id":"resp_abc","object":"response","status":"completed","model":"gpt-5.5","output":[{"id":"msg_abc","type":"message","status":"completed","role":"assistant","content":[{"type":"output_text","text":"Hi!","annotations":[]}]}],"usage":{"input_tokens":12,"output_tokens":5,"total_tokens":17}}}

Compact#

POST/v1/responses/compact

OpenAI server compact (POST /v1/responses/compact) uses opaque encrypted_content items. This gateway does not mint those items. The same chat auth returns 501 with the error code compact_not_supported. Use Codex local compact.

Built-in tools like web_search are not forwarded and are silently dropped. Only {type:"function"} tools are converted and passed to the model.