# エラーと制限

> voicast の API が返すエラーの形・状態コード・エラーの種類と、回数・長さ・時間の上限。

Source: https://voicast.jp/docs/errors

## エラーの形

```json
{
  "error": "invalid_config",
  "message": "config に誤りがあります",
  "details": ["fields[0].key は英小文字・数字・_（先頭は英字）", "closing は空でない文字列"],
  "request_id": "req_…"
}
```

- 分岐には `error`（エラーの種類）を使います。`message` は人が読むための説明で、文言は変わることがあります。
- `details` は入力の誤り（422）のときに、項目ごとの誤りを並べます。
- `request_id` は呼び出しの ID です。成功・失敗にかかわらず、すべての応答の `x-request-id` にも入ります。問い合わせのときに伝えてください。

## 状態コード

| HTTP | 内容 |
| --- | --- |
| 400 | 本文が JSON でない |
| 401 | API キーが無い・違う・取り消し済み |
| 402 | 料金の都合で、新しい通話を断っている |
| 403 | 権限が足りない |
| 404 | 見つからない（ほかの環境のものも見つからない扱い） |
| 409 | 今の状態とぶつかる（重複・使用中など） |
| 422 | 入力の誤り |
| 429 | 回数の上限を超えた |
| 500 | voicast の中のエラー |
| 503 | 外のサービス（決済・連携先・Webhook の送信）に届かない、まだ設定されていない |

## エラーの種類

| HTTP | `error` | 内容 | 直し方 |
| --- | --- | --- | --- |
| 400 | `invalid_json` | 本文が JSON のオブジェクトでない | `Content-Type: application/json` で JSON のオブジェクトを送る |
| 401 | `unauthorized` | API キーが無い・違う・取り消し済み | `Authorization: Bearer vk_…` を確かめる |
| 402 | `balance_depleted` | 残高が 0 以下（チャージ式） | チャージするか、オートチャージを使う |
| 402 | `payment_overdue` | 請求書の支払い期限から 14 日たった（請求書払い） | 請求書を払う（払われればすぐ戻る） |
| 402 | `spending_cap_reached` | 今月の見込みが使いすぎの上限に届いた（請求書払い） | 管理画面で上限を上げる |
| 403 | `forbidden` | 役割が足りない・ブラウザからの MCP の呼び出し | 組織の owner か admin に役割を上げてもらう |
| 404 | `not_found` | ID が無い、ほかの環境のもの | 一覧で ID を確かめる。テストと本番のキーを取り違えていないか |
| 409 | `conflict` | 同じ `external_id` のテナントがある | 既存のテナントを使う |
| 409 | `in_use` | 会話の設定をテナントが使っている | テナントの `agent_id` を替えてから消す |
| 409 | `tenant_disabled` | テナントが止まっている | `PATCH /v1/tenants/{id}` で `status: active` にする |
| 409 | `needs_reauth` | 連携が切れている | 連携の画面でもう一度つなぐ |
| 422 | `invalid_request` | 入力の誤り | `message`・`details` を見て直す |
| 422 | `invalid_config` | 会話の設定・連携の設定の誤り | `details` の項目を直す |
| 422 | `no_agent` | 使う会話の設定が決まらない | `agent_id` を渡すか、テナントに設定する |
| 422 | `verify_failed` | 連携の保存の前の試しの呼び出しに失敗した | URL・API キーを確かめる |
| 422 | `connect_failed` | 連携を始められない（MCP サーバーのメタデータを読めないなど） | URL と相手の対応を確かめる |
| 429 | `rate_limited` | 回数の上限を超えた | 少し待ってから送り直す |
| 500 | `internal` | voicast の中のエラー | 少し待ってから送り直す。続くときはお問い合わせください |
| 503 | `unavailable` | 外のサービスに届かない・設定がまだ | 少し待ってから送り直す |

## 通話を断るとき

料金の都合で新しい通話を断るとき（402）は、経路ごとに次のように見えます。始まっている通話は切りません。

| 経路 | 見え方 |
| --- | --- |
| Web・アプリ | `POST /v1/sessions` が 402。セッションを作ってからつなぐまでに断ることになったときは、`webrtc_url` への offer が 403（いずれ 402 にそろえる予定です。403 も 402 も「つなげない」として扱ってください） |
| 電話 | 音声サーバーがすぐに接続を閉じ、Twilio は `action` か次の動詞へ進む。通話の記録は作られない |

## 回数の上限

| 対象 | 上限 |
| --- | --- |
| `/v1` の API と、API キーでの MCP の呼び出し | API キーごとに 1 分 600 回（合わせて数える） |
| MCP（ログインでの呼び出し） | 1 人あたり 1 分 300 回 |
| MCP のクライアントの登録 | 接続元ごとに 1 時間 30 回 |
| ログインのメール | 同じメールアドレスへ 1 時間 5 回 |

`/v1` の応答には、`x-ratelimit-limit`（1 分の上限）・`x-ratelimit-remaining`（残り）・`x-ratelimit-reset`（枠の終わり、Unix 秒）が付きます。上限を超えると 429 `rate_limited` と `Retry-After`（待つ秒数）を返すので、その秒数だけ待ってから送り直します（[SDK](https://voicast.jp/docs/sdk.md) は自動で送り直します）。

## 長さと時間の上限

| 対象 | 上限 |
| --- | --- |
| `client_token`（Web・アプリ） | 2 分・1 回だけ |
| 連携の画面のリンク・Webhook の設定画面のリンク | 15 分 |
| 接続の鍵・道具の署名の鍵を作り直したあと | 古い鍵も 24 時間通る |
| 通話中の道具の応答 | 8 秒まで待つ。応答の JSON は 4,000 文字まで AI に渡す |
| 連携の操作 | 3 秒で打ち切る |
| 会話の設定 | 聞き取る項目 20 個・よくある質問 50 個・道具 10 個・連携 10 個（[会話の設定](https://voicast.jp/docs/agents.md)） |
| `GET /v1/calls` | 1 回 100 件まで（既定 50） |
| `GET /v1/usage` | 期間は 366 日まで |
| 文字起こし | 500 発言まで・1 発言 2,000 文字まで |
| テナントの `external_id` | 英数字と `. _ : -` の 1〜100 文字 |
| 名前（会話の設定・テナント） | 100 文字まで |
