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

# OpenAI Decisions API

> 透過 gpt-6-luna 呼叫 OpenAI 相容 Decisions 介面：判斷、分類、評分的參數、結構化結果與錯誤處理。

透過 MixRoute 的 OpenAI 相容 Decisions 介面，針對同一份輸入提出具名問題並取得結構化答案。模型使用 `gpt-6-luna`；此協定與 Jev System One 不同。

## 接入方式

`POST https://api.mixroute.ai/v1/decisions`

請求標頭使用 `Authorization: Bearer $MIXROUTE_API_KEY` 和 `Content-Type: application/json`。API Key 僅保存在伺服器端。模型和管道權限取決於帳戶；模型出現在列表中不代表所有介面均可用。

> [!WARNING]
>
> 使用 `input`，不是 `state`；`questions` 是可帶 name 的陣列，不是以問題 ID 為鍵的物件。真假判斷用 `predicate`，不是 `noul`；分類用 `choices`，評分用 `levels`，不是 Jev 的 `criteria`。回應中的 `answers` 也是陣列。Jev 協定見 [System One](https://mixroute.ai/docs/zh-Hant/api-reference/endpoint/jev.md)。

## 請求參數

| 欄位 | 型別 | 要求 | 說明 |
| - | - | - | - |
| `model` | string | 必填 | 使用 gpt-6-luna；不能直接替換成其他聊天模型或 Jev ID。 |
| `input` | string / array | 必填 | 所有問題共同評估的輸入：文字，或依序排列的訊息、函式呼叫及結果、自訂工具呼叫及結果陣列。 |
| `questions` | object\[] | 必填 | 包含 1-400 個 predicate、choice 或 score 問題的陣列。各問題獨立評估；若依賴上一個答案，應分開請求。 |
| `prompt_cache_key` | string / null | 可選 | 呼叫端提供的快取分區識別碼，最多 64 個字元。 |
| `prompt_cache_options` | object / null | 可選 | 可選快取設定。mode 為 implicit（預設）或 explicit；ttl 目前支援 30m。實際快取可用性與計費取決於路由。 |
| `safety_identifier` | string / null | 可選 | 不透明的終端使用者識別碼，最多 128 個字元；建議使用穩定且不含個人資訊的識別碼。 |

## 問題欄位

| 欄位 | 型別 | 要求 | 說明 |
| - | - | - | - |
| `type` | string | 必填 | predicate、choice 或 score。 |
| `instructions` | string / array | 必填 | 要作出的判斷。使用文字字串或非空的受支援內容項目陣列。文字和圖片項目直接放入 instructions，不加訊息外層。 |
| `name` | string | 可選 | 回應中原樣傳回的名稱，建議每個問題使用不同名稱；未命名的問題可傳回 name=null。 |
| `choices` | object\[] | 依型別 | choice 必填，包含 2-255 個互不相同的選項。每項必填 value（字串或布林值），可選 description（字串）。字串 "true" 與布林值 true 是不同值。 |
| `levels` | object\[] | 依型別 | score 必填，包含 2-10 個從低到高排列的等級。每項必填 label（字串），可選 description（字串）；等級索引從 0 開始。 |

## 答案型別

| 型別 | 說明 |
| - | - |
| `predicate` | probability 是條件成立的估計機率，範圍 0-1，不是布林值。 |
| `choice` | choice 是給定的字串或布林選項。probabilities 是 value/probability 物件陣列，另有 confidence 欄位。 |
| `score` | score 是等級索引的機率加權平均值，範圍為 0 到 levels.length-1，可為小數。probabilities 包含 value（索引）、label 和 probability。 |

任何問題都可能傳回 type=refusal，其他問題仍可正常回應。依 name 或問題順序對應，先判斷 type，再讀取對應欄位，並明確處理拒答。信心分數和機率不保證判斷正確。

## 請求範例

呼叫前設定 `MIXROUTE_API_KEY`。範例只提交一次，不自動重試；用戶端逾時不代表伺服器端沒有執行推論。

> [tab] cURL
>
> ```bash theme={null}
> curl --request POST "https://api.mixroute.ai/v1/decisions" \
>   --header "Authorization: Bearer $MIXROUTE_API_KEY" \
>   --header "Content-Type: application/json" \
>   --data '{
>   "model": "gpt-6-luna",
>   "input": "CSV export fails on every attempt. The customer needs the file today and asks for a human agent.",
>   "questions": [
>     {
>       "type": "choice",
>       "name": "team",
>       "instructions": "Which team should handle this ticket?",
>       "choices": [
>         {
>           "value": "engineering",
>           "description": "Software defects"
>         },
>         {
>           "value": "billing",
>           "description": "Payments and refunds"
>         }
>       ]
>     },
>     {
>       "type": "score",
>       "name": "urgency",
>       "instructions": "How soon does the customer need help?",
>       "levels": [
>         {
>           "label": "No deadline",
>           "description": "No deadline is specified."
>         },
>         {
>           "label": "This week",
>           "description": "Help is needed within a week."
>         },
>         {
>           "label": "Today",
>           "description": "Help is explicitly required today."
>         }
>       ]
>     },
>     {
>       "type": "predicate",
>       "name": "needs_human",
>       "instructions": "Does the customer request a human agent?"
>     }
>   ]
> }'
> ```

> [tab] Python
>
> ```python theme={null}
> import json
> import os
> import requests
>
> payload = json.loads(r'''{
>   "model": "gpt-6-luna",
>   "input": "CSV export fails on every attempt. The customer needs the file today and asks for a human agent.",
>   "questions": [
>     {
>       "type": "choice",
>       "name": "team",
>       "instructions": "Which team should handle this ticket?",
>       "choices": [
>         {
>           "value": "engineering",
>           "description": "Software defects"
>         },
>         {
>           "value": "billing",
>           "description": "Payments and refunds"
>         }
>       ]
>     },
>     {
>       "type": "score",
>       "name": "urgency",
>       "instructions": "How soon does the customer need help?",
>       "levels": [
>         {
>           "label": "No deadline",
>           "description": "No deadline is specified."
>         },
>         {
>           "label": "This week",
>           "description": "Help is needed within a week."
>         },
>         {
>           "label": "Today",
>           "description": "Help is explicitly required today."
>         }
>       ]
>     },
>     {
>       "type": "predicate",
>       "name": "needs_human",
>       "instructions": "Does the customer request a human agent?"
>     }
>   ]
> }''')
> response = requests.post(
>     "https://api.mixroute.ai/v1/decisions",
>     headers={"Authorization": "Bearer " + os.environ["MIXROUTE_API_KEY"]},
>     json=payload,
>     timeout=60,
>     allow_redirects=False,
> )
> response.raise_for_status()
> result = response.json()
> if not isinstance(result.get("answers"), list):
>     raise ValueError("Expected an answers array")
> for answer in result["answers"]:
>     kind = answer["type"]
>     if kind == "refusal":
>         print(answer.get("name"), "refused")
>         continue
>     field = {"predicate": "probability", "choice": "choice", "score": "score"}.get(kind)
>     if field is None:
>         raise ValueError("Unexpected answer type: " + kind)
>     print(answer.get("name"), answer[field])
> ```

> [tab] JavaScript
>
> ```javascript theme={null}
> const apiKey = process.env.MIXROUTE_API_KEY;
> if (!apiKey) throw new Error("Set MIXROUTE_API_KEY");
> const payload = {
>   "model": "gpt-6-luna",
>   "input": "CSV export fails on every attempt. The customer needs the file today and asks for a human agent.",
>   "questions": [
>     {
>       "type": "choice",
>       "name": "team",
>       "instructions": "Which team should handle this ticket?",
>       "choices": [
>         {
>           "value": "engineering",
>           "description": "Software defects"
>         },
>         {
>           "value": "billing",
>           "description": "Payments and refunds"
>         }
>       ]
>     },
>     {
>       "type": "score",
>       "name": "urgency",
>       "instructions": "How soon does the customer need help?",
>       "levels": [
>         {
>           "label": "No deadline",
>           "description": "No deadline is specified."
>         },
>         {
>           "label": "This week",
>           "description": "Help is needed within a week."
>         },
>         {
>           "label": "Today",
>           "description": "Help is explicitly required today."
>         }
>       ]
>     },
>     {
>       "type": "predicate",
>       "name": "needs_human",
>       "instructions": "Does the customer request a human agent?"
>     }
>   ]
> };
> const response = await fetch("https://api.mixroute.ai/v1/decisions", {
>   method: "POST",
>   headers: {
>     Authorization: "Bearer " + apiKey,
>     "Content-Type": "application/json",
>   },
>   body: JSON.stringify(payload),
>   signal: AbortSignal.timeout(60000),
>   redirect: "error",
> });
> const result = await response.json();
> if (!response.ok) {
>   throw new Error(result.error?.message ?? "HTTP " + response.status);
> }
> if (!Array.isArray(result.answers)) throw new Error("Expected an answers array");
> for (const answer of result.answers) {
>   if (answer.type === "refusal") {
>     console.log(answer.name, "refused");
>     continue;
>   }
>   const field = { predicate: "probability", choice: "choice", score: "score" }[answer.type];
>   if (!field) throw new Error("Unexpected answer type: " + answer.type);
>   console.log(answer.name, answer[field]);
> }
> ```

## 回應範例

同步傳回 JSON 物件，不是 Chat Completions 的 choices 陣列，也不是需要輪詢的任務。機率和 token 用量會隨請求變化。

```json theme={null}
{
  "model": "gpt-6-luna",
  "answers": [
    {
      "type": "choice",
      "name": "team",
      "choice": "engineering",
      "probabilities": [
        {
          "value": "engineering",
          "probability": 1
        },
        {
          "value": "billing",
          "probability": 0
        }
      ],
      "confidence": 1
    },
    {
      "type": "score",
      "name": "urgency",
      "score": 2,
      "probabilities": [
        {
          "value": 0,
          "label": "No deadline",
          "probability": 0
        },
        {
          "value": 1,
          "label": "This week",
          "probability": 0
        },
        {
          "value": 2,
          "label": "Today",
          "probability": 1
        }
      ],
      "confidence": 1
    },
    {
      "type": "predicate",
      "name": "needs_human",
      "probability": 1
    }
  ],
  "usage": {
    "input_tokens": 416,
    "input_tokens_details": {
      "cached_tokens": 0,
      "cache_write_tokens": 0
    },
    "output_tokens": 0,
    "output_tokens_details": {
      "reasoning_tokens": 0
    },
    "total_tokens": 416
  }
}
```

| 欄位 | 說明 |
| - | - |
| `model` | 實際執行判斷的模型。 |
| `answers` | 與問題順序一致的陣列；先檢查每項的 type 和 name。 |
| `usage.input_tokens` | 本次請求的輸入 token 用量。 |
| `usage.input_tokens_details` | cached\_tokens、cache\_write\_tokens 已包含在 input\_tokens 中，不要重複相加。 |
| `usage.output_tokens / usage.output_tokens_details` | 輸出用量及 reasoning\_tokens，不代表傳回了聊天文字。 |
| `usage.total_tokens` | 介面報告的總 token 用量。 |

## 結構化與圖片輸入

user 訊息的 content 可包含 input\_text（text）、input\_image（image\_url）、input\_json（data）。JSON data 必須是物件或物件陣列；其中的鍵僅為待判斷的資料，不會觸發圖片擷取或建立訊息。JSON 輸入最多 32 層容器、10,000 個值、256 KiB 的緊湊 UTF-8 JSON。

```json theme={null}
{
  "model": "gpt-6-luna",
  "input": [
    {
      "role": "user",
      "content": [
        {
          "type": "input_text",
          "text": "Evaluate the ticket record."
        },
        {
          "type": "input_json",
          "data": {
            "ticket": {
              "feature": "CSV export",
              "fails": true,
              "deadline": "today"
            }
          }
        }
      ]
    }
  ],
  "questions": [
    {
      "type": "predicate",
      "name": "deadline_today",
      "instructions": "Does the ticket require action today?"
    }
  ]
}
```

圖片使用公開 HTTP(S) URL 或 Base64 data URL，不使用 file\_id。detail 可選 auto、low、high、original。developer/system 訊息使用文字；assistant 訊息使用輸出文字或拒答項目。工具結果透過 call\_id 與呼叫對應。此協定不接受檔案、音訊或項目參照。以上為協定格式，進階輸入的實際可用性取決於 MixRoute 路由。

將範例圖片網址替換為可公開存取的商品圖片或 Base64 data URL。

```json theme={null}
{
  "model": "gpt-6-luna",
  "input": [
    {
      "role": "user",
      "content": [
        {
          "type": "input_text",
          "text": "Inspect this product photo."
        },
        {
          "type": "input_image",
          "image_url": "https://example.com/product.png",
          "detail": "auto"
        }
      ]
    }
  ],
  "questions": [
    {
      "type": "predicate",
      "name": "visible_damage",
      "instructions": "Does the product show a crack, tear, or dent?"
    }
  ]
}
```

## 可選提示詞快取

共享 input 至少達到 1,024 tokens 才具備快取條件；questions 不屬於可重用的輸入前綴。預設使用隱含斷點；明確斷點在共享 input 的文字或圖片項目中設定 `prompt_cache_breakpoint: {"mode": "explicit"}`。prompt\_cache\_options.mode=explicit 且沒有明確斷點時不使用快取。問題 instructions 不支援快取斷點。不要將上游快取折扣或價格直接視為 MixRoute 費率。

## 錯誤與計費

先檢查 HTTP 狀態。閘道錯誤可能包含 error.message、error.type、error.code、error.param，其中 param 可能為空。排查時保留 x-oneapi-request-id，不記錄完整 API Key。

| HTTP | 說明 |
| - | - |
| 400 invalid\_request | 檢查 input 和 questions 陣列；問題物件對映屬於 Jev 格式，不適用於本介面。 |
| 401 / 403 | 檢查認證及介面、模型權限。 |
| 503 model\_not\_found | 目前 Key／分組沒有此模型的可用管道，不是模型傳回的判斷結果。 |
| 429 / 其他 5xx | 有 Retry-After 時遵循該值，僅在適當情況下有限重試；結果不確定的逾時不要自動重複提交。 |

```json theme={null}
{
  "error": {
    "message": "questions must be a non-empty array",
    "type": "mixroute_error",
    "param": "",
    "code": "invalid_request"
  }
}
```

結合 usage 與目前[模型廣場](https://console.mixroute.ai/models)確認計費。不要假定 Responses 或 Chat Completions 的費率適用於 Decisions；實際費用取決於帳戶倍率和路由定價。


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