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

Core Concepts

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 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: classifying or routing a request, checking a message against a policy, scoring a passage for relevance, or gating an action on how certain the model is. For free-form text, use chat completions or the Responses API instead.

Requests are answered by TypeSafe's Jev model, on your Inworld API key and bill.

EndpointPOST https://api.inworld.ai/alpha/decisions
Modeltypesafe/jev-latest
StreamingNot supported: the whole answer set comes back in one response
BillingInput tokens only; output tokens are not billed

Quickstart

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
  }
}

Question types

Each entry in questions is keyed by an id you choose, and its answer comes back under the same id. The ids are not sent to the model. 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 null. Up to 255 optionschoice, probabilities (sums to 1), confidence
scoreRate on ordered levelsRequired. An array of level descriptions, lowest first. 2 to 10 levelsscore (probability-weighted level index from 0, which can land between levels), legend, probabilities, confidence

state, instructions and every criterion accept a string, an object, or an array. To keep a long question readable, put the question in one field of an instructions object and the data it refers to in the others, and refer to those fields by name in backticks. All questions are answered against the same state in one pass, so asking several related questions in one request is cheaper and faster than one request per question. TypeSafe's guides to state, question types and confidence cover how to write them well.

Differences from TypeSafe's API

The request and answer bodies follow TypeSafe's System One API. Validation errors are returned with TypeSafe's status and body. The differences:

  • Path and credentials. Call https://api.inworld.ai/alpha/decisions with your Inworld API key. TypeSafe's SDKs call /v1/systemone, which Inworld does not serve, so call this endpoint over HTTP as shown above.
  • Model ids. Name the model typesafe/jev-latest, as you name other providers' models on Inworld Router. The bare jev-latest also works. The response's model is the exact version that answered, with the provider prefix, for example typesafe/jev-1.13.0.
  • Routing metadata. Every successful answer gets a metadata object with the same keys as chat completions: attempts, generation_id and total_duration_ms.

Limits and errors

StatusMeaningWhat to do
400Your workspace has zero data retention, and the Decisions API is not available for these workspaces. Nothing is sent to TypeSafeCall it from a workspace without zero data retention
401Missing or invalid Inworld API keyCheck the Authorization header
413The body is larger than 10 MiBSend less state, or split the questions across requests
422TypeSafe rejected the body, for example invalid JSON, an unknown question type, a missing criteria, or too many optionsFix the request as the error describes
429, 503, 529Rate limited, at capacity, or overloadedRetry with exponential backoff, and honor Retry-After when present
502TypeSafe could not be reached or is unavailableRetry with exponential backoff
504No answer within 60 secondsRetry, or send fewer or smaller questions

Errors that Inworld raises (400, 413, 502, 504, and a 503 when Inworld is at capacity) use the router's error format, {"error": {"message": "...", "type": "..."}}. A 401 has a plain-text body (Unauthorized). TypeSafe's validation and rate-limit errors, such as 422 and 429, use TypeSafe's status and body.

Billing

Decisions are billed per input token (usage.input_tokens) at the Jev rate, whatever version answers. Output tokens are reported but not billed. An answer that fails or is cut off is not billed.