OpenAI Decisions API: how to route a support ticket in one request
A step-by-step build of a support-ticket router on OpenAI's Decisions API, now that it is generally available: the request fields, the predicate, choice and score question types, the billing, and the jobs it is wrong for.
Nihar Rout · · Updated · 9 min read · 34 views
If you are classifying text with a chat prompt and parsing the JSON that comes back, the OpenAI Decisions API replaces that with one typed request: you send the ticket once, attach up to 400 questions about it, and get back probabilities, choices and scores instead of prose. It went generally available on October 22, 2026, and only gpt-6-luna runs on it. Everything below comes from OpenAI's own docs, read on October 23, 2026.
This is a build guide, not a review. The sections go in the order you will actually hit them: what the endpoint returns, the three question types, the request itself, the bill, and the cases where you should use something else.
What the OpenAI Decisions API returns, and what it will not do for you
The endpoint is a POST to /v1/decisions. OpenAI's Decisions API guide describes it as evaluating text, images and JSON and returning typed answers "about 10x faster than the Responses API" - that speed figure is OpenAI's own, and the guide publishes no latency measurements behind it. TechCrunch's October 22 report puts response times at roughly 100 to 180 milliseconds, down from one to three seconds, and says the language-tutor app Speak cut its time between actions from 1.4 seconds to 0.13 seconds. Those are the vendor's and a customer's figures, reported by TechCrunch, not ours.
Two things it does not do. It does not call your tools: the guide is explicit that Decisions evaluates the input and your application runs any actions. And it does not write anything - there is no free-text output to parse, which is the whole point.
The response is an answers array, and each answer carries the name you gave its question, so you read results by key rather than by position. An answer can also come back with type set to refusal, and OpenAI's own examples check for that type before reading any other field. Write that branch first; a router that assumes every answer has a value will fail on the first refusal.
The three question types: predicate, choice and score
Every question you send needs a unique name, a type, and instructions. The type decides the shape of the answer.
| Question type | What you define | What comes back | Use it for |
|---|---|---|---|
| predicate | A condition stated as a question | probability, 0 to 1 | Flags: is this billing, is this abusive, is the box damaged |
| choice | A list of choices, each with a value and a description | The selected choice, a probabilities list, and confidence | Routing to one queue, one owner, one category |
| score | 2 to 10 ordered levels, each with a label and description | A probability-weighted score, per-level probabilities, and confidence | Severity, priority, rubric grading |
Two details in that table bite people. First, confidence is documented for choice and score answers; the predicate example in the guide returns probability only, so do not build a pipeline that expects a confidence number on every answer type. Second, a score is a probability-weighted average of the level indices, which start at 0 - the guide's severity example has three levels (cosmetic, workaround available, fully blocked), so a result of 1.4 is a real and expected output, not a bug. Round it yourself, and decide deliberately which way.
How to build the router, step by step
- Send the ticket once as input. It can be a plain string, or an ordered array of messages, tool calls and tool outputs - match each tool output to its call with call_id. User messages accept text, images and JSON; developer and system messages accept input text only, and system messages are treated as developer messages.
- Add one question per decision, not one per request. The guide's advice is to "write questions around observable criteria" and to separate different concerns into different questions: a choice for the queue, a predicate for "is this a refund request", a score for severity, all against the same ticket.
- Give every choice a description, and add a fallback. The guide asks for distinct meanings with descriptions explaining when each applies, and recommends including a fallback option such as "other" and sending those to a general review queue. In our view this is the step most likely to be skipped, and the consequence is mechanical: a choice question always returns one of your values, so an ambiguous ticket lands in whichever queue scored highest rather than in a human's lap.
- Read answers by name, checking for refusals first. In the Python SDK the call is client.decisions.create(...) with model, input and questions; the guide's example reads decision.answers[0], tests for a refusal, and only then prints the probability.
- Set your thresholds from labeled examples. OpenAI's guidance is to use labeled examples from your own application and to weigh the cost of false positives against false negatives - the docs set no default threshold, and there is no number anyone else can give you honestly.
- Split dependent decisions into separate requests. The guide says to send separate requests when a later decision depends on an earlier answer. Everything inside one request sees the same input and nothing else.
If you want per-candidate image judgements - three product photos, one verdict each - the guide's pattern is one question per candidate image, with the image in that question's instructions.
What the OpenAI Decisions API costs, and where the saving comes from
Uncached input is $0.10 per 1M tokens for gpt-6-luna, output tokens are not charged, prompt cache writes are charged, and cache hits get discounted input pricing, per the guide. Regional processing premiums and long-context multipliers can apply on top. For comparison, OpenAI's API pricing page lists the same model through its standard endpoints at $0.10 input, $0.01 cached input and $0.50 output per 1M tokens.
So the headline rate is not the saving - the input price is the same number. The saving is structural, and it comes from two places:
- Questions are not requests. A request holds between 1 and 400 questions, and the guide states that the num_model_requests field counts requests, not individual questions, so a request with several questions counts once. Forty classifications over one ticket are one request in your usage metrics and one copy of the input, not forty copies.
- The shared input can be cached. An implicit cache breakpoint sits at the end of the shared input. The reusable prefix must contain at least 1,024 tokens, question content does not count toward that minimum, and the prefix has to stay byte-identical between requests. You can partition reuse with prompt_cache_key, or mark boundaries with prompt_cache_breakpoint - but breakpoints are not supported inside question instructions. Check cached_tokens and cache_write_tokens under usage.input_tokens_details; both are already counted in usage.input_tokens.
If your prompt is a 300-token ticket and nothing else, there is no 1,024-token prefix to cache and the pricing is close to a wash against a tight structured-output call. On those numbers we'd move for the latency and the response shape, not for the rate card. The teams we'd expect to see a real cost difference are the ones whose bill is dominated by long shared context - a taxonomy, a policy document, a style guide re-sent on every classification - which is the same lesson as the billable unit in AI customer support pricing.
When Structured Outputs or function calling still win
OpenAI's own guide draws the line, and it is worth quoting rather than guessing at: use Structured Outputs with the Responses API when you need an object that follows your own JSON schema, and use function calling when the model must request a tool call with arguments. Decisions answers questions; it does not fill in a schema you designed or hand you arguments.
The hard limits are worth checking before you plan a migration. Only gpt-6-luna is supported. file_id inputs, files, audio and item references are not supported. input_json parts are allowed only in user messages. Score questions need between 2 and 10 levels. The guide documents no streaming and no tool use on this endpoint.
Skip it entirely if your task's output is a draft reply, a summary or any text a human will read. Also skip it if you are on an older model for a reason - there is no version of this endpoint that runs your current model.
What changed at GA on October 22, and who should re-read their code
OpenAI's API changelog dates the beta to October 6, 2026, a native GPT-Live integration to October 15, and general availability to October 22. If you built against the beta, four things moved:
- The per-request question limit rose from 200 to 400.
- Prompt caching across requests arrived, with the cache-discount rules above.
- input_json lets you pass structured data directly, and images can now be hosted at public HTTP or HTTPS URLs as well as inline base64 data URLs.
- Conversation history, organization usage reporting through GET /v1/organization/usage/decisions (admin key with api.usage.read) and Private Link were added.
On compliance, the guide lists Zero Data Retention and HIPAA for eligible customers, data residency in all supported API regions, and regional processing in the United States and Europe (EEA and Switzerland). Confirm your own eligibility with OpenAI rather than from this page - these terms change, and the guide is the current word, not us.
One piece of context for anyone choosing between vendors: TechCrunch reports that OpenAI did not train a dedicated decision model but reconfigured Luna for faster inference, that Box, Datadog, Ramp and Speak used the API in trials, and that TypeSafe's rival Jev models are the most widely queried decision models on OpenRouter. On the two independent indices TechCrunch cites, the AIM System One Index and the Artificial Analysis Decision Index, Jev placed seventh and third while OpenAI's model placed eighth and fourteenth. We have not tested either model, and we would not treat a benchmark placing as a substitute for running your own tickets through both.
Where to start, if you move one decision first
Start with the single decision that is costing you the most latency, not the whole pipeline. One choice question with a fallback, measured against a labeled set you already have, tells you in an afternoon whether the typed answer is better than the JSON you are parsing today. Then decide whether the rest follows.
If you are shopping the layer rather than the endpoint, Upfynd lists 157 products in LLMs & AI Infrastructure and 208 in AI Agents as of October 2026, including the OpenAI API itself and the gateways that sit in front of several providers. Model pricing moves quickly in both directions - the Gemini API price increase is the live example - so whatever you build, keep the classifier call behind an interface you can repoint.
Frequently asked questions
What is the OpenAI Decisions API?
It is an OpenAI endpoint, a POST to /v1/decisions, that evaluates text, images or JSON and returns typed answers rather than prose: a probability, a selected choice, or a rubric score. It became generally available on October 22, 2026, and runs only on the gpt-6-luna model.
How much does the OpenAI Decisions API cost?
Uncached input costs $0.10 per 1M tokens on gpt-6-luna, output tokens are not charged, cache writes are charged and cache hits get discounted input pricing. Regional processing premiums and long-context multipliers can apply, so check OpenAI's current pricing page before budgeting.
When should I use Decisions instead of Structured Outputs?
OpenAI's guide says to use Structured Outputs with the Responses API when you need an object matching your own JSON schema, and function calling when the model must request a tool call with arguments. Decisions fits fixed questions with fixed answer shapes, such as routing or scoring.
Does the Decisions API support images?
Yes. You can pass images as inline base64 data URLs or as public HTTP or HTTPS URLs, in a user message alongside text, or inside an individual question's instructions. The file_id input type, audio and plain file uploads are not supported on this endpoint.
How many questions can one Decisions request hold?
Between 1 and 400 questions, up from 200 during the public beta. OpenAI's docs note that the num_model_requests usage field counts requests rather than individual questions, so one request carrying forty questions is recorded and billed as a single model request.
Products in this article
About the author
Nihar Rout
CEO & Co-founder