Realtime TTS-2 is live. Built for realtime conversation that feels human. Read the Realtime TTS-2 announcement

Decisions

Get typed answers your code can branch on (yes/no probabilities, picks from your options, and scores) in one request

Preview. The /alpha path and the request and response shape may change before this API is marked stable. See release stages.

The Decisions API runs a decision model that gives your code a structured answer instead of generated text. You send a state (the content to evaluate) and a map of named, typed questions. You get back one typed answer per question: a probability of yes for a noul question, one of your options for a choice question, or a position on your scale for a score question. Answers are never free text, so there is no output to parse or validate.

Use it when your code needs to branch on a judgment: classify or route a request, check a message against a policy, score a passage for relevance, or gate an action on the model's certainty. For free-form text, use chat completions or the Responses API instead.

Requests use your Inworld API key and are billed to your Inworld account.

EndpointPOST https://api.inworld.ai/alpha/decisions
ModelsBrowse Decision models in the public catalog
StreamingNot supported: the whole answer set comes back in one response
PricingSee the selected model in the model catalog

Choose a model

Browse inworld.ai/models and select Decisions for model IDs and pricing. Choose a decision model for typed judgments; a chat model that supports JSON output is not interchangeable with a Decisions API model. For images, choose a decision model with image input support. In the Decisions playground, compatible models have an Images label; the text-only typesafe/jev-latest example below cannot evaluate images.

How it works

  1. Select a decision model and set model to its API model ID.
  2. Send the content to evaluate in state and your named questions in questions.
  3. Read each answer under the same question ID and use it in your application logic.

Question types

Each entry in questions is keyed by an id you choose, and its answer comes back under the same id. Every question has a type and instructions. Each type defines its own criteria.

typeAskscriteriaAnswer fields
noulA yes/no questionOptional. {"true": "...", "false": "..."} describes what yes and no meannoul: the probability of yes, from 0 to 1
choicePick one option from a setRequired. An object mapping each option to its description, or to nullchoice, probabilities (sums to 1), confidence
scoreRate on ordered levelsRequired. An array of level descriptions, lowest firstscore (probability-weighted level index from 0, which can land between levels), legend, probabilities, confidence

All questions in a request are evaluated against the same state.

Quickstart

This example uses typesafe/jev-latest.

Run these examples on your server. Set INWORLD_API_KEY to the Base64 credentials copied from Portal or the CLI; see authentication.

curl
curl -X POST https://api.inworld.ai/alpha/decisions \
  -H "Authorization: Basic $INWORLD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "typesafe/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, new accounts"
        }
      }
    }
  }'

Response:

json
{
  "model": "typesafe/jev-1.13.0",
  "answers": {
    "is_urgent": { "type": "noul", "noul": 0.95 },
    "department": {
      "type": "choice",
      "choice": "billing",
      "probabilities": { "billing": 0.88, "technical": 0.12, "sales": 0.0 },
      "confidence": 0.81
    }
  },
  "usage": { "input_tokens": 318, "output_tokens": 34 },
  "metadata": {
    "attempts": [
      { "model": "typesafe/jev-1.13.0", "status_code": 200, "duration_ms": 212.4, "success": true }
    ],
    "generation_id": "0f5d3c4e-8f0b-4a53-9a55-2f3a6f0d8a1b",
    "total_duration_ms": 212
  }
}

Evaluate an image

Use image input to check a screenshot, classify a photo, or score visible evidence. The image is part of the shared state, so every question evaluates the same text and image.

In Portal's Decisions playground, select a model labeled Images, then load Screenshot check. Add, paste or drop a screenshot into the content area and run the example. It asks whether the checkout shows an error and which next step the application should consider.

For an API integration, encode the image as a data URL and include it directly in the state array beside the text, as in the example below. Remote image URLs are not accepted. See the image input contract for supported formats and fields.

Check a checkout screenshot

Example Shop checkout page with a "Payment declined" error saying the card has expired

Save the screenshot above as checkout-declined.png. In the same directory, install the Python dependency and set your API key:

bash
python -m pip install requests
export INWORLD_API_KEY="<your Base64 API key>"

Save the following as check_screenshot.py. It uses inworld/clef, an image-capable decision model; replace it only with another model that supports image input.

python
import base64
import os
from pathlib import Path
import requests

