GlexirDocs
Dashboard

API

Responses

The Responses API generates text from a model. It handles multi-turn state, reasoning, structured output and function calling. It is the recommended API for new work, and the only one that serves -pro models and tool calling on gpt-6-astra and gpt-6.1-sol.

The endpoint is OpenAI-compatible: POST https://api.glexir.com/v1/responses. Requests and responses use OpenAI's format, with the Glexir differences listed under What Glexir changes.

Create a response

import Glexir from "@glexir/sdk";

const glexir = new Glexir({ apiKey: process.env.GLEXIR_API_KEY });

const response = await glexir.responses.create({
  model: "gpt-5.4-mini",
  instructions: "You are terse.",
  input: "Name three planets.",
});

console.log(response.output_text);
console.log(response.usage);

glexir.responses.create(body, options?) returns APIPromise<Response>. With stream: true it returns APIPromise<Stream<ResponseStreamEvent>> instead; see Streaming.

output_text is added by the SDK. It joins the text of every output_text part in the output. The API does not send it, so it is missing if you call the endpoint without the SDK.

Operations

SDK methodHTTPReturns
responses.create(body, options?)POST /v1/responsesResponse, or Stream<ResponseStreamEvent> with stream: true
responses.stream(params, options?)POST /v1/responses with stream: true, or GET /v1/responses/{id}?stream=true to resumeResponseStream
responses.parse(body, options?)POST /v1/responsesPromise<ParsedResponse<T>>
responses.retrieve(id, query?, options?)GET /v1/responses/{id}Response, or a stream with stream: true
responses.delete(id, options?)DELETE /v1/responses/{id}typed as void
responses.cancel(id, options?)POST /v1/responses/{id}/cancelResponse
responses.compact(body, options?)POST /v1/responses/compactCompactedResponse
responses.inputItems.list(id, query?, options?)GET /v1/responses/{id}/input_itemsPagePromise<ResponseItem>
responses.inputTokens.count(body?, options?)POST /v1/responses/input_tokensInputTokenCountResponse

Every method takes request options as its last argument: { signal, timeout, maxRetries, headers, idempotencyKey }.

Retrieve, delete, cancel and input item calls work only on responses created through your Glexir organization. Any other ID returns 404 (No response found with id '...').

Create parameters

ResponseCreateParams is ResponseCreateParamsNonStreaming | ResponseCreateParamsStreaming. Both extend ResponseCreateParamsBase. Unknown fields are sent unchanged, so new OpenAI parameters work before the SDK types include them.

ResponseCreateParamsBase
modelResponsesModelrequired
A text model ID, such as gpt-5.4-mini. Models priced in Glexir's price book are accepted; see Models.
inputstring | ResponseInputItem[]optional
A string, or a list of input items: messages, earlier output items, function call outputs and so on.
instructionsstring | nulloptional
System or developer instructions. Not carried over by previous_response_id; send them on every turn.
streamboolean | nulloptional
Stream the response as server-sent events. With true, create() returns a Stream.
previous_response_idstring | nulloptional
Continue from a stored response. Do not combine with conversation.
conversationstring | { id: string } | nulloptional
A conversation whose items are prepended to the input, and to which the input and output are appended. See Conversations.
storeboolean | nulloptional
Store the response so you can retrieve it, chain from it or list its input items. The gateway forwards your value unchanged; set it explicitly. See store.
backgroundboolean | nulloptional
Run asynchronously. Poll with retrieve(), or stream with stream: true. See Background responses.
includeResponseIncludable[] | nulloptional
Extra output to include: reasoning.encrypted_content, message.output_text.logprobs, message.input_image.image_url, or any other string.
reasoningReasoning | nulloptional
effort (none, minimal, low, medium, high, xhigh, max), summary (auto, concise, detailed), context (auto, current_turn, all_turns) and mode (standard, pro).
textResponseTextConfigoptional
format: { type: "text" }, { type: "json_object" } or { type: "json_schema", name, schema, description?, strict? }. verbosity: low, medium or high.
toolsTool[]optional
Function, custom and namespace tools only. See Tools.
tool_choiceToolChoiceoptional
none, auto, required, { type: "function", name }, { type: "custom", name }, or { type: "allowed_tools", mode, tools }.
parallel_tool_callsboolean | nulloptional
Allow the model to call several tools in one turn.
max_output_tokensnumber | nulloptional
Upper bound on output tokens, including reasoning tokens.
max_tool_callsnumber | nulloptional
Upper bound on tool calls in one response.
metadataRecord<string, string> | nulloptional
Up to 16 key/value pairs. Keys up to 64 characters, values up to 512.
temperaturenumber | nulloptional
Sampling temperature.
top_pnumber | nulloptional
Nucleus sampling.
top_logprobsnumber | nulloptional
0 to 20. Requires include: ["message.output_text.logprobs"].
service_tierServiceTier | nulloptional
auto, default, flex, scale, priority, fast or ultrafast. See Service tier.
prompt_cache_keystringoptional
Groups requests that share a prompt prefix. The gateway scopes it to your organization; see What Glexir changes.
prompt_cache_optionsResponsePromptCacheOptions | nulloptional
mode (implicit or explicit), ttl (for example 30m), prewarm, comparison_response_id.
prompt_cache_retention"in_memory" | "24h" | nulloptional
Deprecated. Use prompt_cache_options.ttl.
context_managementContextManagement[] | nulloptional
[{ type: "compaction", compact_threshold? }] compacts the context automatically when it exceeds compact_threshold tokens.
truncation"auto" | "disabled" | nulloptional
Deprecated. Use context_management.
moderationModerationConfig | nulloptional
Inline moderation of input and output: { model: "omni-moderation-latest", policy?: { input?: { mode }, output?: { mode } } }, where mode is score or block.
safety_identifierstringoptional
A stable ID for your end user. The gateway replaces it with a hashed value; see What Glexir changes.
stream_options{ include_obfuscation?: boolean } | nulloptional
Streaming only. Controls the obfuscation padding field on delta events.
userstringoptional
Deprecated. Use safety_identifier and prompt_cache_key. The gateway uses it as the end-user ID when safety_identifier is missing, then removes it.
promptobject | nulloptional
Rejected. Dashboard prompt templates are not available on Glexir; send instructions instead.

