---
title: "Chat Completions API"
description: "*.arkor.app 推論エンドポイントのリクエスト/レスポンス完全仕様。"
---

すべての Arkor エンドポイントは `https://<slug>.arkor.app` で同じ OpenAI 互換サーフェスを提供します。このページはワイヤレベルのリファレンスで、[ワンクリックエンドポイント](/ja/docs/cloud/app-server)にも[プロジェクトのエンドポイント](/ja/docs/cloud/endpoints)にも等しく適用されます。

## ルート

| メソッド | パス | 用途 |
| ------ | ---- | ------- |
| `POST` | `/v1/chat/completions` | チャット補完（JSON または SSE ストリーミング） |
| `POST` | `/v1/messages` | Anthropic ネイティブの Messages API（Anthropic ダイアレクトのモデル専用） |
| `GET` | `/v1/models` | エンドポイントが配信するモデル id の一覧 |
| `GET` | `/v1/chat/completions/runs/{id}` | 保存済み実行の SSE リプレイ |
| `GET` | `/healthz` | 死活監視。`{ "ok": true }` を返す |

`GET /v1/models` は OpenAI 標準のリスト形式を返します。[マルチモデルエンドポイント](/ja/docs/cloud/endpoints#ターゲット)では現在の公開カタログを（モデルの公開に応じて一覧は変わります）、それ以外のエンドポイントでは固定された 1 モデルだけを返します。チャット補完と同じ API キー認証の背後にあり、レスポンスは最大 30 秒キャッシュされることがあります。

各モデルが話すワイヤダイアレクトは 1 つだけです。大半のモデルはこのページで説明する OpenAI chat completions サーフェスを話しますが、Anthropic のモデル（`claude-*` の id）は同じエンドポイントの `POST /v1/messages`（Anthropic ネイティブの Messages API）で配信されます。同じベース URL と API キーで Anthropic SDK を向ければ使えます。`GET /v1/models` は両者を区別せずに一覧するため、モデルを誤ったサーフェスに送ると、正しいルートを示すメッセージつきの `400` が返ります。

## 認証

**Fixed API key** モードのエンドポイントは、どちらのヘッダでもキーを受け付けます。

```bash title="curl"
curl https://<slug>.arkor.app/v1/chat/completions \
  -H "Authorization: Bearer $ARKOR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"messages":[{"role":"user","content":"こんにちは"}]}'
```

`x-api-key: <key>` も同じように動きます。**No auth** モードのエンドポイントはチェック自体を行いません。

認証失敗は `401` と機械可読な `code` を返します。

| コード | 意味 |
| ---- | ------- |
| `missing_key` | キーが提示されていない |
| `invalid_key` | どの有効キーとも一致しない |
| `no_keys` | キー必須のエンドポイントにキーが 1 つも設定されていない |

これらの `code` 値が現れるのは OpenAI 形式のルートだけです。`POST /v1/messages` では同じ認証失敗が Anthropic のエラーエンベロープ `{ "type": "error", "error": { "type": "authentication_error", "message": "..." } }` で返り、`code` フィールドはありません。

失効済みキーは、エッジのキャッシュが更新されるまで最大 30 秒ほど認証に通ることがあります。

## リクエストボディ

`POST /v1/chat/completions` は OpenAI の chat completions 形式を取ります。**4 MiB** を超えるリクエストは `413` で拒否されます。

| フィールド | 型 | 備考 |
| ----- | ---- | ----- |
| `messages` | 配列、必須 | チャットメッセージ 1 件以上。`content` はプレーン文字列、または OpenAI のコンテンツパート配列です。`text` パート（`{ "type": "text", "text": "..." }`）に加え、**user メッセージに限り** `image_url` パートを受け付けます。`image_url.url` はインラインの data URL（`data:image/<png\|jpeg\|webp\|gif>;base64,...`、正規の base64）のみ有効で、リモートの `http(s)` 画像 URL、user 以外のロールでの `image_url`、`input_audio` / `file` パートは `400` で拒否されます。画像 1 枚の data URL は約 6 MiB（画像データ約 4.5 MB 相当）まで。ただしリクエスト全体は 4 MiB のボディ上限に収める必要があるため、実用上はエンコード前で 2.5 MB 以下が目安です |
| `model` | string | 単一モデルのエンドポイントでは受理されるが**無視**される（モデルはエンドポイント側で固定）。[マルチモデルエンドポイント](/ja/docs/cloud/endpoints#ターゲット)では id でモデルを選択する（大文字小文字は区別しない）。省略時はデフォルトモデル、未知の id は `404`（コード `model_not_found`）。有効な id は `GET /v1/models` で一覧できます |
| `stream` | boolean | デフォルト `false`（JSON レスポンス） |
| `stream_options.include_usage` | boolean | ストリーミング時に usage チャンクを受け取るオプトイン |
| `n` | integer | `1`（OpenAI のデフォルト）のみ受理。それ以外は `400`（パイプラインは単一 choice のみ配信） |
| `temperature` | number | 0〜2 |
| `top_p` | number | 0〜1 |
| `max_tokens` | integer | 正の整数 |
| `max_completion_tokens` | integer | OpenAI の新しい出力トークン上限フィールド。両方受理され、両方送られた場合は `max_completion_tokens` が優先されます |
| `stop` | string または配列 | 停止シーケンス。空でない文字列のみ、リストは 16 個まで |
| `presence_penalty` | number | -2〜2 |
| `frequency_penalty` | number | -2〜2 |
| `seed` | integer | ベストエフォートの決定的サンプリング |
| `logprobs` | boolean | 出力トークンの対数確率を返す |
| `top_logprobs` | integer | 0〜20。0 より大きい値には `logprobs: true` が必要（モデルサーバ側で検証） |
| `logit_bias` | object | 文字列化したトークン id → バイアス（-100〜100） |
| `tools` / `tool_choice` | OpenAI 形式 | Function calling。ツールパーサ対応モデルが必要なのは自動選択（`tool_choice` 未指定または `"auto"`）のみで、名前付き関数指定・`"required"`・`"none"` はパーサなしでも動作します |
| `response_format` | OpenAI 形式 | `json_schema` による構造化出力を含む |
| `structured_outputs` | object | vLLM 拡張。`json` / `regex` / `choice` / `grammar` / `json_object` の制約フィールド（相互排他） |
| `enable_thinking` | boolean | 対応モデルでの推論（thinking）モード |
| `reasoning_effort` | string | `none` / `minimal` / `low` / `medium` / `high` / `xhigh` / `max` のいずれか（それ以外は `400`）。Gemma 4 は Thinking のオン/オフのみを区別するため、`none` は Thinking オフ、それ以外の値はすべて Thinking オンに丸められます |
| `user` | string | OpenAI のエンドユーザー・アトリビューションフィールド。`X-Arkor-End-User-Id` と同じ[使用量](/ja/docs/cloud/usage)アトリビューションに反映されます（両方ある場合はヘッダが優先）。値は使用量履歴に保存され、集計キーになります。制約はアトリビューションヘッダと同じで、印字可能な Latin-1 で 256 文字まで。それ以外の値（日本語など）は黙って破棄されます。認可には使われません |

メッセージのロールは OpenAI の 4 種 `system` / `user` / `assistant` / `tool` です。新しい `developer` ロールは受理されず `400` になります。assistant メッセージは `tool_calls` を持てて（その場合 `content` は省略可）、`tool` メッセージは必須の `tool_call_id` で応答先を指定します。任意の `name` 参加者ラベルは system / user / assistant メッセージで受理されます。

未知のフィールドは拒否されず取り除かれるので、OpenAI SDK 固有の追加フィールドがエラーになることはありません。ツール定義・JSON スキーマ・`structured_outputs` の制約はそのままモデルサーバに転送されます。

## レスポンスとストリーミング

`stream: false`（デフォルト）では標準の `chat.completion` JSON オブジェクトを返します。`stream: true` では OpenAI 形式の SSE チャンクを返し、`data: [DONE]` で終端します。usage は `stream_options.include_usage` を指定した場合のみストリームに含まれます。

Reasoning パーサ付きで動くモデルは、推論内容を可視の回答とは別に `delta.reasoning_content` として出力します。

実行履歴の保存が有効な場合、Arkor が永続化したレスポンスには保存された実行を指す `X-Arkor-Run-Id` ヘッダが付きます（[実行履歴](/ja/docs/cloud/runs)参照）。外部のサードパーティプロバイダが配信したレスポンス（例えばマルチモデルエンドポイント上の Gemini や Claude モデル）は保存設定に関わらず永続化されず、run id も付きません。

## 保存済み実行のリプレイ

`GET /v1/chat/completions/runs/{id}` は保存済み実行の SSE ストリームを再送します。`Last-Event-ID` または `?from=` クエリでの再開に対応します。未知・期限切れ・別エンドポイントの実行 id は `410`（コード `run_gone`）を返します。

## アトリビューションヘッダ

2 つの任意リクエストヘッダで、[使用量](/ja/docs/cloud/usage)の内訳にリクエストをラベル付けできます。

- `X-Arkor-End-User-Id` には、あなたのアプリケーションのユーザー id を指定します。
- `X-Arkor-Session-Id` には、会話やセッションの id を指定します。

値は印字可能な Latin-1 で 256 文字までです。不正な値は黙って破棄され、リクエストが拒否されることはなく、認可に使われることもありません。

OpenAI の `user` ボディフィールドも同じエンドユーザー・アトリビューションに反映されます。フィールドと `X-Arkor-End-User-Id` ヘッダの両方がある場合はヘッダが優先されます。Anthropic Messages ルートでは標準の `metadata.user_id` フィールドが同じ役割を果たし、優先順位も同じです（ヘッダが優先）。上記の制約はこれらのボディフィールドにも適用されます。256 文字超や印字可能な Latin-1 以外の値（日本語のテキストなど）は黙って破棄され、リクエストは成功してもエンドユーザー・アトリビューションは付きません。採用された値はリクエストの使用量行に保存されるため、記録されたくない識別子は送らないでください。

## エラー

| ステータス | 条件 |
| ------ | ---- |
| `400` | 不正な JSON、スキーマ違反、`response_format` と `structured_outputs` の矛盾 |
| `401` | 認証失敗（上記コード参照） |
| `403` | 選択したモデルに Arkor アカウントが必要（コード `model_requires_signup`）。プレミアムモデルは匿名エンドポイントの `GET /v1/models` にも表示されますが、そこからのディスパッチはサインアップ案内つきで拒否されます |
| `404` | 未知のサブドメイン、無効化済み、または期限切れのエンドポイント（メッセージは一律）。マルチモデルエンドポイントでは未知の `model` id も該当（コード `model_not_found`） |
| `410` | 保存済み実行が存在しない（リプレイルート） |
| `413` | ボディが 4 MiB 超 |
| `429` | レート制限（コード `rate_limit_exceeded`）。理由は 2 通りあります。エンドポイント所有者の推論クォータ超過（匿名のワンクリックエンドポイントにはアカウント所有より厳しい分・日単位の上限があります）、または外部プロバイダが処理したマルチモデルリクエストでベンダ側のレート制限が尽きた場合。いずれもレスポンスに `Retry-After` ヘッダ（秒。外部の場合はベンダの値を転送）が付くので、それ以上待ってからリトライしてください |
| `499` | クライアントが処理中に接続を切断 |
| `502` | 上流モデルサーバのエラー |
| `503` | プロバイダが一時的に利用不可（コード `provider_env_unavailable`）。リトライ可能 |
| `504` | すべての推論候補が応答前にタイムアウト（コード `inference_upstream_timeout`）。リトライ可能 |
| `529` | 試行したすべての外部プロバイダが過負荷を報告（コード `overloaded`。Anthropic の慣例に準拠）。ベンダの `Retry-After` があれば転送されます。時間を置いてリトライしてください |

OpenAI 互換ルート（`POST /v1/chat/completions` と `GET /v1/models`）のエラーボディは OpenAI のネストされたエンベロープです。

```json title="エラーボディ（OpenAI 互換ルート）"
{ "error": { "message": "...", "type": "...", "param": null, "code": "..." } }
```

Arkor 固有のリプレイルート（`GET /v1/chat/completions/runs/{id}`）だけはフラットなエンベロープ（`{ "error": string, "code"?: string }`）を維持します。

## CORS

エンドポイントは許容的な CORS（`Access-Control-Allow-Origin: *`、credentials なし）を送るため、ブラウザから直接呼び出せます。許可されるリクエストヘッダには `Authorization`、`Content-Type`、`x-api-key`、`Last-Event-ID`、および上記のアトリビューションヘッダが含まれます。
