Two endpoints
POST /v1/decisionstakes OpenAI’s Decisions format.POST /v1/systemonetakes the System One format, which Microsoft and Cloudflare use.
The models
GET /v1/models marks each one with a decisions block. It lists the routes, the question limit, and the price on each route.
gpt-6-luna is also a text model, so it keeps serving the text endpoints. The other three write no text, so a text endpoint refuses them with 400 model_surface_mismatch. A text model sent to a decision endpoint gets the same error.
Your own keys only
Decision models run on the provider keys you add in the dashboard.openaiuses your OpenAI key.foundryuses your Azure AI Foundry key and resource.cloudflareuses your Workers AI token and account ID.
400 decisions_byok_only. A missing key returns that route’s own error, such as 400 no_foundry_key.
On Foundry, the model field names a deployment, and we send the model ID you used. Name the deployment after the model: gpt-6-luna or microsoft-decision-1.
No Flex Race
Decision requests never race. OpenAI’s Decisions API refuses a flex tier, and System One has no tiers at all.- Send
"start_within": "default"in the body, orx-start-within: defaultas a header. - A duration returns
400 flex_model_not_capable. priorityorautoreturns400 tier_unsupported_on_decisions.- An API key with a deadline default works. Its fallback tier applies.
x-flexinference-routing-reason reads tier_direct, or chain_advanced when a backup served. Name backups in provider, the same as on the text endpoints. A route that answers 429, 5xx, or no connection passes the request to the next one.
Neither endpoint streams. "stream": true returns 400 unsupported_parameter.
OpenAI’s Decisions format
The System One format
How we translate
- A noul is a predicate. Its answer is a probability in both formats.
- A choice’s
criteriaobject becomeschoices, onevalueper label. - A score’s
criterialist becomeslevels. Each level’s label is its position,"0","1", and so on, the same key the answer’slegendandprobabilitiesuse. - System One names each question with its key. OpenAI names it with
nameand answers in a list, in question order. - A noul’s true and false
criteriahave no OpenAI field, so we add them to the instructions. - A System One question with no
instructionsgets one for its type, such as “Which option best fits the state?”. OpenAI requires instructions. - Structured state becomes one
input_jsonpart. OpenAI’s text and JSON parts join into one state string, and a single JSON part stays structured. - An OpenAI level becomes
"label: description"in System One. - OpenAI can refuse to answer a question. On
/v1/systemonethat answer is{ "type": "refusal" }under the question’s name. - For a System One model we drop
safety_identifierand the three prompt-cache fields. None of them changes an answer.
400 decision_translation_unsupported, before we call the provider.
- Images. Send them in the model’s own format:
input_imageparts forgpt-6-lunaon/v1/decisions, orimagesforclefon/v1/systemone. - A field the other format has no place for.
- A choice with one option, or a score with one level, for an OpenAI model. OpenAI needs at least two.
- More than 255 options for a System One model.
start_within, provider, stream, and include_cost. The answer is the provider’s own body.
What we check first
400 invalid_decision_request names the field that breaks a rule of its format:
inputorstateis missing.- A question count is outside the model’s range.
- Two questions share a name.
- A choice offers
trueand"true"as two options. - The body nests deeper than 64 levels, or holds a number JSON can’t carry.
Cost
Decision models bill input tokens only.gpt-6-lunaonopenai: $0.10 per million input tokens. Cache reads bill at $0.01 and cache writes at $0.125. All three double above 272,000 input tokens. We report the cost inx-flexinference-cost.clefcosts $0.24 and `clef-flash` $0.038 per million input tokens on Cloudflare’s price list. A serve on your own Cloudflare account carries no cost header, the same as every cloud route.- Microsoft publishes no rate for either Foundry model yet, so a Foundry serve carries no cost header.
usage.cost and usage.routing in its body. A same-format answer is the provider’s own body, so it reports cost on the header only.
Errors on /v1/systemone come back as { "detail": "...", "param": ..., "flexinference": { ... } }, where param names the field at fault. See Errors for every code.