APIリファレンス
はじめに
DMM AI Routerは、さまざまなLLMを1つのAPIキーと共通のリクエスト形式で呼び出せるREST APIを提供します。すべてのリクエストはJSONで送り、応答はJSON(ストリーミング時はServer-Sent Events)で返ります。提供するエンドポイントは、呼び出せるモデルの一覧を返すGET /v1/modelsと、会話形式でテキストを生成するPOST /v1/chat/completionsの2つです。EmbeddingsやResponses API、画像・音声の入出力は提供していません。
1つのモデルに複数の供給元(provider)の経路があるとき、最も安い経路から順に試します。障害のほか、レート制限や負荷の集中で一時的に利用できないときも、次の経路に切り替えます。どの供給元が応答したかは、レスポンスのprovider項目で確認できます。
https://api.airouter.dmm.com/v1curl https://api.airouter.dmm.com/v1/chat/completions \
-H "Authorization: Bearer $AIROUTER_API_KEY" \
-H "Content-Type: application/json" \
-d '{"model": "google/gemini-2.5-flash", "messages": [{"role": "user", "content": "Hello!"}]}'認証
APIキーをAuthorization: Bearerヘッダで渡します。キーはダッシュボードの「APIキー」で発行し、利用料はキーが属するワークスペースの残高から精算します。用途ごとに複数のキーを作れます。失効したキーは即座に使えなくなり、元に戻せません。
キーごとに1か月あたりの利用額の上限を設定できます。上限に達すると、そのキーからのリクエストは402(monthly_limit_exceeded)になります。集計は毎月1日0:00 UTC(日本時間9:00)にリセットされます。
- キーはサーバー側だけで使い、ブラウザやモバイルアプリに埋め込まないでください。
- ソースコードにキーを書かず、環境変数やシークレット管理の仕組みから読み込んでください。
POST /v1/chat/completions HTTP/1.1
Host: api.airouter.dmm.com
Authorization: Bearer sk-air-...
Content-Type: application/jsoncurl https://api.airouter.dmm.com/v1/models \
-H "Authorization: Bearer $AIROUTER_API_KEY"Models
/v1/models現在呼び出せるモデルの一覧を返します。idがそのままmodelに指定する値、owned_byはモデルの開発元です。
各モデルのコンテキスト長・最大出力・単価・データ保持方針はモデル一覧で確認できます。単価は最も安い経路のもので、利用料は実際に応答した経路の単価で精算します。
レスポンス
modelオブジェクトの一覧。
一覧オブジェクト
objectstring常に
list取りうる値:listdataarrayモデルの配列
4個の子の項目を表示子の項目を隠す
idstring公開モデルID。
modelに指定する値objectstring常に
model取りうる値:modelcreatedinteger登録時刻(UNIX秒)
owned_bystringモデルの開発元
curl https://api.airouter.dmm.com/v1/models \
-H "Authorization: Bearer $AIROUTER_API_KEY"{
"object": "list",
"data": [
{
"id": "google/gemini-2.5-flash",
"object": "model",
"created": 1759363200,
"owned_by": "google"
},
{
"id": "deepseek/deepseek-v4-pro",
"object": "model",
"created": 1759363200,
"owned_by": "deepseek"
}
]
}Chat Completions
/v1/chat/completions会話からモデルの応答を生成します。streamがtrueのときはchat.completion.chunkの列をServer-Sent Eventsで返します。
temperatureやreasoning_effortなどの生成パラメータは、供給元とモデルごとにベストエフォートで適用されます。
リクエスト本文
modelstring必須公開モデルID。
GET /v1/modelsのidと同じmessagesarray必須会話の履歴。古い順に並べた1件以上の配列。JSONにして2,000,000文字まで
6個の子の項目を表示子の項目を隠す
rolestring必須発言者の役割
取りうる値:systemuserassistanttoolcontentstring | array | null必須本文。文字列か、
typeがtextのパートの配列。assistantでツール呼び出しだけを返した発言ではnull可namestring発言者の識別名
対象: system, user, assistant
tool_callsarrayモデルが返したツール呼び出しをそのまま入れる
対象: assistant
3個の子の項目を表示子の項目を隠す
idstring必須呼び出しのID。toolメッセージの
tool_call_idと対応typestring必須常に
function取りうる値:functionfunctionobject必須呼び出す関数
2個の子の項目を表示子の項目を隠す
namestring必須関数名
argumentsstring必須引数のJSON文字列。モデルが出した値をそのまま渡す
refusalstring | nullモデルが生成を拒否したときの文
対象: assistant
tool_call_idstring必須応答先のツール呼び出しの
id対象: tool
streamboolean既定: falsetrueでServer-Sent Eventsによる逐次応答stream_optionsobjectストリーミングの追加設定。
streamがtrueのときだけ指定可1個の子の項目を表示子の項目を隠す
include_usagebooleanusageイベントは指定に関わらず常に送るため、結果は変わらない
max_completion_tokensinteger生成する出力トークンの上限
max_tokensintegermax_completion_tokensと同じ意味の旧名。どちらか一方だけ指定可reasoning_effortstring推論の労力。取りうる値と効果はモデルによる
temperaturenumber出力のランダムさ。0から2
top_pnumbernucleusサンプリングの確率質量。0から1
seedinteger決定的な出力を得るための乱数シード。保証はモデルによる
presence_penaltynumber既出トークンへのペナルティ。-2から2
frequency_penaltynumber出現頻度に応じたペナルティ。-2から2
response_formatobject応答の形式。省略時は制限しない
2個の子の項目を表示子の項目を隠す
typestring必須形式の種類
取りうる値:textjson_objectjson_schemajson_schemaobjecttypeがjson_schemaのとき必須4個の子の項目を表示子の項目を隠す
namestring必須スキーマの名前。英数字・
_・-で1から64文字descriptionstringスキーマの説明
schemaobject必須JSON Schemaオブジェクト
strictbooleantrueでスキーマへの厳密な準拠を要求
toolsarrayモデルが呼び出せる関数の一覧
2個の子の項目を表示子の項目を隠す
typestring必須常に
function取りうる値:functionfunctionobject必須関数の定義
4個の子の項目を表示子の項目を隠す
namestring必須関数名
descriptionstring関数の説明。モデルが呼ぶかどうかを判断する材料
parametersobject引数のJSON Schema
strictbooleantrueで引数のスキーマへの厳密な準拠を要求
tool_choicestring | object既定: autoツール呼び出しの制御。
none・auto・requiredの文字列か、関数を指定するオブジェクト(typeがfunction、function.nameに関数名)parallel_tool_callsbooleanfalseで1回の応答のツール呼び出しを1つに制限するよう要求
上限
- リクエスト本文は10 MiBまで。超えると
413(payload_too_large)を返します。 messages全体はJSONにして2,000,000文字まで。超えると400を返します。
レスポンス
chat.completionオブジェクト。idは応答ヘッダx-request-idと同じ値です。
利用料はprompt_tokensとcompletion_tokensにモデルの単価を掛けた額で、ワークスペースの残高から精算します。居住国が日本の場合は消費税を加えます。
レスポンスオブジェクト
idstring受付ID。応答ヘッダ
x-request-idと同じ値objectstring常に
chat.completion取りうる値:chat.completioncreatedinteger作成時刻(UNIX秒)
modelstring応答した公開モデルID
providerstring応答した供給元のID
choicesarray生成結果。常に1件
3個の子の項目を表示子の項目を隠す
indexinteger候補の番号。常に0
messageobjectモデルの応答
4個の子の項目を表示子の項目を隠す
rolestring常に
assistant取りうる値:assistantcontentstring | null本文。ツール呼び出しだけのときは
nullrefusalstring | null生成を拒否したときの文。通常は
nulltool_callsarrayモデルが要求したツール呼び出し。無いときは項目ごと省く
3個の子の項目を表示子の項目を隠す
idstring必須呼び出しのID。toolメッセージの
tool_call_idと対応typestring必須常に
function取りうる値:functionfunctionobject必須呼び出す関数
2個の子の項目を表示子の項目を隠す
namestring必須関数名
argumentsstring必須引数のJSON文字列。モデルが出した値をそのまま渡す
finish_reasonstring生成が終わった理由
取りうる値:stoplengthtool_callscontent_filter
usageobjectトークン使用量
5個の子の項目を表示子の項目を隠す
prompt_tokensinteger入力トークン数
completion_tokensinteger出力トークン数
total_tokensinteger合計
prompt_tokens_detailsobject入力の内訳。供給元が返したときだけ含まれる
completion_tokens_detailsobject出力の内訳。供給元が返したときだけ含まれる
curl https://api.airouter.dmm.com/v1/chat/completions \
-H "Authorization: Bearer $AIROUTER_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "google/gemini-2.5-flash",
"messages": [
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "Hello!"}
]
}'{
"id": "01K72W3M9Q4ZJ8N2T6VY5XH0RB",
"object": "chat.completion",
"created": 1759968000,
"model": "google/gemini-2.5-flash",
"provider": "edensoft",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": "Hello! How can I help you today?",
"refusal": null
},
"finish_reason": "stop"
}
],
"usage": {
"prompt_tokens": 17,
"completion_tokens": 9,
"total_tokens": 26
}
}ストリーミング
streamをtrueにするとtext/event-streamで返ります。各イベントはdata: に続くJSONです。
イベントの順序
- 本文を少しずつ運ぶチャンク。
choices[0].deltaに差分が入り、生成が進むたびに届きます - 最後のチャンク。
usageにトークン数が入ります data: [DONE]。ストリームの終わりです
各チャンクのchoices[0].deltaには差分だけが入ります。contentを順に連結すると本文になります。ツール呼び出しはtool_calls[].indexが同じ断片をつなぎ、function.argumentsは連結してからJSONとして解釈します。
チャンクオブジェクト
idstring受付ID。応答ヘッダ
x-request-idと同じ値objectstring常に
chat.completion.chunk取りうる値:chat.completion.chunkcreatedinteger作成時刻(UNIX秒)
modelstring応答した公開モデルID
providerstring応答した供給元のID
choicesarray差分
3個の子の項目を表示子の項目を隠す
indexinteger候補の番号。常に0
deltaobject前のチャンクからの差分
4個の子の項目を表示子の項目を隠す
rolestring最初のチャンクにだけ
assistantcontentstring | null本文の断片
refusalstring | null拒否文の断片
tool_callsarrayツール呼び出しの断片。
indexが同じものをつなぐ4個の子の項目を表示子の項目を隠す
indexinteger必須呼び出しの番号
idstring最初の断片にだけ
typestring最初の断片にだけ
functionfunctionobject関数の断片
2個の子の項目を表示子の項目を隠す
namestring最初の断片にだけ
argumentsstring引数JSON文字列の断片
finish_reasonstring | null途中は
null。最後の本文チャンクで確定。開始後に失敗したときはerror取りうる値:stoplengthtool_callscontent_filtererror
usageobject終端直前のusageイベントにだけ
5個の子の項目を表示子の項目を隠す
prompt_tokensinteger入力トークン数
completion_tokensinteger出力トークン数
total_tokensinteger合計
prompt_tokens_detailsobject入力の内訳。供給元が返したときだけ含まれる
completion_tokens_detailsobject出力の内訳。供給元が返したときだけ含まれる
errorobject開始後に失敗したときの終端イベントにだけ。形はエラー応答の
errorと同じ3個の子の項目を表示子の項目を隠す
messagestringエラーの説明
codestring分岐に使う安定した識別子
paramstring | null入力が原因のときの場所(ドット区切り、配列は添字付き)。それ以外は
null
curl https://api.airouter.dmm.com/v1/chat/completions \
-H "Authorization: Bearer $AIROUTER_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "google/gemini-2.5-flash",
"messages": [{"role": "user", "content": "Hello!"}],
"stream": true
}'data: {"id":"01K72W3M9Q4ZJ8N2T6VY5XH0RB","object":"chat.completion.chunk","created":1759968000,"model":"google/gemini-2.5-flash","provider":"edensoft","choices":[{"index":0,"delta":{"role":"assistant","content":""},"finish_reason":null}]}
data: {"id":"01K72W3M9Q4ZJ8N2T6VY5XH0RB","object":"chat.completion.chunk","created":1759968000,"model":"google/gemini-2.5-flash","provider":"edensoft","choices":[{"index":0,"delta":{"content":"Hello"},"finish_reason":null}]}
data: {"id":"01K72W3M9Q4ZJ8N2T6VY5XH0RB","object":"chat.completion.chunk","created":1759968000,"model":"google/gemini-2.5-flash","provider":"edensoft","choices":[{"index":0,"delta":{"content":"! How can I help you today?"},"finish_reason":"stop"}]}
data: {"id":"01K72W3M9Q4ZJ8N2T6VY5XH0RB","object":"chat.completion.chunk","created":1759968000,"model":"google/gemini-2.5-flash","provider":"edensoft","choices":[{"index":0,"delta":{},"finish_reason":null}],"usage":{"prompt_tokens":17,"completion_tokens":9,"total_tokens":26}}
data: [DONE]{
"id": "01K72W3M9Q4ZJ8N2T6VY5XH0RB",
"object": "chat.completion.chunk",
"created": 1759968000,
"model": "google/gemini-2.5-flash",
"provider": "edensoft",
"choices": [
{
"index": 0,
"delta": {"content": "Hello"},
"finish_reason": null
}
]
}ツール呼び出し
モデルに関数の定義を渡し、呼び出しの指示を受け取って、結果を返す往復を行います。
toolsに関数の名前・説明・引数のJSON Schemaを渡してリクエストします。- モデルが呼び出しを決めると、
finish_reasonがtool_callsになり、message.tool_callsに呼び出す関数と引数(JSON文字列)が入ります。 - 関数をあなたのコードで実行し、
tool_callsを含むassistantメッセージの直後に、roleがtool、tool_call_idが呼び出しのidのメッセージを追加して再度リクエストします。 - モデルが結果を踏まえた最終的な応答を返します。
curl https://api.airouter.dmm.com/v1/chat/completions \
-H "Authorization: Bearer $AIROUTER_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "google/gemini-2.5-flash",
"messages": [{"role": "user", "content": "What is the weather in Tokyo?"}],
"tools": [{
"type": "function",
"function": {
"name": "get_weather",
"description": "Get the current weather for a city.",
"parameters": {
"type": "object",
"properties": {
"city": {"type": "string", "description": "City name"}
},
"required": ["city"]
}
}
}],
"tool_choice": "auto"
}'{
"id": "01K72W3M9Q4ZJ8N2T6VY5XH0RB",
"object": "chat.completion",
"created": 1759968000,
"model": "google/gemini-2.5-flash",
"provider": "edensoft",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": null,
"refusal": null,
"tool_calls": [
{
"id": "call_7Yq3",
"type": "function",
"function": {
"name": "get_weather",
"arguments": "{\"city\": \"Tokyo\"}"
}
}
]
},
"finish_reason": "tool_calls"
}
],
"usage": {
"prompt_tokens": 58,
"completion_tokens": 14,
"total_tokens": 72
}
}curl https://api.airouter.dmm.com/v1/chat/completions \
-H "Authorization: Bearer $AIROUTER_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "google/gemini-2.5-flash",
"messages": [
{"role": "user", "content": "What is the weather in Tokyo?"},
{
"role": "assistant",
"content": null,
"tool_calls": [
{
"id": "call_7Yq3",
"type": "function",
"function": {"name": "get_weather", "arguments": "{\"city\": \"Tokyo\"}"}
}
]
},
{
"role": "tool",
"tool_call_id": "call_7Yq3",
"content": "{\"temperature_c\": 24, \"condition\": \"sunny\"}"
}
],
"tools": [{
"type": "function",
"function": {
"name": "get_weather",
"description": "Get the current weather for a city.",
"parameters": {
"type": "object",
"properties": {
"city": {"type": "string", "description": "City name"}
},
"required": ["city"]
}
}
}]
}'calls = {}
for chunk in stream:
choice = chunk.choices[0]
for part in choice.delta.tool_calls or []:
call = calls.setdefault(part.index, {"id": None, "name": None, "arguments": ""})
if part.id:
call["id"] = part.id
if part.function and part.function.name:
call["name"] = part.function.name
if part.function and part.function.arguments:
call["arguments"] += part.function.arguments
if choice.finish_reason == "tool_calls":
break
# calls[index]["arguments"] is now a complete JSON string構造化出力
response_formatで応答をJSONに限定できます。json_schemaはスキーマに従ったJSONを、json_objectは任意のJSONを返すよう指示します。
json_schema.nameとjson_schema.schemaが必須です。strictをtrueにすると、対応するモデルではスキーマへの厳密な準拠を求めます。応答のmessage.contentはJSONの文字列なので、受け取った側でパースしてください。
curl https://api.airouter.dmm.com/v1/chat/completions \
-H "Authorization: Bearer $AIROUTER_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "google/gemini-2.5-flash",
"messages": [
{"role": "system", "content": "Extract the event details."},
{"role": "user", "content": "Team lunch on Friday at 12:30 in Shibuya."}
],
"response_format": {
"type": "json_schema",
"json_schema": {
"name": "event",
"schema": {
"type": "object",
"properties": {
"title": {"type": "string"},
"day": {"type": "string"},
"time": {"type": "string"},
"location": {"type": "string"}
},
"required": ["title", "day", "time", "location"],
"additionalProperties": false
},
"strict": true
}
}
}'{
"role": "assistant",
"content": "{\"title\":\"Team lunch\",\"day\":\"Friday\",\"time\":\"12:30\",\"location\":\"Shibuya\"}",
"refusal": null
}{
"model": "google/gemini-2.5-flash",
"messages": [
{"role": "system", "content": "Answer in JSON with keys \"answer\" and \"confidence\"."},
{"role": "user", "content": "What is the capital of Japan?"}
],
"response_format": {"type": "json_object"}
}{
"error": {
"message": "This model does not support JSON output.",
"code": "unsupported_parameter",
"param": "response_format"
}
}エラー
エラーはHTTPステータスとJSON本文で返します。本文はerrorオブジェクトを1つ持ち、message・code・paramで構成されます。
エラーオブジェクト
messagestringエラーの説明
codestring分岐に使う安定した識別子
paramstring | null入力が原因のときの場所(ドット区切り、配列は添字付き)。それ以外は
null
ストリーム中のエラー
ストリームを始める前の失敗は通常のHTTPエラー応答です。始まったあとの失敗はHTTP 200のまま、finish_reasonがerrorでerrorを持つイベントを送り、[DONE]で閉じます。途中まで届いた本文は破棄するか再試行してください。
HTTPステータス
| HTTPステータス | 意味 |
|---|---|
| 400 | リクエストの内容に問題がある |
| 401 | APIキーが無効 |
| 402 | 残高不足、またはキーの月額上限 |
| 404 | モデルが存在しない |
| 413 | 本文が大きすぎる |
| 5xx | サーバーまたは供給元の障害 |
エラーコード一覧
| code | 意味 |
|---|---|
| validation_failed400 | 本文が仕様に合わない。paramに場所が入るparamとmessageを見て修正する |
| invalid_request400 | JSONとして読めないなど、HTTPリクエスト自体の問題リクエストの組み立てを確認する |
| unsupported_parameter400 | モデルが対応しない指定(JSON出力など)指定を外すか、別のモデルを使う |
| provider_rejected_request400 | すべての供給元がリクエストの内容を理由に拒否した。パラメータや入力がモデルに合わないパラメータを減らす・入力を見直す・別のモデルを使う |
| invalid_api_key401 | キーが無い・形式が違う・失効済みAuthorizationヘッダとキーを確認する |
| insufficient_credits402 | ワークスペースの残高が不足チャージする |
| monthly_limit_exceeded402 | キーの月額上限に達した上限を見直すか、翌月まで待つ |
| model_not_found404 | モデルが存在しないか提供終了GET /v1/modelsでIDを確認する |
| payload_too_large413 | 本文が10 MiBを超えた入力を減らす |
| internal_error5xx | サーバーまたは供給元の障害時間をおいて再試行する |
応答が得られなかったリクエストには課金しません。
すべての応答にx-request-idヘッダが付きます。サポートへ問い合わせる際は、この値と発生時刻をお知らせください。
HTTP/1.1 400 Bad Request
Content-Type: application/json; charset=utf-8
x-request-id: 01K72W3M9Q4ZJ8N2T6VY5XH0RB
{
"error": {
"message": "messages[1].role: role must be one of system, user, assistant or tool.",
"code": "validation_failed",
"param": "messages[1].role"
}
}data: {"id":"01K72W3M9Q4ZJ8N2T6VY5XH0RB","object":"chat.completion.chunk","created":1759968000,"model":"google/gemini-2.5-flash","provider":"edensoft","choices":[{"index":0,"delta":{"content":"Hello"},"finish_reason":null}]}
data: {"id":"01K72W3M9Q4ZJ8N2T6VY5XH0RB","object":"chat.completion.chunk","created":1759968000,"model":"google/gemini-2.5-flash","provider":"edensoft","choices":[{"index":0,"delta":{},"finish_reason":"error"}],"error":{"message":"An unexpected error occurred. Please try again later.","code":"internal_error","param":null}}
data: [DONE]