> ## AI Agent Context
> Get the complete documentation index at: https://aistudio.google.com/llms.txt
> Use this file to discover all available pages.
> For the full documentation in a single file, fetch: https://aistudio.google.com/llms-full.txt

# Decisions API

Generative models produce text for people to read. When your code needs a
judgment to branch on, generating and parsing text adds latency and brittle
parsing logic.

The Decisions API evaluates typed questions against your data using
[Gemini Decision 1](/docs/models/gemini-decision-1) and returns calibrated
probabilities. It generates zero text tokens, so output token usage is always 0.
Your code can branch, sort, and route on the response directly.

## How it works  {% id="how-it-works" %}

Each call sends [shared input](/docs/decisions-api#input) and a map of
questions, and returns one typed answer per question:

![](https://www.gstatic.com/cloud-cms/55bb56725305bef6dd99ace3e16515c1.png)

Every question uses one of three [question types](/docs/decisions-api#question-types):

| Question type | Goal | Returns |
| :--- | :--- | :--- |
| [Yes/no (`noul`)](/docs/decisions-api#noul) | Check whether a statement holds | `noul` (0.01 to 0.99), `confidence` |
| [Choice (`choice`)](/docs/decisions-api#choice) | Pick one option from a fixed list | `choice`, `probabilities`, `confidence` |
| [Score (`score`)](/docs/decisions-api#score) | Rate input against ordered rubric levels | `score`, `probabilities`, `legend`, `confidence` |

Keep three ideas in mind when building with Gemini Decision 1:

*   **Parallel, isolated scoring:** Every question runs against the shared input
  in one forward pass. Questions can't see each other, and latency stays
  nearly flat when you
  [ask multiple questions](/docs/decisions-api#multiple-questions).
*   **Value plus confidence:** The answer tells your code what action fits.
  [Confidence](/docs/decisions-api#confidence) tells your code whether to run
  it automatically or escalate.
*   **Atomic checks, composed in code:** Ask narrow, single-purpose questions.
  Combine the answers with ordinary `if` statements and weights in code (see
  [Best practices](/docs/decisions-api#best-practices)).

## Quickstart  {% id="quickstart" %}

Requires SDK 3.2 or later (`pip install -U google-genai` or
`npm install @google/genai@latest`). Pass a model, shared input, and a map of
questions. Each question requires a type ([`noul`](/docs/decisions-api#noul) for
yes/no) and instructions:

{% tabs %}
  {% tab filename="decisions.py" label="Python" %}
  ```python
  from google import genai
  
  client = genai.Client(http_options={"api_version": "v1beta"})
  
  result = client.decisions.create(
      model="gemini-decision-1",
      input="The blue mug I ordered on Monday arrived cracked on Wednesday.",
      questions={
          "is_damaged": {
              "type": "noul",
              "instructions": "Did the item arrive damaged?",
          },
      },
  )
  
  answer = result.answers["is_damaged"]
  print(f"P(yes)={answer.noul:.2f} confidence={answer.confidence:.2f}")
  ```

  {% /tab %}

  {% tab filename="decisions.mjs" label="JavaScript" %}
  ```javascript
  import { GoogleGenAI } from "@google/genai";
  
  const ai = new GoogleGenAI({ apiVersion: "v1beta" });
  
  const result = await ai.decisions.create({
    model: "gemini-decision-1",
    input: "The blue mug I ordered on Monday arrived cracked on Wednesday.",
    questions: {
      is_damaged: {
        type: "noul",
        instructions: "Did the item arrive damaged?",
      },
    },
  });
  
  const answer = result.answers?.is_damaged;
  if (answer?.type === "noul") {
    console.log(`P(yes)=${answer.noul} confidence=${answer.confidence}`);
  }
  ```

  {% /tab %}

  {% tab filename="decisions.sh" label="REST" %}
  ```bash
  curl -X POST "https://generativelanguage.googleapis.com/v1beta/decisions" \
    -H "x-goog-api-key: $GEMINI_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "model": "gemini-decision-1",
      "input": "The blue mug I ordered on Monday arrived cracked on Wednesday.",
      "questions": {
        "is_damaged": {
          "type": "noul",
          "instructions": "Did the item arrive damaged?"
        }
      }
    }'
  ```

  {% /tab %}

{% /tabs %}

The API returns calibrated probabilities and token usage:

```json
{
  "answers": {
    "is_damaged": { "type": "noul", "noul": 0.99, "confidence": 0.99 }
  },
  "usage": {
    "total_input_tokens": 100,
    "input_tokens_by_modality": [{ "modality": "text", "tokens": 100 }],
    "total_output_tokens": 0,
    "total_tokens": 100
  }
}
```

## Question types  {% id="question-types" %}

### Yes or no (noul)  {% id="noul" %}

A yes/no question returns the calibrated probability that the answer is yes. Add
criteria to define what yes and no mean when the question alone is ambiguous.

{% tabs %}
  {% tab filename="decisions.py" label="Python" %}
  ```python
  from google import genai
  
  client = genai.Client(http_options={"api_version": "v1beta"})
  
  result = client.decisions.create(
      model="gemini-decision-1",
      input="Customer returned the sweater because they preferred green over blue.",
      questions={
          "is_defect": {
              "type": "noul",
              "instructions": "Is the customer reporting a product defect?",
              "criteria": {
                  "true_description": "The product itself is broken or faulty.",
                  "false_description": "Preference, sizing, shipping, or pricing complaint.",
              },
          },
      },
  )
  
  print(result.answers["is_defect"].noul)
  ```

  {% /tab %}

  {% tab filename="decisions.mjs" label="JavaScript" %}
  ```javascript
  import { GoogleGenAI } from "@google/genai";
  
  const ai = new GoogleGenAI({ apiVersion: "v1beta" });
  
  const result = await ai.decisions.create({
    model: "gemini-decision-1",
    input: "Customer returned the sweater because they preferred green over blue.",
    questions: {
      is_defect: {
        type: "noul",
        instructions: "Is the customer reporting a product defect?",
        criteria: {
          true_description: "The product itself is broken or faulty.",
          false_description: "Preference, sizing, shipping, or pricing complaint.",
        },
      },
    },
  });
  
  const answer = result.answers?.is_defect;
  if (answer?.type === "noul") console.log(answer.noul);
  ```

  {% /tab %}

  {% tab filename="decisions.sh" label="REST" %}
  ```bash
  curl -X POST "https://generativelanguage.googleapis.com/v1beta/decisions" \
    -H "x-goog-api-key: $GEMINI_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "model": "gemini-decision-1",
      "input": "Customer returned the sweater because they preferred green over blue.",
      "questions": {
        "is_defect": {
          "type": "noul",
          "instructions": "Is the customer reporting a product defect?",
          "criteria": {
            "true_description": "The product itself is broken or faulty.",
            "false_description": "Preference, sizing, shipping, or pricing complaint."
          }
        }
      }
    }'
  ```

  {% /tab %}

{% /tabs %}

Answer:

```json
{ "type": "noul", "noul": 0.03, "confidence": 0.97 }
```

{% callout type="note" %}
  Yes/no probabilities always fall between 0.01 and 0.99. Set thresholds inside
  that range, since a check above 0.99 never matches.

{% /callout %}

### Pick one option (choice)  {% id="choice" %}

A choice question scores a fixed set of options and returns both the top option
and the calibrated probability of every option (summing to 1). Criteria maps
each option ID to a description of when it applies. Use an empty string (`""`)
when the option ID is self-explanatory.

Before evaluation, the API sorts option keys alphabetically in UTF-8 byte
order. Changing key order in your JSON request doesn't change option positions,
and exact probability ties break to the alphabetically first key.

{% tabs %}
  {% tab filename="decisions.py" label="Python" %}
  ```python
  from google import genai
  
  client = genai.Client(http_options={"api_version": "v1beta"})
  
  result = client.decisions.create(
      model="gemini-decision-1",
      input="I was charged twice for my order.",
      questions={
          "department": {
              "type": "choice",
              "instructions": "Which department should handle this request?",
              "criteria": {
                  "billing": "Payments, invoices, and refunds.",
                  "technical": "Problems using the product.",
                  "shipping": "Delivery and tracking.",
                  "other": "Anything outside these categories.",
              },
          },
      },
  )
  
  answer = result.answers["department"]
  print(answer.choice, answer.confidence, answer.probabilities)
  ```

  {% /tab %}

  {% tab filename="decisions.mjs" label="JavaScript" %}
  ```javascript
  import { GoogleGenAI } from "@google/genai";
  
  const ai = new GoogleGenAI({ apiVersion: "v1beta" });
  
  const result = await ai.decisions.create({
    model: "gemini-decision-1",
    input: "I was charged twice for my order.",
    questions: {
      department: {
        type: "choice",
        instructions: "Which department should handle this request?",
        criteria: {
          billing: "Payments, invoices, and refunds.",
          technical: "Problems using the product.",
          shipping: "Delivery and tracking.",
          other: "Anything outside these categories.",
        },
      },
    },
  });
  
  const answer = result.answers?.department;
  if (answer?.type === "choice") {
    console.log(answer.choice, answer.confidence, answer.probabilities);
  }
  ```

  {% /tab %}

  {% tab filename="decisions.sh" label="REST" %}
  ```bash
  curl -X POST "https://generativelanguage.googleapis.com/v1beta/decisions" \
    -H "x-goog-api-key: $GEMINI_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "model": "gemini-decision-1",
      "input": "I was charged twice for my order.",
      "questions": {
        "department": {
          "type": "choice",
          "instructions": "Which department should handle this request?",
          "criteria": {
            "billing": "Payments, invoices, and refunds.",
            "technical": "Problems using the product.",
            "shipping": "Delivery and tracking.",
            "other": "Anything outside these categories."
          }
        }
      }
    }'
  ```

  {% /tab %}

{% /tabs %}

Answer:

```json
{
  "type": "choice",
  "choice": "billing",
  "probabilities": { "billing": 0.99, "shipping": 0.004, "other": 0.003, "technical": 0.002 },
  "confidence": 0.99
}
```

{% callout type="note" %}
  Choice questions always distribute probability across your options, even when
  none fits. Threshold confidence to catch low-certainty inputs, pair the
  question with a separate yes/no scope check, or add a catch-all option such as
  "other" with an explicit description. Avoid positional keys like
  "none_of_the_above": alphabetical sorting places it ahead of keys like
  "shipping" and "technical" instead of last.

{% /callout %}

### Rate on a scale (score)  {% id="score" %}

A score question rates the input across ordered levels. Criteria is an array of
non-empty level descriptions ordered from lowest to highest (2 to 255 levels,
with 2 to 10 recommended for most rubrics), indexed starting at 0.

The returned score is the probability-weighted average of the level indices, so
it can fall between levels, and legend maps each index back to its description.

{% tabs %}
  {% tab filename="decisions.py" label="Python" %}
  ```python
  from google import genai
  
  client = genai.Client(http_options={"api_version": "v1beta"})
  
  result = client.decisions.create(
      model="gemini-decision-1",
      input="Export fails in Safari but works in Chrome.",
      questions={
          "severity": {
              "type": "score",
              "instructions": "How severe is this issue for the user?",
              "criteria": [
                  "Cosmetic: appearance only, no lost functionality.",
                  "Workaround available: a task fails, but another way works.",
                  "Fully blocked: a task fails with no workaround.",
              ],
          },
      },
  )
  
  answer = result.answers["severity"]
  print(answer.score, answer.confidence, answer.probabilities)
  ```

  {% /tab %}

  {% tab filename="decisions.mjs" label="JavaScript" %}
  ```javascript
  import { GoogleGenAI } from "@google/genai";
  
  const ai = new GoogleGenAI({ apiVersion: "v1beta" });
  
  const result = await ai.decisions.create({
    model: "gemini-decision-1",
    input: "Export fails in Safari but works in Chrome.",
    questions: {
      severity: {
        type: "score",
        instructions: "How severe is this issue for the user?",
        criteria: [
          "Cosmetic: appearance only, no lost functionality.",
          "Workaround available: a task fails, but another way works.",
          "Fully blocked: a task fails with no workaround.",
        ],
      },
    },
  });
  
  const answer = result.answers?.severity;
  if (answer?.type === "score") {
    console.log(answer.score, answer.confidence, answer.probabilities);
  }
  ```

  {% /tab %}

  {% tab filename="decisions.sh" label="REST" %}
  ```bash
  curl -X POST "https://generativelanguage.googleapis.com/v1beta/decisions" \
    -H "x-goog-api-key: $GEMINI_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "model": "gemini-decision-1",
      "input": "Export fails in Safari but works in Chrome.",
      "questions": {
        "severity": {
          "type": "score",
          "instructions": "How severe is this issue for the user?",
          "criteria": [
            "Cosmetic: appearance only, no lost functionality.",
            "Workaround available: a task fails, but another way works.",
            "Fully blocked: a task fails with no workaround."
          ]
        }
      }
    }'
  ```

  {% /tab %}

{% /tabs %}

Answer:

```json
{
  "type": "score",
  "score": 1.12,
  "legend": {
    "0": "Cosmetic: appearance only, 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.03, "1": 0.83, "2": 0.15 },
  "confidence": 0.83
}
```

Because different probability distributions can produce the same expected
value (here 1.12, sitting just above level 1), check the per-level
probabilities and confidence alongside the score when inputs can split across
levels.

Use the score to rank inputs or filter candidate results against a rubric
threshold. When your code needs a discrete level, pick the entry with the
highest probability:

```python
level = max(answer.probabilities, key=answer.probabilities.get)  # "1"
print(answer.legend[level])  # "Workaround available: ..."
```

To compare scales with different numbers of levels, divide the score by the
highest level index to normalize it between 0 and 1.

## Ask multiple questions  {% id="multiple-questions" %}

Put independent questions about the same input in one request. Shared input
counts once per request regardless of how many questions you ask (each question
adds only its own instructions and criteria), and question types can be mixed.
This example routes a support ticket using order data and the customer message.

{% tabs %}
  {% tab filename="decisions.py" label="Python" %}
  ```python
  import json
  from google import genai
  
  client = genai.Client(http_options={"api_version": "v1beta"})
  
  order = {"order": {"id": "8821", "item": "headphones", "price_usd": 240}, "tier": "Gold"}
  message = {"message": "Audio cuts out on the left earcup. Fix it today or I cancel my membership."}
  
  result = client.decisions.create(
      model="gemini-decision-1",
      input=[
          {"type": "text", "text": json.dumps(order) + "\n"},
          {"type": "text", "text": json.dumps(message)},
      ],
      questions={
          "is_defect": {
              "type": "noul",
              "instructions": "Does `message` describe a hardware defect?",
          },
          "next_action": {
              "type": "choice",
              "instructions": "What is the right resolution given `tier` and `order`?",
              "criteria": {
                  "instant_refund": "Refund without return. Low value or clear fault.",
                  "replacement_shipment": "Ship a replacement. Customer returns the original.",
                  "troubleshooting_flow": "The issue may be fixable by the customer.",
                  "human_escalation": "",
              },
          },
          "churn_risk": {
              "type": "score",
              "instructions": "How likely is the customer to churn if the issue is not resolved now?",
              "criteria": [
                  "No churn signal",
                  "Mild frustration",
                  "Mentions alternatives",
                  "Threatens to cancel",
              ],
          },
      },
  )
  
  a = result.answers
  if a["is_defect"].noul > 0.9 and a["next_action"].confidence > 0.6:
      action = a["next_action"].choice
  else:
      action = "human_escalation"
  
  print(action, a["churn_risk"].score)
  ```

  {% /tab %}

  {% tab filename="decisions.mjs" label="JavaScript" %}
  ```javascript
  import { GoogleGenAI } from "@google/genai";
  
  const ai = new GoogleGenAI({ apiVersion: "v1beta" });
  
  const order = { order: { id: "8821", item: "headphones", price_usd: 240 }, tier: "Gold" };
  const message = { message: "Audio cuts out on the left earcup. Fix it today or I cancel my membership." };
  
  const result = await ai.decisions.create({
    model: "gemini-decision-1",
    input: [
      { type: "text", text: JSON.stringify(order) + "\n" },
      { type: "text", text: JSON.stringify(message) },
    ],
    questions: {
      is_defect: {
        type: "noul",
        instructions: "Does `message` describe a hardware defect?",
      },
      next_action: {
        type: "choice",
        instructions: "What is the right resolution given `tier` and `order`?",
        criteria: {
          instant_refund: "Refund without return. Low value or clear fault.",
          replacement_shipment: "Ship a replacement. Customer returns the original.",
          troubleshooting_flow: "The issue may be fixable by the customer.",
          human_escalation: "",
        },
      },
      churn_risk: {
        type: "score",
        instructions: "How likely is the customer to churn if the issue is not resolved now?",
        criteria: ["No churn signal", "Mild frustration", "Mentions alternatives", "Threatens to cancel"],
      },
    },
  });
  
  const { is_defect, next_action, churn_risk } = result.answers ?? {};
  let action = "human_escalation";
  if (
    is_defect?.type === "noul" && next_action?.type === "choice" &&
    (is_defect.noul ?? 0) > 0.9 && (next_action.confidence ?? 0) > 0.6
  ) {
    action = next_action.choice ?? action;
  }
  console.log(action, churn_risk?.type === "score" ? churn_risk.score : undefined);
  ```

  {% /tab %}

  {% tab filename="decisions.sh" label="REST" %}
  ```bash
  curl -X POST "https://generativelanguage.googleapis.com/v1beta/decisions" \
    -H "x-goog-api-key: $GEMINI_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "model": "gemini-decision-1",
      "input": [
        { "type": "text", "text": "{\"order\": {\"id\": \"8821\", \"item\": \"headphones\", \"price_usd\": 240}, \"tier\": \"Gold\"}\n" },
        { "type": "text", "text": "{\"message\": \"Audio cuts out on the left earcup. Fix it today or I cancel my membership.\"}" }
      ],
      "questions": {
        "is_defect": {
          "type": "noul",
          "instructions": "Does `message` describe a hardware defect?"
        },
        "next_action": {
          "type": "choice",
          "instructions": "What is the right resolution given `tier` and `order`?",
          "criteria": {
            "instant_refund": "Refund without return. Low value or clear fault.",
            "replacement_shipment": "Ship a replacement. Customer returns the original.",
            "troubleshooting_flow": "The issue may be fixable by the customer.",
            "human_escalation": ""
          }
        },
        "churn_risk": {
          "type": "score",
          "instructions": "How likely is the customer to churn if the issue is not resolved now?",
          "criteria": ["No churn signal", "Mild frustration", "Mentions alternatives", "Threatens to cancel"]
        }
      }
    }'
  ```

  {% /tab %}

{% /tabs %}

Response:

```json
{
  "answers": {
    "is_defect": { "type": "noul", "noul": 0.94, "confidence": 0.94 },
    "next_action": {
      "type": "choice",
      "choice": "human_escalation",
      "probabilities": {
        "human_escalation": 0.76,
        "replacement_shipment": 0.18,
        "troubleshooting_flow": 0.04,
        "instant_refund": 0.02
      },
      "confidence": 0.76
    },
    "churn_risk": {
      "type": "score",
      "score": 2.99,
      "legend": {
        "0": "No churn signal",
        "1": "Mild frustration",
        "2": "Mentions alternatives",
        "3": "Threatens to cancel"
      },
      "probabilities": { "0": 0.0, "1": 0.0, "2": 0.01, "3": 0.99 },
      "confidence": 0.99
    }
  },
  "usage": {
    "total_input_tokens": 324,
    "input_tokens_by_modality": [{ "modality": "text", "tokens": 324 }],
    "total_output_tokens": 0,
    "total_tokens": 324
  }
}
```

Some decisions depend on another, for example picking a repair category only
if the item is damaged. Either send a second request after you read the first
answer, or ask both questions in one request and ignore the answer you don't
need.

## Answers, probabilities, and confidence  {% id="confidence" %}

Each answer includes calibrated probabilities and a confidence score:

*   **Top value:** Probability of yes for binary questions, most likely option
  for choice questions, or probability-weighted expected level for score
  questions.
*   **Probabilities:** On choice and score answers, a map of calibrated
  probabilities across all options or levels (summing to 1). For yes/no
  answers, the probability of no is 1 minus the yes probability.
*   **Confidence:** Estimated probability (from 0 to 1) that the top answer is
  right. Equals the top outcome's probability, or `max(noul, 1 - noul)` for
  yes/no questions.

Use the answer value to pick an action and confidence to decide whether to run
it automatically:

```python
answer = result.answers["department"]
if answer.confidence >= 0.7:
    route_to(answer.choice)
else:
    route_to("human_review")
```

{% callout type="note" %}
  Set thresholds using labeled examples from your own traffic. Weigh the cost
  of a false positive against a false negative.

{% /callout %}

## Input  {% id="input" %}

The input field accepts text, image, audio, video, and PDF document blocks
using the same content block schema as the
[Interactions API](/docs/interactions-overview) (tool-call, tool-result, and
thought blocks aren't supported):

```none
Input   = string | Content | Content[]
Content = TextContent | ImageContent | AudioContent | VideoContent | DocumentContent
```

| Block | Fields | Supported MIME types |
| :--- | :--- | :--- |
| `text` | `text` | n/a |
| `image` | `data` or `uri`, `mime_type`, optional `resolution` | `image/png`, `image/jpeg`, `image/webp`, `image/heic`, `image/heif`, `image/gif`, `image/bmp`, `image/tiff` |
| `audio` | `data` or `uri`, `mime_type` | `audio/wav`, `audio/mp3`, `audio/mpeg`, `audio/aiff`, `audio/aac`, `audio/ogg`, `audio/flac`, `audio/m4a`, `audio/opus`, `audio/webm`, `audio/l16`, `audio/alaw`, `audio/mulaw` |
| `video` | `data` or `uri`, `mime_type`, optional `resolution` | `video/mp4`, `video/mpeg`, `video/mov`, `video/avi`, `video/webm`, `video/wmv`, `video/x-flv`, `video/3gpp` |
| `document` | `data` or `uri`, `mime_type` | `application/pdf` |

*   Inline data accepts base64-encoded bytes (up to 100 MB per request, or
  50 MB for PDFs).
*   URI inputs accept [Files API](/docs/files) URIs (`file.uri`) and public or
  signed HTTPS URLs (up to 15 MB per external URL).
*   Always set the MIME type to the real file format. The API rejects generic
  octet-stream types and content that doesn't match the block type.
*   The API concatenates adjacent text blocks in `input` and `instructions` in
  order with no separator. Include your own spaces or newlines (`\n`) between
  blocks.
*   Input can't be empty.

### Structured data  {% id="structured-data" %}

Serialize JSON objects and arrays to a string and pass them as text so keys
inside your payload stay plain data rather than content blocks. In your
question instructions, refer to JSON fields by their key path:

```python
state = json.dumps({"customer": {"tier": "Gold"}, "order": {"id": "8821", "age_days": 14}})
```

### Images  {% id="media" %}

Read a local file and pass base64-encoded bytes inline. The same pattern works
for local audio, video, and PDF files. This example checks a product photo for
damage:

{% tabs %}
  {% tab filename="decisions.py" label="Python" %}
  ```python
  import base64
  from google import genai
  
  client = genai.Client(http_options={"api_version": "v1beta"})
  
  with open("earcup.jpg", "rb") as f:
      image_b64 = base64.b64encode(f.read()).decode("utf-8")
  
  result = client.decisions.create(
      model="gemini-decision-1",
      input=[
          {"type": "text", "text": "Customer photo for return request #8821."},
          {
              "type": "image",
              "data": image_b64,
              "mime_type": "image/jpeg",
              "resolution": "low",  # Supported values: "low", "medium", "high", "ultra_high"
          },
      ],
      questions={
          "visible_damage": {
              "type": "noul",
              "instructions": "Does the photo show physical damage to the device? Ignore the packaging.",
          },
      },
  )
  
  print(result.answers["visible_damage"].noul)
  ```

  {% /tab %}

  {% tab filename="decisions.mjs" label="JavaScript" %}
  ```javascript
  import { readFileSync } from "node:fs";
  import { GoogleGenAI } from "@google/genai";
  
  const ai = new GoogleGenAI({ apiVersion: "v1beta" });
  const imageB64 = readFileSync("earcup.jpg").toString("base64");
  
  const result = await ai.decisions.create({
    model: "gemini-decision-1",
    input: [
      { type: "text", text: "Customer photo for return request #8821." },
      {
        type: "image",
        data: imageB64,
        mime_type: "image/jpeg",
        resolution: "low", // Supported values: "low", "medium", "high", "ultra_high"
      },
    ],
    questions: {
      visible_damage: {
        type: "noul",
        instructions: "Does the photo show physical damage to the device? Ignore the packaging.",
      },
    },
  });
  
  const answer = result.answers?.visible_damage;
  if (answer?.type === "noul") console.log(answer.noul);
  ```

  {% /tab %}

  {% tab filename="decisions.sh" label="REST" %}
  ```bash
  curl -X POST "https://generativelanguage.googleapis.com/v1beta/decisions" \
    -H "x-goog-api-key: $GEMINI_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "model": "gemini-decision-1",
      "input": [
        { "type": "text", "text": "Customer photo for return request #8821." },
        { "type": "image", "data": "<BASE64_IMAGE_DATA>", "mime_type": "image/jpeg", "resolution": "low" }
      ],
      "questions": {
        "visible_damage": {
          "type": "noul",
          "instructions": "Does the photo show physical damage to the device? Ignore the packaging."
        }
      }
    }'
  ```

  {% /tab %}

{% /tabs %}

### Audio and video  {% id="audio-and-video" %}

Pass a [Files API](/docs/files) URI, a public or signed HTTPS URL, or inline
base64 bytes in your input block.

This example checks a short MP3 clip for spaceflight discussion:

{% tabs %}
  {% tab filename="decisions.py" label="Python" %}
  ```python
  from google import genai
  
  client = genai.Client(http_options={"api_version": "v1beta"})
  
  result = client.decisions.create(
      model="gemini-decision-1",
      input=[
          {
              "type": "audio",
              "uri": "https://storage.googleapis.com/generativeai-downloads/data/Apollo-11_Day-01-Highlights-10s.mp3",
              "mime_type": "audio/mp3",
          },
      ],
      questions={
          "mentions_launch": {
              "type": "noul",
              "instructions": "Is the speaker talking about spaceflight or a rocket launch?",
          },
      },
  )
  
  print(result.answers["mentions_launch"].noul)
  ```

  {% /tab %}

  {% tab filename="decisions.mjs" label="JavaScript" %}
  ```javascript
  import { GoogleGenAI } from "@google/genai";
  
  const ai = new GoogleGenAI({ apiVersion: "v1beta" });
  
  const result = await ai.decisions.create({
    model: "gemini-decision-1",
    input: [
      {
        type: "audio",
        uri: "https://storage.googleapis.com/generativeai-downloads/data/Apollo-11_Day-01-Highlights-10s.mp3",
        mime_type: "audio/mp3",
      },
    ],
    questions: {
      mentions_launch: {
        type: "noul",
        instructions: "Is the speaker talking about spaceflight or a rocket launch?",
      },
    },
  });
  
  const answer = result.answers?.mentions_launch;
  if (answer?.type === "noul") console.log(answer.noul);
  ```

  {% /tab %}

  {% tab filename="decisions.sh" label="REST" %}
  ```bash
  curl -X POST "https://generativelanguage.googleapis.com/v1beta/decisions" \
    -H "x-goog-api-key: $GEMINI_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "model": "gemini-decision-1",
      "input": [
        {
          "type": "audio",
          "uri": "https://storage.googleapis.com/generativeai-downloads/data/Apollo-11_Day-01-Highlights-10s.mp3",
          "mime_type": "audio/mp3"
        }
      ],
      "questions": {
        "mentions_launch": {
          "type": "noul",
          "instructions": "Is the speaker talking about spaceflight or a rocket launch?"
        }
      }
    }'
  ```

  {% /tab %}

{% /tabs %}

This example checks an MP4 video clip at low resolution:

{% tabs %}
  {% tab filename="decisions.py" label="Python" %}
  ```python
  from google import genai
  
  client = genai.Client(http_options={"api_version": "v1beta"})
  
  result = client.decisions.create(
      model="gemini-decision-1",
      input=[
          {
              "type": "video",
              "uri": "https://storage.googleapis.com/generativeai-downloads/videos/ForBiggerBlazes.mp4",
              "mime_type": "video/mp4",
              "resolution": "low",
          },
      ],
      questions={
          "shows_fire": {
              "type": "noul",
              "instructions": "Does the video show fire or flames?",
          },
      },
  )
  
  print(result.answers["shows_fire"].noul)
  ```

  {% /tab %}

  {% tab filename="decisions.mjs" label="JavaScript" %}
  ```javascript
  import { GoogleGenAI } from "@google/genai";
  
  const ai = new GoogleGenAI({ apiVersion: "v1beta" });
  
  const result = await ai.decisions.create({
    model: "gemini-decision-1",
    input: [
      {
        type: "video",
        uri: "https://storage.googleapis.com/generativeai-downloads/videos/ForBiggerBlazes.mp4",
        mime_type: "video/mp4",
        resolution: "low",
      },
    ],
    questions: {
      shows_fire: {
        type: "noul",
        instructions: "Does the video show fire or flames?",
      },
    },
  });
  
  const answer = result.answers?.shows_fire;
  if (answer?.type === "noul") console.log(answer.noul);
  ```

  {% /tab %}

  {% tab filename="decisions.sh" label="REST" %}
  ```bash
  curl -X POST "https://generativelanguage.googleapis.com/v1beta/decisions" \
    -H "x-goog-api-key: $GEMINI_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "model": "gemini-decision-1",
      "input": [
        {
          "type": "video",
          "uri": "https://storage.googleapis.com/generativeai-downloads/videos/ForBiggerBlazes.mp4",
          "mime_type": "video/mp4",
          "resolution": "low"
        }
      ],
      "questions": {
        "shows_fire": {
          "type": "noul",
          "instructions": "Does the video show fire or flames?"
        }
      }
    }'
  ```

  {% /tab %}

{% /tabs %}

### Media resolution  {% id="media-resolution" %}

Set [media resolution](/docs/media-resolution) on image and video blocks (low,
medium, high, or ultra_high) to control token cost and visual detail.
Ultra-high resolution applies to images only; audio and document blocks don't
use resolution settings.

## Best practices  {% id="best-practices" %}

*   Keep each question focused on a single decision or rubric. Complex rubrics
  work in one question when criteria are explicit, or you can split
  independent checks into separate questions in one request and combine the
  answers in code.
*   Write the full question in the instructions. The model never sees question
  keys or your variable names.
*   Give each choice option and score level a short description. Make adjacent
  score levels clearly distinct, and keep score scales linear. Because score
  averages array indices (0, 1, 2, and up), exponential scales like 1, 10,
  100, and 1000 skew the expected value.
*   Plan for inputs that fit no choice option. Check confidence before acting
  on the top option, or pair the choice question with a yes/no scope check
  such as "Is this message about an order?". If you add a catch-all option,
  use a non-positional key like "other" rather than "none_of_the_above",
  since the API sorts option keys alphabetically.
*   Prefer positive phrasing. Ask "Is the tier Gold?" and subtract the yes
  probability from 1 in code rather than asking negated questions such as
  "Is the tier NOT Gold?".
*   Send only the fields the questions need. Unrelated content lowers accuracy.
*   Compare numbers, dates, and durations in code, then pass the result or a
  named bucket in the input.
*   Treat input as untrusted. User-supplied text can argue for its own
  classification. Write explicit criteria, test with adversarial examples,
  and keep a human or a second check on high-stakes actions such as payouts.

## Decisions API or structured output  {% id="when-to-use" %}

Use the Decisions API when you need calibrated probabilities over closed-ended
outcomes:

*   Route a request to a model, queue, agent, or tool.
*   Check inputs and outputs against many policy rules at once.
*   Decide which tools an agent needs, or whether to compact, escalate, or stop.
*   Filter, score, or rank candidate results against a rubric.
*   React to UI state, audio, or video frames in real time.

| Use the Decisions API when you need | Use the [Interactions API](/docs/interactions-overview) when you need |
| :--- | :--- |
| A yes/no probability, one option from a fixed set, or a rating on a fixed scale | Generated text, summaries, or explanations |
| Calibrated probabilities you can threshold | Extracted values or objects that follow your own JSON schema (see [Structured outputs](/docs/structured-output)) |
| Many independent checks over the same input in one call | Tool calls with arguments |
| Low latency and zero output token cost | Multi-step reasoning |

## Request and response reference  {% id="request" %}

| Field | Type | Required | Description |
| :--- | :--- | :--- | :--- |
| `model` | string | yes | Model ID: `gemini-decision-1`. See [Gemini Decision 1](/docs/models/gemini-decision-1). |
| `input` | string, `Content`, or `Content[]` | yes | Shared context for all questions (text, image, audio, video, or PDF document). See [Input](/docs/decisions-api#input). |
| `questions` | map of string to `Question` | yes | 1 to 1,000 questions. You choose the keys (`[A-Za-z0-9_-]+`, up to 64 characters). Answers come back under the same keys. |

Every question has:

| Field | Type | Required | Description |
| :--- | :--- | :--- | :--- |
| `type` | `noul`, `choice`, or `score` | yes | Question type. |
| `instructions` | string, `TextContent`, or `TextContent[]` | yes | The question to evaluate against the input. Text only. |
| `criteria` | depends on type | choice and score: yes. noul: no. | The possible answers. See [Question types](/docs/decisions-api#question-types). |

The API evaluates each question independently against the shared input.
Questions can't see each other, and adding or removing one doesn't change the
other answers. The model never sees question keys, so write the full question in
the instructions field.

The response contains:

| Field | Type | Description |
| :--- | :--- | :--- |
| `answers` | map of string to `Answer` | One answer per question, under the same keys as `questions`. Each answer has a type that matches its question. |
| `usage` | `Usage` | Input token counts by modality (text, image, and audio, with video frames and PDF page images counted as image tokens) and 0 output tokens. Only input tokens are billed; see [Pricing](/docs/pricing#gemini-decision). |

When input safety filters block a request, the API returns an HTTP
`400 Bad Request` error instead of `answers`. The JSON `error` object includes
a `message` and a `code` (`safety`, `prohibited_content`, `blocklist`,
`image_safety`, or `content_blocked`):

```json
{
  "error": {
    "code": "safety",
    "message": "Request blocked due to safety violations (harmful content). Please modify your input and retry."
  }
}
```

## Limits  {% id="limits" %}

| Limit | Value |
| :--- | :--- |
| Questions per request | 1 to 1,000 (bounded by the 262,144-token context window) |
| Options per choice question | 2 to 255 |
| Levels per score question | 2 to 255 non-empty strings (2 to 10 recommended for most rubrics) |
| Question key | 1 to 64 ASCII characters matching `[A-Za-z0-9_-]+` |
| Option key | 1 to 128 characters (up to 512 UTF-8 bytes). Internal ASCII spaces are allowed. Leading or trailing spaces, control characters, and non-ASCII spaces aren't allowed. |
| Context window | 262,144 tokens across shared input and all questions |
| JSON nesting depth | 100 levels |
| Media per request | Same as the [Interactions API](/docs/interactions-overview) |
| Question instructions | Text only |

When a request exceeds a limit or fails key validation, the API returns HTTP 400
with an error message that names the rule you exceeded.

## Limitations  {% id="limitations" %}

*   Available on the Gemini Developer API (v1beta) with
  [Gemini Decision 1](/docs/models/gemini-decision-1) only.
*   Question instructions accept text only. Media inside questions isn't
  supported.
*   The Decisions API doesn't support YouTube URLs or direct Cloud Storage
  (`gs://`) URIs. Pass media using a [Files API](/docs/files) URI, a public or
  signed HTTPS URL, or inline base64 bytes.
*   Conversation history, thought, and tool-call blocks aren't supported as
  input blocks. Serialize multi-turn context as text.
*   The Decisions API doesn't support context caching,
  [Batch API](/docs/batch-api), or Flex or Priority inference. Repeated input
  across requests counts in full.

## What's next  {% id="whats-next" %}

*   Test yes/no, choice, and score questions interactively on custom text and
  media in the [Decisions Playground](https://aistudio.google.com/apps/f6cbef57-8bad-443a-813f-4d4c8f9750af?fullscreenApplet=true),
  then export runnable code.
*   Explore sample apps built with Gemini Decision 1 in Google AI Studio,
  including [Doorstep Parcels](https://aistudio.google.com/apps/bdca3fee-8d0a-4663-b30e-73828a55c1e8?fullscreenApplet=true)
  and [Find the Zookeeper](https://aistudio.google.com/apps/b86d2f3b-c1d4-4d44-9198-5303a0cb65c1?fullscreenApplet=true).
*   Review model specifications on the
  [Gemini Decision 1](/docs/models/gemini-decision-1) model page, along with
  [Pricing](/docs/pricing#gemini-decision) and
  [Rate limits](/docs/rate-limits#gemini-decision).
*   Build autonomous workflows with [Managed agents](/docs/agents) on the
  Gemini API.

