> ## Documentation Index
> Fetch the complete documentation index at: https://docs.portkey.ai/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Decisions

> Get typed judgments (probability, choice, or score) from models through the Prisma AIRS AI Gateway's /v1/decisions endpoint.

The Decisions API returns a **typed judgment** instead of generated text. Send the content to judge and a set of `questions`. The model returns one typed answer per question.

Use it for classification, routing, scoring, and yes/no checks, where a structured answer is needed and not free text.

> [!NOTE]
>
> `/v1/decisions` does not support streaming. A `stream` parameter in the request is ignored.

## Quick Start

Set `model` to `@integration-slug/model`. The integration holds the provider credentials, so no provider headers are needed.

Request shape depends on the provider. Workers AI (Cloudflare), TypeSafe, and OpenRouter use the **Jev shape**. OpenAI and Azure OpenAI use the **OpenAI shape**. The examples below are the same three questions in each shape.

```sh Jev shape theme={"system"}
curl --request POST \
  --url https://aigw.portkey.ai/v1/decisions \
  --header 'Content-Type: application/json' \
  --header "Authorization: Bearer $PORTKEY_API_KEY" \
  --data '{
  "model": "@your-cf-integration-slug/model",
  "state": "I was charged twice for my order. Please return the extra charge.",
  "questions": {
    "refund_requested": {
      "type": "noul",
      "instructions": "Does the customer ask for a refund?"
    },
    "department": {
      "type": "choice",
      "instructions": "Which department should handle this complaint?",
      "criteria": {
        "billing": "Payments and refunds.",
        "technical": "Product problems.",
        "shipping": "Delivery and tracking.",
        "other": "All other requests."
      }
    },
    "severity": {
      "type": "score",
      "instructions": "How severe is this issue?",
      "criteria": [
        "Cosmetic: no lost functionality.",
        "Workaround available: a task fails, but another way works.",
        "Fully blocked: a task fails with no workaround."
      ]
    }
  }
}'
```

```sh OpenAI shape theme={"system"}
curl --request POST \
  --url https://aigw.portkey.ai/v1/decisions \
  --header 'Content-Type: application/json' \
  --header "Authorization: Bearer $PORTKEY_API_KEY" \
  --data '{
  "model": "@your-openai-integration-slug/gpt-6-luna",
  "input": "I was charged twice for my order. Please return the extra charge.",
  "questions": [
    {
      "type": "predicate",
      "name": "refund_requested",
      "instructions": "Does the customer ask for a refund?"
    },
    {
      "type": "choice",
      "name": "department",
      "instructions": "Which department should handle this complaint?",
      "choices": [
        {"value": "billing", "description": "Payments and refunds."},
        {"value": "technical", "description": "Product problems."},
        {"value": "shipping", "description": "Delivery and tracking."},
        {"value": "other", "description": "All other requests."}
      ]
    },
    {
      "type": "score",
      "name": "severity",
      "instructions": "How severe is this issue?",
      "levels": [
        {"label": "Cosmetic", "description": "No lost functionality."},
        {"label": "Workaround available", "description": "A task fails, but another way works."},
        {"label": "Fully blocked", "description": "A task fails with no workaround."}
      ]
    }
  ]
}'
```

Responses follow the shape of the request (values are illustrative):

```json Jev shape theme={"system"}
{
  "model": "<model>",
  "answers": {
    "refund_requested": { "type": "noul", "noul": 0.95 },
    "department": {
      "type": "choice",
      "choice": "billing",
      "probabilities": { "billing": 0.93, "technical": 0.03, "shipping": 0.01, "other": 0.03 },
      "confidence": 0.9
    },
    "severity": {
      "type": "score",
      "score": 1.1,
      "legend": {
        "0": "Cosmetic: no lost functionality.",
        "1": "Workaround available: a task fails, but another way works.",
        "2": "Fully blocked: a task fails with no workaround."
      },
      "probabilities": { "0": 0.1, "1": 0.7, "2": 0.2 },
      "confidence": 0.55
    }
  },
  "usage": { "input_tokens": 162, "output_tokens": 0 },
  "provider": "workers-ai"
}
```

