---
title: "Evaluate questions (OpenAI Decisions format)"
method: POST
path: "/v1/decisions"
tags: ["Evaluate"]
---

# Evaluate questions (OpenAI Decisions format)

`POST /v1/decisions`

## Request

- Base URL: `https://console.nace.ai`
- URL: `https://console.nace.ai/v1/decisions`
- Auth: HTTP bearer
- TypeScript: <https://skmtc.dev/nace/apis/drex-api/docs/v1/decisions/post.ts> (a function with typed inputs; its response is checked against the schema)

`POST /v1/decisions` takes OpenAI's Decisions wire format on the same models as `POST /v1/systemone`, so the OpenAI SDKs, LiteLLM and Vercel AI Gateway call Drex with only a base URL and model change. The same key, funding, rate limits, validation and billing apply; only the request and response shapes differ. See [OpenAI-compatible decisions](/docs/drex/guides/openai-compatible-decisions).

- **Billing:** only a `200` is billed, at the per-input-token price, exactly as `/v1/systemone` bills the same request.
- **Accepted and ignored:** `safety_identifier`, `prompt_cache_key`, `prompt_cache_options`, `prompt_cache_breakpoint` and an image's `detail` are checked against OpenAI's schema and then dropped. Any other key Drex doesn't know is ignored.
- **Errors:** Drex's `error.type` and status, plus OpenAI's `error.code` and `error.param`.

Checks run in the same order as `/v1/systemone` and stop at the first failure.

## Request body

- DecisionRequest
  - `model` string: As on `POST /v1/systemone`. A registered id or alias is served as named, and no `model` is served like `drex-latest`. Any other name (`gpt-6-luna`, `jev-latest`, a mistyped `drex-` name) or a registered id that isn't available yet returns `422` with `code: model_not_found` and `param: model`.
  - `input` union, required: What the questions are about: a string, or user messages whose text parts are joined with a blank line into the state. See [State](/docs/drex/guides/state).
    - string
    - DecisionMessage[]
      - `type` 'message'
      - `role` 'user', required
      - `content` union, required
        - string
        - DecisionInputPart[]
          - union: One part of a user message's content.
            - object
              - …
            - object
              - …
            - object
              - …
  - `questions` DecisionQuestion[], required: 1 to 512 questions, answered in order.
    - union: One question. Answers come back in question order. `predicate` is System One's `noul`, `choice` its `choice` and `score` its `score`; see [Questions](/docs/drex/guides/questions).
      - object
        - `type` 'predicate', required
        - `name` string, nullable: Echoed on the answer as `name`; an unnamed question answers with `name: null`. Names need not be unique.
        - `instructions` string, required: The yes/no question. Text only.
      - object
        - `type` 'choice', required
        - `name` string, nullable: Echoed on the answer as `name`; an unnamed question answers with `name: null`. Names need not be unique.
        - `instructions` string, required
        - `choices` object[], required: The options, in the order their probabilities come back.
          - `value` union, required: Returned as sent, so `true` stays a boolean. A boolean is the lowercase label `true` or `false`; a string equal to that label (`"true"`) in the same question returns `422` whose `param` is the later choice, such as `questions[0].choices[1].value`. `"True"` is a different string and its own option.
            - string
            - boolean
          - `description` string, nullable
      - object
        - `type` 'score', required
        - `name` string, nullable: Echoed on the answer as `name`; an unnamed question answers with `name: null`. Names need not be unique.
        - `instructions` string, required
        - `levels` object[], required: The ordered rubric, 2 to 10 levels. Level `i` scores `i`.
          - `label` string, required: Returned in `probabilities[].label`.
          - `description` string, nullable: Shown to the model with the label as `label: description`.
  - `safety_identifier` string, nullable: OpenAI's opaque end-user identifier. Accepted for compatibility, up to 128 characters; Drex neither forwards nor stores it.
  - `prompt_cache_key` string, nullable: Accepted for OpenAI compatibility, up to 64 characters, and ignored: Drex has no prompt cache.
  - `prompt_cache_options` object, nullable: Accepted for OpenAI compatibility and ignored: Drex has no prompt cache.
    - `mode` 'implicit' | 'explicit' | 'null', nullable
    - `ttl` '30m'

## Response `200`

Every question answered, in order. `usage.input_tokens` is debited from the account's balance before the response is returned.

- DecisionResponse
  - `model` 'drex-v1.5' | 'drex-v2.0' | 'drex-max' | 'drex-max-v1.1' | 'drex-max-finance', required: The version that answered.
  - `answers` DecisionAnswer[], required: In question order.
    - union: One answer, in question order. `refusal` is part of OpenAI's contract; Drex's models answer every question today.
      - object
        - `type` 'predicate', required
        - `name` string, nullable, required: The question's `name`, or `null`.
        - `probability` number, required: The probability of yes.
      - object
        - `type` 'choice', required
        - `name` string, nullable, required: The question's `name`, or `null`.
        - `choice` union, required: The chosen option's `value`, as sent.
          - string
          - boolean
        - `confidence` number, required
        - `probabilities` object[], required: One per option, in the order sent.
          - `value` union, required
            - string
            - boolean
          - `probability` number, required
      - object
        - `type` 'score', required
        - `name` string, nullable, required: The question's `name`, or `null`.
        - `score` number, required: The expected score; it can fall between levels.
        - `confidence` number, required
        - `probabilities` object[], required: One per level, in the order sent.
          - `value` integer, required: The level's index.
          - `label` string, required
          - `probability` number, required
      - object
        - `type` 'refusal', required
        - `name` string, nullable, required: The question's `name`, or `null`.
  - `usage` DecisionUsage, required
    - `input_tokens` integer, required: Billed, at the model's per-input-token price. Image tokens are included.
    - `output_tokens` integer, required
    - `total_tokens` integer, required: `input_tokens + output_tokens`.
    - `input_tokens_details` object, required: Always zero: Drex has no prompt cache.
      - `cached_tokens` 0, required
      - `cache_write_tokens` 0, required
    - `output_tokens_details` object, required: Always zero: Drex has no reasoning tokens.
      - `reasoning_tokens` 0, required
  - `request_id` string, required: Identifier of this request, `req_` plus 32 hex characters. Also sent in the `x-request-id` header, and on `/v1/systemone` and `/v1/models` in `x-typesafe-request-id` too. Quote it in support requests.

## Other responses

- `401`: The bearer token is missing or not a valid key.
- `402`: The account has no available funds or an unpaid invoice.
- `422`: The body is not JSON, fails validation, is over the byte limit, or is over the model's token limit. `error.param` names the field; `error.issues` lists every problem. The request is not billed.
- `429`: The account's rate limit; `retry-after` says when to retry.
- `500`: Drex failed. Retry, and quote `request_id` in a support request.
- `529`: Drex or the model service is at capacity; `retry-after` says when to retry.

---

[API](https://skmtc.dev/nace/apis/drex-api.md) - [All operations](https://skmtc.dev/nace/apis/drex-api/llms.txt) - [OpenAPI document](https://skmtc.dev/nace/apis/drex-api/revisions/a0e62d925a61?raw)
