> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.beatapi.io/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.beatapi.io/_mcp/server.

# Decisions API

> アプリケーションの状態と型を指定した質問を送信し、確率付きの型付き回答を取得します。生成された文章を解釈する必要はありません。処理を実行する前に、レスポンスを検証してください。

# Decisions API

多くのモデル呼び出しでは文章が返され、そこから判断結果を取り出す必要があります。JSON を要求し、解析・検証し、形式が崩れれば再試行する、という流れです。Decisions API は、その処理を不要にします。アプリケーションの現在の状態と質問を送信すると、真偽の確率、指定した選択肢のいずれか、独自の尺度上の値など、型が定まった回答が確率とともに返ります。

会話ではなく、ソフトウェア内部の判断に使う API です。チケットの振り分け、ツール呼び出しの可否判定、キューの優先順位付け、人が確認する前の投稿の評価などに利用できます。

`POST https://api.beatapi.io/v1/systemone`

エンドポイントのパス、リクエストとレスポンスのボディは TypeSafe の API と同じです。TypeSafe API またはその SDK 向けのクライアントは、ベース URL とモデル名を変更するだけで利用でき、他の調整は不要です。`POST /v1/decisions` も別名として引き続き利用できます。

| モデル             | 選び方                                                                    |
| --------------- | ---------------------------------------------------------------------- |
| `jev-1.13-free` | **まずは無料の JEV から。** 入力も出力も \$0 で、残高がゼロでも利用できます。後述の**無料の呼び出し**を参照してください。 |
| `jev-1.13`      | 必要に応じて選べる有料モデルです。入力 1M トークンあたり \$0.042 で、出力は課金されません。                   |

> **Note**
>
> このエンドポイントは `/v1/chat/completions` ではなく、`jev-1.13` はそちらでは利用できません。リクエストに `messages` はなく、レスポンスに `choices` もありません。判断モデルはテキストを生成しません。

## クイックスタート