Input items

input takes a string or an array of ResponseInputItem:

ItemShape
EasyInputMessage{ role: "user" | "assistant" | "system" | "developer", content: string | ResponseInputContent[], phase? }
ResponseInputMessage{ type?: "message", role: "user" | "system" | "developer", content: ResponseInputContent[] }
ResponseOutputMessageAn assistant message from an earlier response's output.
ResponseReasoningItemA reasoning item from an earlier response. Replay it unchanged.
ResponseFunctionToolCall / ResponseFunctionCallOutputA function call and your result: { type: "function_call_output", call_id, output }.
ResponseCustomToolCall / ResponseCustomToolCallOutputA custom tool call and your result.
ResponseCompactionItem{ type: "compaction", encrypted_content } from compact(). Replay it unchanged.
ResponseCompactionTrigger{ type: "compaction_trigger" }. Asks the model to compact now. Must be the last item.
ResponseItemReference{ type?: "item_reference", id }. Points to a stored item.
ResponseConfigurationUpdate{ type: "configuration_update", reasoning?: { effort } }. Changes reasoning effort for later turns.

Content parts (ResponseInputContent):

  • { type: "input_text", text }
  • { type: "input_image", detail, image_url?, file_id? }, where detail is low, high, auto or original, and image_url is a URL or a data: URL.
  • { type: "input_file", file_url?, file_data?, file_id?, filename?, detail? } for PDFs and other files.

Any part can carry prompt_cache_breakpoint: { mode: "explicit" } to mark an explicit cache breakpoint (gpt-5.6 and later).

TypeScript
import Glexir from "@glexir/sdk";

const glexir = new Glexir();

const response = await glexir.responses.create({
  model: "gpt-5.4-mini",
  input: [
    {
      role: "user",
      content: [
        { type: "input_text", text: "What is in this image, and what does the PDF say?" },
        { type: "input_image", detail: "auto", image_url: "https://example.com/cat.png" },
        { type: "input_file", file_url: "https://example.com/report.pdf" },
      ],
    },
  ],
});

console.log(response.output_text);

file_id must be a file you uploaded through Glexir (Files). Any other file ID returns 404.

Input the gateway rejects

The gateway returns 400 with code unsupported_on_glexir for:

  • Audio input parts (type: "input_audio"). Use Audio for transcription.
  • Input items that only come from OpenAI-hosted tools: file_search_call, web_search_call, computer_call, computer_call_output, code_interpreter_call, image_generation_call, local_shell_call, local_shell_call_output, shell_call, shell_call_output, apply_patch_call, apply_patch_call_output, mcp_list_tools, mcp_approval_request, mcp_approval_response, mcp_call, tool_search_call, tool_search_output, program, program_output, agent_message, multi_agent_call, multi_agent_call_output.
  • prompt (dashboard prompt templates).

The Response object

