Skip to Content
API referenceDecisions

Decisions API

The Decisions API lets a model make typed decisions about a piece of content instead of generating text. You provide the content to evaluate and a set of questions, and the model returns a structured answer for each one: the probability of yes/no, a single pick from a list of options, or a score on a graded scale, along with per-option probabilities and a confidence value.

It is built for classification, routing, moderation, scoring, filtering, and any other case where your code needs to branch directly on the result. The model can only answer with the options and levels you define, never anything outside them, so there is no free-form text to parse.

When using a decision model for the first time, it is recommended to read the Jev guide first, which covers quick start, question design, response fields, and scenario examples. This page is the field-level reference.

Endpoints

All three endpoints serve the same models with the same pricing; they differ only in request and response format. Pick the one that matches your client:

EndpointFormatBest for
POST https://api.ofox.ai/v1/decisionsOfoxAI unified format (questions as an array)cURL, any HTTP client, the OpenAI SDK
POST https://api.ofox.ai/openai/v1/decisionsSame as aboveProjects that already set the OpenAI SDK base_url to https://api.ofox.ai/openai/v1
POST https://api.ofox.ai/typesafe/v1/systemoneOfficial TypeSafe System One format (questions as an object)The official TypeSafe SDK, or code written against the official TypeSafe docs

Authentication works the same as the other endpoints: Authorization: Bearer <your OFOXAI_API_KEY>. Only non-streaming requests are supported; each request returns all answers synchronously.

Available models

Model IDDescription
typesafe/jev-latestTypeSafe Jev, a dedicated decision model. Text or JSON input only, 64K context. Can be shortened to jev-latest
openai/gpt-6-lunaWorks on all three endpoints; can read images (pass input_image in the message array)

For the full list of models that support this API, see the models page . Calling it with a regular chat model (such as openai/gpt-4o) returns endpoint_not_supported.

Unified format: /v1/decisions

Request parameters

ParameterTypeRequiredDescription
modelstring✅Model ID, e.g. typesafe/jev-latest
inputstring | object | array✅The content to evaluate; see Input format
questionsarray✅List of questions, each a question object. Answers are returned in the same order
safety_identifierstring—A stable end-user ID; only applies to OpenAI models

Input format

input accepts three forms:

  • Text: a single string.
    "input": "Customer message: I was charged twice, nobody has answered my two emails, and I need a refund today."
  • Structured data: a JSON object, passed to the model as-is. Questions can reference field names in backticks, such as `message`.
    "input": { "ticket_id": 4812, "message": "I was charged twice.", "plan": "pro" }
  • Message array: [{ "role", "content" }], where content is a string or a list of content blocks. Only input_text and input_image blocks are supported. Images only work with models that can read them. Jev does not read images; sending one returns 400.

Question object

FieldApplies toDescription
typeAllpredicate (yes/no), choice (single choice), or score (graded score)
nameAllOptional but recommended. Echoed back in the answer so you can match them up. Must be unique within a request
instructionsAllThe question itself. A string, or a JSON object containing the question and reference data
criteriapredicateOptional. { "true": "...", "false": "..." } describing what yes and no each mean
choiceschoiceRequired. Array of options, each { "value": "billing", "description": "Charges, refunds" }; description is optional. Up to 255 options
levelsscoreRequired. Array of levels ordered from lowest to highest, each { "label": "low", "description": "..." }. 2–10 levels

Request examples

Terminal
curl https://api.ofox.ai/v1/decisions \ -H "Authorization: Bearer $OFOX_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "typesafe/jev-latest", "input": "Customer message: I was charged twice, nobody has answered my two emails, and I need a refund today.", "questions": [ { "type": "predicate", "name": "is_frustrated", "instructions": "Is the customer frustrated?" }, { "type": "choice", "name": "category", "instructions": "Which category does this ticket belong to?", "choices": [ { "value": "billing", "description": "Charges and refunds" }, { "value": "bug", "description": "Product issue" }, { "value": "other", "description": "Other" } ] }, { "type": "score", "name": "urgency", "instructions": "How quickly does a human need to respond?", "levels": [ { "label": "low", "description": "Within a week is fine" }, { "label": "medium", "description": "Should respond soon" }, { "label": "high", "description": "Must respond today" } ] } ] }'

Response format

{ "model": "typesafe/jev-latest", "answers": [ { "type": "predicate", "name": "is_frustrated", "probability": 0.97 }, { "type": "choice", "name": "category", "choice": "billing", "confidence": 1, "probabilities": [ { "value": "billing", "probability": 1 }, { "value": "bug", "probability": 0 }, { "value": "other", "probability": 0 } ] }, { "type": "score", "name": "urgency", "score": 2, "confidence": 1, "legend": { "0": "low: Within a week is fine", "1": "medium: Should respond soon", "2": "high: Must respond today" }, "probabilities": [ { "value": 0, "label": "low", "probability": 0 }, { "value": 1, "label": "medium", "probability": 0 }, { "value": 2, "label": "high", "probability": 1 } ] } ], "usage": { "prompt_tokens": 407, "completion_tokens": 72, "total_tokens": 479 } }

answers maps one-to-one to questions, in the same order. Fields for each answer type:

TypeFieldDescription
predicateprobabilityProbability that the answer is yes, 0–1
choicechoiceThe option with the highest probability
probabilitiesProbability for each option; sums to 1
confidenceHow certain the model is about this decision, 0–1; see Probability and confidence
scorescoreProbability-weighted level value, starting from 0. It can fall between two levels (e.g. 1.43)
legendMapping from level index to description
probabilitiesProbability for each level
confidenceSame as above