まずは `jev-1.13-free` を使用してください。入力も出力も **\$0** で、残高がゼロでも利用できます。デフォルトの **auto** グループのキーを使います。無料版には専用の上限があり、初回チャージ前は**毎分 1 回の成功リクエスト**、チャージ後は**毎分最大 10 回**です。[無料の呼び出し](#free-calls)を参照してください。

```bash
curl https://api.beatapi.io/v1/systemone \
  -H "Authorization: Bearer $BEATAPI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "jev-1.13-free",
    "state": "Task: clean up inactive accounts before the quarterly report.\nProposed tool call: delete_rows(table=\"customers\", where=\"last_login < 2023-01-01\")\nContext: the customers table has 48,210 rows and no backup was taken today.",
    "questions": {
      "safe_to_run": {
        "type": "noul",
        "instructions": "Is this action safe to run without a human approving it first?",
        "criteria": {
          "true": "Reversible or low-impact, and clearly within the stated task.",
          "false": "Destructive, irreversible, or broader than the task requires."
        }
      }
    }
  }'
```

以下のレスポンスは説明用の例であり、実測結果ではありません。JSON を解析し、HTTP ステータスと回答の型を確認して値を検証したうえで、独自のしきい値を適用してください。

```json
{
  "id": "task_01J...",
  "model": "jev-1.13-free",
  "answers": {
    "safe_to_run": { "type": "noul", "noul": 0.04 }
  },
  "usage": { "input_tokens": 384, "output_tokens": 22 }
}
```

`0.04` は、モデルが回答を「はい」と判断する確率です。4% のため、エージェントは処理を止めて人に確認します。これが、この質問を行う目的です。

### 型付きの判断を 1 回で取得

接続先を BeatAPI に設定し、state と questions を送信して answers を取得します。別名の /v1/decisions も同じように使えます。これは chat/completions ではなく、jev-1.13-free はそちらでは利用できません。JSON を修復するための再試行ループは不要です。

```javascript
const response = await fetch("https://api.beatapi.io/v1/systemone", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.BEATAPI_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    model: "jev-1.13-free",
    state: {
      task: "clean up inactive accounts",
      tool: 'delete_rows(table="customers", where="last_login < 2023-01-01")',
      rows: 48210,
      backup_today: false,
    },
    questions: {
      safe_to_run: {
        type: "noul",
        instructions: "Is this action safe to run without a human approving it first?",
        criteria: {
          true: "Reversible or low-impact, and clearly within the stated task.",
          false: "Destructive, irreversible, or broader than the task requires.",
        },
      },
    },
  }),
});

if (!response.ok) {
  // On HTTP 429, wait the Retry-After seconds before retrying.
  throw new Error(`JEV HTTP ${response.status}; Retry-After: ${response.headers.get("Retry-After")}`);
}
const decision = await response.json();
const answer = decision.answers?.safe_to_run;
if (answer?.type !== "noul" || !Number.isFinite(answer.noul)
    || answer.noul < 0 || answer.noul > 1) {
  throw new Error("Invalid JEV answer; route to human review");
}
// Illustrative threshold: evaluate it on your own cases before use.
const needsReview = answer.noul < 0.9;
console.log({ probability: answer.noul, needsReview });
```

## リクエスト

| フィールド       | 型                         | 必須 | 説明                                                                                                           |
| ----------- | ------------------------- | -: | ------------------------------------------------------------------------------------------------------------ |
| `model`     | string                    | はい | `jev-1.13`、または無料で利用する場合は `jev-1.13-free` を指定します。モデルを指定しないリクエストは拒否されます。                                       |
| `state`     | string \| object \| array | はい | アプリケーションが現在把握している情報です。文字列、JSON オブジェクト、テキスト値の配列を使用できます。入力はテキストまたは構造化テキストです。画像、音声、動画、バイナリはテキストに変換してから送信してください。 |
| `questions` | object                    | はい | 名前を付けた 1 つ以上の質問です。名前は自由に指定でき、そのキーで回答が返ります。                                                                   |

各質問には `type`、`instructions`、そして型に応じて `criteria` を指定します。

| フィールド          | 型                         |          必須 | 説明                                                                                                            |
| -------------- | ------------------------- | ----------: | ------------------------------------------------------------------------------------------------------------- |
| `type`         | string                    |          はい | `noul`、`choice`、`score` のいずれかです。                                                                              |
| `instructions` | string \| object \| array | `noul` では必須 | 質問の内容です。同僚に尋ねるように記述してください。`noul` では、何についての真偽を問うのかを他に示す項目がないため必須です。`choice` と `score` は `criteria` だけでも指定できます。 |
| `criteria`     | 下記を参照                     |        型による | 回答の値が何を意味するかを定義します。                                                                                           |

## 3 つの質問形式

### `noul`：較正された確率

単純な二者択一ではなく、しきい値に基づいて真偽を判断したい場合に使用します。回答は `0`～`1` の数値です。

```json
"refund_ok": {
  "type": "noul",
  "instructions": "Should this refund be approved automatically?",
  "criteria": {
    "true": "Clear billing error, under $100, first request from this account.",
    "false": "Disputed usage, over $100, or a repeat request."
  }
}
```

```json
"refund_ok": { "type": "noul", "noul": 0.83 }
```

`criteria` は任意ですが、真偽の両方の条件を説明すると、回答がより明確になります。しきい値は自分で設定してください。例えば、`0.9` を超えたら自動承認、`0.6` 未満なら上位の担当者へ回し、その間は確認待ちのキューに入れます。

> **Note**
>
> `noul` は実際の型名であり、`bool` の誤記ではありません。型名を間違えると HTTP 400 で拒否され、使用できる 3 つの型が示されます。

### `choice`：指定した選択肢から選択

`criteria` は、各選択肢の名前とその意味を対応付けるオブジェクトです。回答には、選ばれた選択肢と全選択肢の確率分布が含まれます。

```json
"route": {
  "type": "choice",
  "instructions": "Which queue should this ticket go to?",
  "criteria": {
    "billing": "Payment, invoices, refunds, or charges.",
    "technical": "The product is broken or erroring.",
    "sales": "Pre-purchase questions about plans or pricing."
  }
}
```

```json
"route": {
  "type": "choice",
  "choice": "billing",
  "probabilities": { "billing": 1, "technical": 0, "sales": 0 },
  "confidence": 1
}
```

### `score`：独自の尺度上の値

`criteria` は、尺度を低い順に説明する配列です。回答は、`0` から始まる**配列のインデックス**上の連続値です。

```json
"urgency": {
  "type": "score",
  "instructions": "How urgent is this ticket?",
  "criteria": [
    "1 - can wait a week",
    "2 - answer within a few days",
    "3 - answer today",
    "4 - answer within an hour",
    "5 - wake someone up"
  ]
}
```

```json
"urgency": {
  "type": "score",
  "score": 1.98,
  "legend": { "0": "1 - can wait a week", "1": "2 - answer within a few days",
              "2": "3 - answer today", "3": "4 - answer within an hour",
              "4": "5 - wake someone up" },
  "probabilities": { "0": 0, "1": 0.17, "2": 0.67, "3": 0.16, "4": 0 },
  "confidence": 0.72
}
```

`1.98` は `legend["1"]` と `legend["2"]` の間で、後者の「今日中に回答」に近い値です。区分に振り分ける場合は丸め、キューを並べ替える場合は小数のまま使用します。

## 1 回の呼び出しで複数の質問

同じ状態について必要な質問をまとめて送信できます。各回答は独立しており、共通の状態は質問ごとではなく 1 回だけ計上されます。`jev-1.13-free` の呼び出しは引き続き無料です。

```bash
curl https://api.beatapi.io/v1/systemone \
  -H "Authorization: Bearer $BEATAPI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "jev-1.13-free",
    "state": {"ticket": "charged twice this month", "plan": "pro", "tenure_days": 412},
    "questions": {
      "refund_ok": {"type": "noul", "instructions": "Approve the refund automatically?"},
      "urgency":   {"type": "score", "instructions": "How urgent?", "criteria": ["low", "medium", "high"]}
    }
  }'
```

## レスポンス

| フィールド     | 説明                                                                                            |
| --------- | --------------------------------------------------------------------------------------------- |
| `model`   | 回答したモデルです。                                                                                    |
| `answers` | 質問ごとに 1 件の回答があり、指定した質問名がキーになります。                                                              |
| `usage`   | この呼び出しの `input_tokens` と `output_tokens` です。                                                  |
| `id`      | BeatAPI のリクエスト識別子です。サポートへの問い合わせ時に伝えてください。元の API の 3 フィールドに追加されており、このフィールドを型に含めないクライアントは無視します。 |

レスポンスは同期的に返され、HTTP レスポンスが成功すると判断は完了しています。ポーリングや生成ファイルの取得は不要です。

## 制限

* **コンテキスト。** `state` とすべての質問を合わせて 64K トークンまでです。また、`state` と最も長い個別の質問の合計は 32K トークン以内である必要があります。[モデルの上限](https://docs.typesafe.ai/models)を参照してください。
* **サンプリングパラメーターは使用できません。** `temperature`、`top_p`、`seed` などは受け付けません。回答の形式が一定になるように設計されたモデルです。
* **ストリーミングはありません。** 回答は値であり、トークンの列ではありません。
* **`choice` には空でない `criteria` オブジェクト、`score` には空でない `criteria` 配列が必要です。** 条件を満たさない場合は HTTP 400 で拒否され、どちらの条件に違反したかが示されます。`instructions` は任意ですが、空の値を指定すると処理に送信されずに拒否されます。

## エラー

エラーは BeatAPI 標準の形式で返され、すべてのエラーに `retryable` が含まれます。一覧と再試行の方針は[エラー](/errors)を参照してください。

| HTTP ステータス | コード                                                 | 意味                                                     |
| ---------: | --------------------------------------------------- | ------------------------------------------------------ |
|        400 | `bad_request`                                       | JSON、モデル、質問の型、criteria のいずれかが不正です。フィールド名がメッセージに示されます。  |
|        401 | `missing_api_key` / `invalid_api_key`               | キーが未送信、不正、期限切れ、無効、または利用上限に達しています。                      |
|        402 | `insufficient_credits`                              | 残高不足です。残高がゼロ、または呼び出しの料金に足りません。                         |
|        403 | `forbidden`                                         | キーまたはアカウントにモデルの利用権限がありません。例えば、無料クレジットでは利用できないモデルの場合です。 |
|        404 | `not_found`                                         | 不明なモデルです。                                              |
|        429 | `rate_limit_exceeded`                               | 無料モデルの上限を含むリクエストの上限に達しています。`Retry-After` の秒数だけ待ってください。 |
|        500 | `internal_error`                                    | 予期しない内部エラーです。再試行できます。                                  |
|        503 | `processing_unavailable` またはその他の `processing_*` コード | リクエストを完了できませんでした。待機時間を段階的に延ばして再試行してください。               |

失敗した呼び出しではクレジットは消費されません。

## 課金

有料モデル `jev-1.13` は、`state` と `questions` が占める**入力トークンのみ**を対象に、**入力 1M トークンあたり \$0.042** で課金されます。出力は生成された文章ではなく型付きの値のため、課金されません。各レスポンスの `usage.input_tokens` で、実際に計上されたトークン数を確認し、呼び出しごとの費用を照合できます。

そのため、同じ状態を何度も送信するより、1 回の呼び出しで複数の質問をまとめた方が、費用を大幅に抑えられます。

### 無料の呼び出し

`"model": "jev-1.13-free"` を指定すると、呼び出しは無料です。同じモデル、同じリクエストとレスポンスを使用し、指定した質問名で回答が返ります。残高がゼロでも使えるため、チャージ前に JEV をプロジェクトへ組み込めます。

* 新しいキーがデフォルトで使用する **auto** グループから利用できます。特定の 1 グループに固定したキーでは、このモデルは表示されません。
* 無料版にはアカウント単位の専用の固定上限があります。初回チャージ前は**毎分 1 回の成功リクエスト**、チャージ後は金額にかかわらず**毎分最大 10 回**です。アカウントの通常のレート制限とは別にカウントされ、無料の呼び出しで有料の利用枠を消費することはありません。
* 無料版の上限を超えると、`Retry-After` ヘッダー付きの `429 rate_limit_exceeded` が返ります。指定された時間だけ待ってから再試行してください。
* 有料モデル `jev-1.13` は、上記の料金で引き続き利用できます。累計チャージ額に応じて増える、アカウントの通常のレート制限が適用されます。利用するにはモデル名だけを変更してください。

### リクエスト上限を増やす

チャージ後も `jev-1.13-free` は無料のままで、**毎分最大 10 回の成功リクエスト**を送信できます。有料モデル `jev-1.13` の呼び出しには、アカウント共通の利用枠が適用されます。現在の上限と次のチャージ区分はダッシュボードで確認してください。JEV 専用の別枠ではありません。

[残高をチャージ](https://beatapi.io/dashboard/billing)したうえで、有料版を使う場合は `model` を `jev-1.13-free` から `jev-1.13` に明示的に変更してください。エンドポイント、`state`、`questions` はそのまま使用します。入力は **1M トークンあたり \$0.042**、出力は無料です。チャージしてもモデルは自動で切り替わらず、有料版の呼び出しには十分な残高が必要です。HTTP 429 の場合は `Retry-After` に従ってください。