Response
idstringoptional
The response ID, for example resp_....
object"response"optional
Always response.
created_atnumberoptional
Unix timestamp in seconds.
completed_atnumber | nulloptional
When the response finished.
modelstringoptional
The model that served the request.
statusResponseStatusoptional
queued, in_progress, completed, incomplete, failed or cancelled.
outputResponseOutputItem[]optional
Messages, reasoning items, function calls, custom tool calls and compaction items.
output_textstringoptional
Added by the SDK. All output text joined together.
usageResponseUsageoptional
input_tokens, input_tokens_details.cached_tokens, input_tokens_details.cache_write_tokens, output_tokens, output_tokens_details.reasoning_tokens, total_tokens. Glexir bills from these numbers.
errorResponseError | nulloptional
{ code, message } when status is failed.
incomplete_details{ reason?: string } | nulloptional
Why the response is incomplete: max_output_tokens, max_messages, content_filter, steered or another string.
service_tierServiceTier | nulloptional
The tier that actually served the response. Glexir bills at this tier.
conversation{ id: string } | nulloptional
The conversation this response belongs to.
previous_response_idstring | nulloptional
The response this one continues.
backgroundboolean | nulloptional
Whether it ran in the background.
moderationobject | nulloptional
Moderation results for input and output when you set moderation.
_request_idstring | nulloptional
Added by the SDK as a non-enumerable property: the x-request-id header. Quote it in support requests.

The object also echoes request settings: instructions, metadata, parallel_tool_calls, temperature, top_p, tool_choice, tools, max_output_tokens, max_tool_calls, prompt_cache_key, reasoning, safety_identifier, text, top_logprobs and truncation.

Multi-turn conversations

You have three ways to carry context between turns.

Replay the output yourself (stateless). Send store: false and pass the previous output items back as input. Reasoning items come back with encrypted_content; replay them unchanged.

TypeScript
import Glexir from "@glexir/sdk";

const glexir = new Glexir();

const first = await glexir.responses.create({ model: "gpt-5.4-mini", input: "Pick a number.", store: false });

const second = await glexir.responses.create({
  model: "gpt-5.4-mini",
  store: false,
  input: [...first.output, { role: "user", content: "Double it." }],
});

console.log(second.output_text);

Chain with previous_response_id. Store the first response, then point the next request at it. Resend instructions each turn.

TypeScript
import Glexir from "@glexir/sdk";

const glexir = new Glexir();

const first = await glexir.responses.create({ model: "gpt-5.4-mini", input: "Pick a number.", store: true });

const second = await glexir.responses.create({
  model: "gpt-5.4-mini",
  previous_response_id: first.id,
  input: "Double it.",
  store: true,
});

console.log(second.output_text);

Use a conversation. Create one with conversations.create() and pass its ID as conversation. Items are added to it automatically.

Store

store decides whether OpenAI keeps the response. You need a stored response to call retrieve(), chain with previous_response_id or list inputItems.

The gateway forwards store exactly as you send it and does not set a default. Set it explicitly on every request: store: false for stateless calls, store: true when you need any of the above.

Responses are tied to the Glexir organization that created them, whatever the value of store. Another organization's response ID returns 404.

Tools

Glexir supports tools that your code runs:

ToolShape
FunctionTool{ type: "function", name, description?, parameters?, strict?, output_schema?, defer_loading?, async? }
CustomTool{ type: "custom", name, description?, format?, defer_loading?, async? }. format is { type: "text" } or { type: "grammar", syntax: "lark" | "regex", definition }.
NamespaceTool{ type: "namespace", name, description, tools }. tools may hold only function and custom tools. Calls carry the namespace.

Tools the gateway rejects

Any other tool type returns 400 with code unsupported_on_glexir. That includes every OpenAI-hosted tool: web search, file search, code interpreter, MCP, image generation, shell and computer use. The same check applies inside a namespace, to tool_choice, and to allowed_tools entries: they may reference only function and custom tools.

JSON
{
  "error": {
    "message": "Tool type \"web_search\" is not supported. Glexir supports function and custom tools only.",
    "type": "invalid_request_error",
    "param": "tools[0]",
    "code": "unsupported_on_glexir"
  }
}

Function calling

Run the tool yourself and send the result back as a function_call_output item with the same call_id.

TypeScript
import Glexir, { type ResponseInputItem } from "@glexir/sdk";

const glexir = new Glexir();

const tools = [
  {
    type: "function" as const,
    name: "get_weather",
    description: "Current temperature for a city.",
    parameters: {
      type: "object",
      properties: { city: { type: "string" } },
      required: ["city"],
      additionalProperties: false,
    },
    strict: true,
  },
];