```json OpenAI shape theme={"system"}
{
  "model": "gpt-6-luna",
  "answers": [
    { "type": "predicate", "name": "refund_requested", "probability": 0.95 },
    {
      "type": "choice",
      "name": "department",
      "choice": "billing",
      "probabilities": [
        { "value": "billing", "probability": 0.93 },
        { "value": "technical", "probability": 0.03 },
        { "value": "shipping", "probability": 0.01 },
        { "value": "other", "probability": 0.03 }
      ],
      "confidence": 0.9
    },
    {
      "type": "score",
      "name": "severity",
      "score": 1.1,
      "probabilities": [
        { "value": 0, "label": "Cosmetic", "probability": 0.1 },
        { "value": 1, "label": "Workaround available", "probability": 0.7 },
        { "value": 2, "label": "Fully blocked", "probability": 0.2 }
      ],
      "confidence": 0.55
    }
  ],
  "usage": { "input_tokens": 162, "output_tokens": 0, "total_tokens": 162 },
  "provider": "openai"
}
```

Either shape works with any provider. See [Switching Shapes](#switching-shapes).

## Supported Providers

| Provider | Slug | Native shape | Notes |
| :- | :- | :- | :- |
| [TypeSafe](https://docs.portkey.ai/docs/aigw/integrations/llms/typesafe.md) | `typesafe` | Jev | `jev-latest` is the default model |
| [OpenRouter](https://docs.portkey.ai/docs/aigw/integrations/llms/openrouter.md) | `openrouter` | Jev | Routes to Jev models |
| [Workers AI](https://docs.portkey.ai/docs/aigw/integrations/llms/workers-ai.md) | `workers-ai` | Jev | Cloudflare model ID, for example `@your-cf-integration-slug/model` |
| [OpenAI](https://docs.portkey.ai/docs/aigw/integrations/llms/openai.md) | `openai` | OpenAI | `gpt-6-luna` |

Any provider accepts either request shape. The AI Gateway converts the request to the provider's native shape and converts the answers back. See [Switching Shapes](#switching-shapes).

## Request Shapes

The shape is detected from the body. A body that mixes fields from both shapes, or matches neither, returns `400`.

| Field | Jev shape | OpenAI shape |
| :- | :- | :- |
| Content to judge | `state`: string, object, or array | `input`: string, or user messages with `input_text` and `input_image` parts |
| Questions | `questions`: map of question ID to question | `questions`: array. Each question has a `name` |
| Yes/no type | `noul` | `predicate` |
| Choice options | `criteria`: map of label to description, or array of labels | `choices`: array of `{ value, description }` |
| Score levels | `criteria`: ordered array of labels or `{ label, description }` | `levels`: ordered array of `{ label, description }`, lowest to highest |
| `model` | Optional. Defaults to `jev-latest` | Required |
| Other | | `safety_identifier` |

## Question Types

Each question sets a `type`. The type sets the shape of the answer:

| Jev type | OpenAI type | Use for | Answer |
| :- | :- | :- | :- |
| `noul` | `predicate` | A yes/no judgment | Jev: `{ noul }`. OpenAI: `{ probability }`. A 0–1 probability |
| `choice` | `choice` | One label from a fixed set | `{ choice, probabilities, confidence }` |
| `score` | `score` | A position on an ordered scale | `{ score, probabilities, confidence }`, plus `legend` in the Jev shape |

A `score` is the probability-weighted average of the level indices, so it can fall between levels.

### Refusals

Any question can come back as `{ "type": "refusal" }` while other questions in the same request still return answers. In the OpenAI shape the refusal also carries the question `name`. Check each answer's `type` before reading its result.

The AI Gateway also returns a refusal for a question the provider returned no answer for, when converting a Jev-shaped answer to the OpenAI shape.

## Response Shapes

| | Jev shape | OpenAI shape |
| :- | :- | :- |
| `answers` | Map keyed by question ID | Array, in question order |
| Choice and score `probabilities` | Map of label to probability | Array of `{ value, probability }`. Score entries also carry `label` |
| `usage` | `input_tokens`, `output_tokens` | Provider usage, passed through |

Every response includes `provider`, the slug that served the request.

## Switching Shapes

The AI Gateway converts between shapes, so one request body works across providers. To fail over between a Jev provider and an OpenAI-native one, keep the same text-only body and switch the model per target.

```json Fallback config theme={"system"}
{
  "strategy": { "mode": "fallback" },
  "targets": [
    { "override_params": { "model": "@your-typesafe-slug/jev-latest" } },
    { "override_params": { "model": "@your-openai-slug/gpt-6-luna" } }
  ]
}
```

Conversion rules:

* **Jev `state`** that is an object or array is JSON-stringified into `input`.
* **`noul` criteria** are appended to the question's `instructions`, since a `predicate` has no criteria field.
* **OpenAI `input`** is flattened to text for Jev providers. Only `input_text` parts are kept.
* **Unnamed questions** are keyed `q0`, `q1`, and so on.

Jev providers return a `400` for requests they cannot serve:

* `input_image` parts. Jev is text-only.
* `safety_identifier`.
* Duplicate question `name` values, since names become response keys.

## Errors

Upstream errors return the standard AI Gateway error shape. The message is prefixed with the provider slug, and `provider` is included:

```json theme={"system"}
{
  "error": {
    "message": "workers-ai error: model not found",
    "type": "invalid_request_error",
    "param": null,
    "code": null
  },
  "provider": "workers-ai"
}
```

A `200` response from the provider without an `answers` field also returns an error, not an empty result.

## Gateway Features

Decisions requests go through the same gateway as other endpoints:

* **Routing** — Retries, fallbacks, load balancing, and circuit breaking through [Configs](https://docs.portkey.ai/docs/aigw/product/ai-gateway/configs.md)
* **Caching** — [Simple and semantic caching](https://docs.portkey.ai/docs/aigw/product/ai-gateway/cache-simple-and-semantic.md)
* **Guardrails** — Before-request checks on the content to judge only: `state` in the Jev shape, or the text in `input` in the OpenAI shape. See [Guardrails for Decisions](https://docs.portkey.ai/docs/aigw/product/guardrails/decisions-guardrails.md)
* **Observability** — Logs, cost tracking, and analytics in [Observability](https://docs.portkey.ai/docs/aigw/product/observability.md)

## API Reference

* [Create a Decision](https://docs.portkey.ai/docs/aigw/api-reference/decisions/create-decisions.md) -- `POST /v1/decisions`

> [card] [TypeSafe](https://docs.portkey.ai/docs/aigw/integrations/llms/typesafe.md)
>
> Provider setup and pricing

> [card] [API Reference](https://docs.portkey.ai/docs/aigw/api-reference/decisions/create-decisions.md)
>
> Decisions API reference

> [card] [Universal API](https://docs.portkey.ai/docs/aigw/product/ai-gateway/universal-api.md)
>
> All API formats

> [card] [Guardrails for Decisions](https://docs.portkey.ai/docs/aigw/product/guardrails/decisions-guardrails.md)
>
> Scan the content to judge before it reaches the model


## Related topics

- [Create decisions](https://docs.portkey.ai/docs/aigw/api-reference/decisions/create-decisions.md)
- [Guardrails for Decisions Requests](https://docs.portkey.ai/docs/aigw/product/guardrails/decisions-guardrails.md)
- [Request Parameters Check](https://docs.portkey.ai/docs/aigw/integrations/guardrails/request-parameters-check.md)
- [TypeSafe (Jev)](https://docs.portkey.ai/docs/aigw/integrations/llms/typesafe.md)
- [Supported Endpoints & Capabilities](https://docs.portkey.ai/docs/aigw/product/guardrails/capabilities.md)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.