TypeSafe native format: /typesafe/v1/systemone

Request and response formats match the official TypeSafe API , so you can use the TypeSafe SDK directly or migrate existing code. Compared with the unified format, the differences are:

Unified format /v1/decisionsTypeSafe native format
Content to evaluateinputstate
QuestionsArray, identified by nameObject, where each key is the question ID
Yes/no questionstype: "predicate", answer field probabilitytype: "noul", answer field noul
Options and levelschoices / levels arraysBoth go in criteria: an {option: description} object for choice, an array of description strings for score
Usage fieldsprompt_tokens / completion_tokensinput_tokens / output_tokens
Terminal
curl https://api.ofox.ai/typesafe/v1/systemone \ -H "Authorization: Bearer $OFOX_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "jev-latest", "state": "Help! My payouts have been failing for 3 days.", "questions": { "is_urgent": { "type": "noul", "instructions": "Does this convey urgency?" }, "department": { "type": "choice", "instructions": "Which team should handle this?", "criteria": { "billing": "Payments, invoicing, refunds", "technical": "Bugs, outages, integrations", "sales": "Pricing, upgrades" } }, "frustration": { "type": "score", "instructions": "How frustrated is the customer?", "criteria": ["Calm", "Frustrated", "Very angry"] } } }'
{ "model": "typesafe/jev-latest", "answers": { "is_urgent": { "type": "noul", "noul": 0.95 }, "department": { "type": "choice", "choice": "billing", "confidence": 0.85, "probabilities": { "billing": 0.9, "technical": 0.1, "sales": 0 } }, "frustration": { "type": "score", "score": 1.03, "confidence": 0.95, "legend": { "0": "Calm", "1": "Frustrated", "2": "Very angry" }, "probabilities": { "0": 0, "1": 0.97, "2": 0.03 } } }, "usage": { "input_tokens": 399, "output_tokens": 73 } }

SDK integration

OpenAI SDK

The official OpenAI SDK provides client.decisions.create(). Point base_url at https://api.ofox.ai/v1 and use the unified format for the request body. See the Python tab above for an example. You need an SDK version that includes the Decisions API (tested with openai Python 3.31.0).

TypeSafe SDK

With the official TypeSafe SDK, set base_url to https://api.ofox.ai/typesafe and replace api_key with your OfoxAI API Key. The rest of your code stays the same:

typesafe_sdk.py
# pip install typesafe-sdk import os from typesafe_sdk import TypeSafeClient, Noul, Choice, Score with TypeSafeClient(base_url="https://api.ofox.ai/typesafe", api_key=os.environ["OFOX_API_KEY"]) as client: r = client.system_one( model="jev-latest", state={"message": "I was charged twice, nobody has answered my two emails, and I need a refund today."}, questions={ "urgent": Noul(instructions="Is the customer asking for this to be handled today?"), "dept": Choice( instructions="Which team should handle this?", criteria={"billing": "Charges, invoices, refunds", "technical": "Bugs, integrations", "sales": "Pricing, upgrades"}, ), "anger": Score(instructions="How upset is the customer?", criteria=["Calm", "Upset but polite", "Very angry"]), }, ) print(r.nouls["urgent"].noul) # 0.98 print(r.choices["dept"].choice) # billing print(r.scores["anger"].score) # 1.56

Probability and confidence

  • Probability answers “what is the answer”: probability and probabilities are the model’s calibrated probabilities for each possible answer.
  • Confidence answers “should I trust this decision”: confidence is derived from the probability distribution and is higher when the distribution is more concentrated. If two options each sit at 0.5, choice still returns one of them, but confidence will be low.

A common pattern is to set a threshold in your code: act automatically when confidence is high, and route to a human or a stronger model for review when it is low.

Pricing

Billing is per token; see the model page  for rates. typesafe/jev-latest bills input tokens only; output is not billed (completion_tokens / output_tokens are still returned).

All questions in a request share the same input, so putting multiple questions in one request is much cheaper and faster than splitting them across separate calls.

Limits

ItemLimit
Request bodyUp to 32 MiB
Context64K tokens for Jev; exceeding it returns 400
Choice optionsUp to 255
Score levels2–10
JSON nestingUp to 64 levels each for input/state, instructions, and criteria
StreamingNot supported

Common errors

HTTP · typeError messageCauseFix
400 invalid_request_errorquestion "a" has kind choice and requires criteria optionsA choice question has no choicesAdd the options array
400 invalid_request_errorquestion name "a" is used more than onceTwo questions share the same nameUse unique names
400 invalid_request_errorToo many score levels. Must have at most 10 levels.A score question has more than 10 levelsMerge levels, or split into multiple questions
400 invalid_request_errordecision input carries an "input_image" part, which Typesafe cannot readAn image was sent to JevRemove the image, or switch to a model that can read images
400 invalid_request_errorInvalid request payloadThe TypeSafe native format (state + object-style questions) was sent to /v1/decisionsSwitch to the unified format, or call /typesafe/v1/systemone instead
400 endpoint_not_supportedModel 'openai/gpt-4o' does not support the /v1/decisions endpoint on this platform.The model is not a decision modelUse one of the available models
404 model_not_foundModel 'typesafe/jev-9' not foundWrong model IDUse typesafe/jev-latest
404 invalid_request_errorUnsupported API endpoint.The path was written as /v1/systemoneThe TypeSafe native endpoint is /typesafe/v1/systemone

For other general errors, see Error handling.

Last updated on