const input: ResponseInputItem[] = [{ role: "user", content: "What's the weather in Lagos?" }];
const first = await glexir.responses.create({ model: "gpt-5.4-mini", input, tools, store: false });

input.push(...first.output);
for (const item of first.output) {
  if (item.type !== "function_call") continue;
  const { city } = JSON.parse(item.arguments) as { city: string };
  input.push({ type: "function_call_output", call_id: item.call_id, output: JSON.stringify({ city, celsius: 31 }) });
}

const second = await glexir.responses.create({ model: "gpt-5.4-mini", input, tools, store: false });
console.log(second.output_text);

Structured output

glexir.responses.parse(body, options?) creates a response and parses its JSON when text.format.type is json_schema or json_object. It returns ParsedResponse<T>: the Response plus output_parsed: T | null.

TypeScript
import Glexir, { toStrictJsonSchema } from "@glexir/sdk";

const glexir = new Glexir();

interface Person {
  name: string;
  age: number | null;
}

const schema = toStrictJsonSchema({
  type: "object",
  properties: { name: { type: "string" }, age: { type: ["integer", "null"] } },
  required: ["name"],
});

const response = await glexir.responses.parse<Person>({
  model: "gpt-5.4-mini",
  input: "Ada Lovelace, 36",
  text: { format: { type: "json_schema", name: "person", schema, strict: true } },
});

console.log(response.output_parsed?.name);
  • options is ParseOptions<T>: the usual request options plus validate?: (value: unknown) => T, for example a zod schema's parse.
  • output_parsed is null when the model refused, or when the format is not JSON.
  • It throws LengthFinishReasonError when incomplete_details.reason is max_output_tokens, and ContentFilterFinishReasonError when it is content_filter.
  • toStrictJsonSchema(schema) adds additionalProperties: false to every object and makes every property required. It throws StrictSchemaError if an optional property isn't nullable, or if the schema uses a keyword strict mode doesn't support, such as oneOf, if or patternProperties.

Service tier

service_tier picks the processing tier: auto, default, flex, scale, priority, fast or ultrafast.

  • The tier on the returned response is the one that served it. fast and priority usually come back as priority.
  • Glexir bills at the tier OpenAI reports. Glexir prices four tiers: standard, flex, fast (fast and priority) and ultrafast. auto, default, scale and any unknown tier bill at standard. A tier with no price for that model bills at standard.
  • Your organization must be allowed to use the tier you ask for, and the model must have a price at that tier. Otherwise the request fails with 403 tier_not_allowed (param: "service_tier") before it reaches the model.

See Pricing for prices.

Retrieve a response

TypeScript
import Glexir from "@glexir/sdk";

const glexir = new Glexir();

const response = await glexir.responses.retrieve("resp_123", { include: ["reasoning.encrypted_content"] });
console.log(response.status, response.output_text);

retrieve(responseId, query?, options?). query is ResponseRetrieveParams plus stream:

includeResponseIncludable[]optional
Extra output to include.
include_obfuscationbooleanoptional
Streaming only. Include obfuscation padding.
streambooleanoptional
With true, returns Stream<ResponseStreamEvent> and replays a background response's events.
starting_afternumberoptional
With stream: true, replay only events after this sequence number. Background responses only.

Retrieving a finished background response also settles its bill.

Background responses

Set background: true to return right away while the model works. Poll retrieve() until the status is terminal, or stream it. Set store: true so you can retrieve it later.

TypeScript
import Glexir from "@glexir/sdk";

const glexir = new Glexir();

let response = await glexir.responses.create({
  model: "gpt-5.4",
  input: "Write a long report on tidal energy.",
  background: true,
  store: true,
});

while (response.status === "queued" || response.status === "in_progress") {
  await new Promise((resolve) => setTimeout(resolve, 2000));
  response = await glexir.responses.retrieve(response.id);
}

console.log(response.status, response.output_text);
  • Glexir reserves credit for a background response when you create it and holds it for up to six hours. The bill settles when the response finishes, through a retrieve, a cancel, a stream replay or OpenAI's webhook.
  • To resume a background stream, see Resuming a background stream.

Cancel a response

TypeScript
import Glexir from "@glexir/sdk";

const glexir = new Glexir();

const cancelled = await glexir.responses.cancel("resp_123");
console.log(cancelled.status);

cancel(responseId, options?) cancels a background response and returns it. Calling it again returns the final response.

Delete a response

TypeScript
import Glexir from "@glexir/sdk";