image = base64.b64encode(Path("checkout-declined.png").read_bytes()).decode("ascii")
response = requests.post(
    "https://api.inworld.ai/alpha/decisions",
    headers={"Authorization": f"Basic {os.environ['INWORLD_API_KEY']}"},
    json={
        "model": "inworld/clef",
        "state": [
            "A shopping agent took this screenshot right after it clicked Pay.",
            {"type": "image_url", "image_url": {"url": f"data:image/png;base64,{image}"}},
        ],
        "questions": {
            "error_shown": {
                "type": "noul",
                "instructions": "Does the screenshot show an error that must be fixed before continuing?",
            },
            "next_step": {
                "type": "choice",
                "instructions": "What should the agent do next?",
                "criteria": {
                    "continue": "The step succeeded: go on",
                    "retry": "A temporary problem: try again",
                    "change_payment": "The payment method was refused: use another",
                    "ask_user": "Needs information only the user knows",
                },
            },
        },
    },
    timeout=60,
)
response.raise_for_status()
answers = response.json()["answers"]
print(answers["error_shown"]["noul"])
print(answers["next_step"]["choice"])

Run it from the directory containing both files:

bash
python check_screenshot.py

The script prints a probability between 0 and 1, then one of the four next_step options. This screenshot shows a payment declined because the card expired: a useful answer should recognize the error and select change_payment. The exact probability can vary; evaluate the model on your own screenshots before choosing a threshold.

error_shown.noul is a probability, and next_step.choice is one of your supplied options. Your application defines thresholds and decides what action to take; the API does not execute the selected action.

Before sending larger images, resize or compress them: base64 increases request size, and accepted image counts and request sizes depend on the selected model. The playground accepts up to four images and may resize large photos. When copying its generated code, replace the <BASE64_IMAGE_n> placeholders with your encoded image bytes.

Use the answers in your application

The response's model is the provider-qualified model that answered: a specific version such as typesafe/jev-1.13.0, or the model family such as typesafe/jev when no version is reported. metadata reports attempts, generation_id and total_duration_ms.

The example returns answers.is_urgent.noul as a probability and answers.department.choice as one of the options you supplied. Your application decides what action to take: for example, send a request classified as billing to the billing queue, and flag it for priority review when the urgency probability exceeds your chosen threshold.

Choose thresholds using examples from your own workload. The model supplies the judgment; your code defines the action and any review or escalation rules.

Errors

Check the HTTP status and response content type before parsing the body. Decisions errors use {"error": {"message": "...", "type": "..."}}. Request validation returns 400 before sending the request to a model; these errors can also include error.param, which names the field to fix. See the error example.

Model errors relayed to your application keep their HTTP status, including 422, and use the same error format. Rate-limit and server errors use generic messages. Authentication, account, and API-key rate-limit errors can use a different body, so check the content type and preserve the status and body when reporting a failure.

The following describes error handling for the model used in the quickstart:

StatusMeaningWhat to do
400Invalid request, such as invalid JSON, a missing state or questions, an unknown question type, missing criteria, too many options, or an image the model cannot accept. Also returned when the workspace has zero data retention and the model cannot serve itFix the request as the error describes. For zero data retention, choose another model or use a workspace without it
401Missing or invalid Inworld API keyCheck the Authorization header
413Request body exceeds the accepted sizeSend less state, or split the questions across requests
422The model rejected input that passed request validationFix the request as the error describes
429, 503, 529Rate limited, at capacity or overloadedRetry with exponential backoff and honor Retry-After when present
502The model could not be reached or is unavailableRetry with exponential backoff
504No answer within the request timeoutRetry, or send fewer or smaller questions

Billing

Check the model catalog for the selected model's rates and billing units. The response reports usage.input_tokens and usage.output_tokens; reported usage does not mean every token category is billed. The documented billing units for the example model are listed below.

Model capabilities and limits

Use the catalog to discover models. The table records documented limits for the example model; these limits do not define the contract for every decision model.

ModelQuestion typesInput formatsQuestion limitsRequest limitsBilling
typesafe/jev-latestnoul, choice, scorestate, instructions and criteria accept strings, objects or arraysUp to 255 choice options; 2 to 10 score levels10 MiB body; 60-second timeoutInput tokens only; failed or cut-off answers are not billed