const glexir = new Glexir();

await glexir.responses.delete("resp_123");

delete(responseId, options?) is typed APIPromise<void>. The gateway answers with { id, object: "response", deleted: true } (or OpenAI's body), and the SDK returns that object at run time.

List input items

responses.inputItems.list(responseId, query?, options?) lists the input items of a stored response. It returns a PagePromise<ResponseItem>; iterate it with for await to walk every page. See Pagination.

TypeScript
import Glexir from "@glexir/sdk";

const glexir = new Glexir();

for await (const item of glexir.responses.inputItems.list("resp_123", { order: "asc", limit: 50 })) {
  console.log(item.type);
}
InputItemListParams
afterstringoptional
Item ID to start after.
limitnumberoptional
Items per page.
order"asc" | "desc"optional
Sort order.
includeResponseIncludable[]optional
Extra fields to include.

Count input tokens

responses.inputTokens.count(body?, options?) counts the input tokens a request would use, without running the model. It is not billed.

TypeScript
import Glexir from "@glexir/sdk";

const glexir = new Glexir();

const { input_tokens } = await glexir.responses.inputTokens.count({
  model: "gpt-5.4-mini",
  input: "How many tokens is this?",
});

console.log(input_tokens);

InputTokenCountParams takes the request-shaping fields of a create call, all optional: model, input, instructions, previous_response_id, conversation, reasoning, text, tools, tool_choice, parallel_tool_calls and truncation. It returns { object: "response.input_tokens", input_tokens: number }. The same tool and input checks as create() apply, and model, when present, must be a text model.

Compact a conversation

responses.compact(body, options?) shrinks a long conversation into an opaque compaction item. Pass the returned output as input on later turns.

TypeScript
import Glexir from "@glexir/sdk";

const glexir = new Glexir();

const compacted = await glexir.responses.compact({
  model: "gpt-5.4-mini",
  previous_response_id: "resp_123",
});

const next = await glexir.responses.create({
  model: "gpt-5.4-mini",
  input: [...compacted.output, { role: "user", content: "Summarise where we are." }],
  store: false,
});

console.log(next.output_text);
ResponseCompactParams
modelResponsesModel | nullrequired
The model. The gateway requires it.
inputResponseInput | nulloptional
The conversation to compact.
instructionsstring | nulloptional
Instructions.
previous_response_idstring | nulloptional
Compact the history of a stored response.
prompt_cache_keystring | nulloptional
Prompt cache key, scoped to your organization by the gateway.
prompt_cache_options{ mode?, ttl? } | nulloptional
Prompt cache options.
service_tierServiceTier | nulloptional
Processing tier.

It returns CompactedResponse: { id, object: "response.compaction", created_at, output, usage }. Compaction is billed from usage like any other request.

What Glexir changes

The gateway forwards your request to OpenAI with these changes:

  • End-user ID. It replaces safety_identifier with a hashed ID derived from your organization and the value you sent (or user when safety_identifier is missing). It always sets one, and removes user.
  • Prompt cache key. It prefixes prompt_cache_key with a hash of your organization, so cache entries are never shared with other organizations. Without a key it uses default. The result is cut to 64 characters.
  • Compaction and token counts. POST /responses/compact scopes prompt_cache_key the same way but forwards safety_identifier unchanged. POST /responses/input_tokens forwards both unchanged.
  • Rejected input. Hosted tools, hosted-tool input items, audio input and prompt return 400 unsupported_on_glexir.
  • Ownership. Response, conversation and file IDs must belong to your organization; others return 404. Combining objects that live on different upstream accounts returns 409 cross_account_reference.
  • Credit. Before the request runs, Glexir reserves an estimate of its cost from your credit. A request with a conversation reserves extra for about 50,000 tokens of earlier context. If you lack credit, the request fails with 402. See Credits & billing.

Errors

StatuscodeCause
400unsupported_on_glexirHosted tool, hosted-tool input item, audio input, or prompt.
400model_not_foundmodel missing, not a text model, or not enabled for your organization.
402credit_balance_exhausted, spend_limit_exceededNot enough credit, or a spend limit reached.
403account_suspendedYour organization is suspended.
403model_not_pricedThe model is not in Glexir's price book yet.
403tier_not_allowedThe service_tier or model is not available to your organization.
404nullThe response, conversation or file ID is not yours.
409cross_account_referenceThe referenced objects live on different upstream accounts.
429rate_limit_exceeded, concurrency_limit_exceededToo many requests.

Errors from OpenAI pass through in the same { error: { message, type, param, code } } shape. See HTTP error codes and Errors & retries.