コンソール

APIリファレンス

共通規約

ベースURL

すべてのエンドポイントは /v1 プレフィックスの下で提供されます。

認証

/v1/* エンドポイントへの呼び出しは APIキー認証を使用します (JWTではありません)。APIキーは以下のヘッダーで渡されます:

ヘッダーフォーマット説明
AuthorizationBearer <api_key>OpenAIスタイル。Anthropic互換エンドポイントは x-api-key と anthropic-version: 2023-06-01 も受け付けます。

キーが存在しない、または無効な場合は 401 を返します。

残高事前チェック

すべてのモデル呼び出しエンドポイントは実行前に残高事前チェックを行います:

  • 残高不足の場合 Insufficient credit を返し、以下にマッピングされます:
    • OpenAIプロトコル:HTTP 400、 code = insufficient_quota
    • Anthropicプロトコル:HTTP 402、type = billing_error
  • 一部のエンドポイントは2回目の事前チェックのためにモデルごとの最小コストを見積もります。

Create Chat CompletionPOSThttps://api.basicrouter.ai/api/v1/chat/completions

OpenAI Chat Completions互換エンドポイント。ストリーミングと非ストリーミング、ツール 呼び出し、JSONモード、マルチモーダル入力をサポートします。

フィールドタイプ必須説明
modelStringはいモデル名。
messagesMessage[]はい会話メッセージ。
streamBooleanいいえストリームモード、デフォルト false。
temperatureDoubleいいえサンプリング温度。
max_tokensIntegerいいえ最大出力トークン数。
top_pDoubleいいえ核サンプリング。
presence_penaltyDoubleいいえ—
frequency_penaltyDoubleいいえ—
toolsTool[]いいえツール定義。
tool_choiceString|Objectいいえauto / none / required / 特定の 関数。
response_formatObjectいいえ{type, json_schema:{name,schema,strict}}; text/json_object/json_schema。
parallel_tool_callsBooleanいいえ—
metadataMapいいえパススルーメタデータ。

Message フィールド:

フィールドタイプ説明
roleStringsystem / user / assistant / tool。
contentString|Arrayプレーンテキストまたはマルチモーダルコンテンツブロック配列 ([{type:"text",text},{type:"image_url",image_url:{url}}])。
tool_call_idStringrole=tool の場合、tool_callsにリンクします。
tool_callsToolCall[]role=assistant がツール呼び出しを行う場合に存在します。
フィールドタイプ説明
typeString固定値 function。
functionObject関数定義。
function.nameString関数名。
function.descriptionString関数の説明。
function.parametersObject入力のJSONスキーマ。
curl --request POST \
  --url https://api.basicrouter.ai/api/v1/chat/completions \
  --header "Authorization: Bearer $BASICROUTER_API_KEY" \
  --header "Content-Type: application/json" \
  --data '{
    "model": "glm-5.2",
    "messages": [{"role": "user", "content": "Describe Hangzhou in one sentence."}],
    "stream": false,
    "temperature": 0.7
  }'
{
  "id": "chatcmpl-xxx",
  "object": "chat.completion",
  "created": 1721380000,
  "model": "glm-5.2",
  "choices": [
    {
      "index": 0,
      "message": {"role": "assistant", "content": "Hangzhou is ..."},
      "finish_reason": "stop"
    }
  ],
  "usage": {"prompt_tokens": 12, "completion_tokens": 18, "total_tokens": 30}
}

レスポンスフィールド(非ストリーミング):

フィールドタイプ説明
idString補完ID。
objectString固定値 chat.completion。
createdLong作成タイムスタンプ(秒)。
modelStringモデル名。
choicesChoice[]{index, message:{role, content, tool_calls?}, finish_reason}。
usageObject{prompt_tokens, completion_tokens, total_tokens}。
フィールドタイプ説明
idStringツール呼び出しID。
typeString固定値 function。
functionObject関数呼び出しの詳細。
function.nameString関数名。
function.argumentsObject関数の引数。

ストリーミングレスポンスの例:

data: {"object":"chat.completion.chunk","choices":[{"delta":{"role":"assistant","content":"..."}}]}

data: {"object":"chat.completion.chunk","choices":[{"delta":{"content":"..."}}]}

data: [DONE]

Create ResponsePOSThttps://api.basicrouter.ai/api/v1/responses

OpenAI Responses互換エンドポイント。messages の代わりに input を、 システムメッセージの代わりに instructions を、response_format の 代わりに text ブロックを使用します。

フィールドタイプ必須説明
modelStringはいモデル名。
inputString|Arrayはいプレーン文字列(ユーザーメッセージ)またはメッセージオブジェクト配列。
instructionsStringいいえシステムプロンプト。
streamBooleanいいえデフォルト false。
max_output_tokensIntegerいいえ最大出力トークン数。
temperatureDoubleいいえデフォルト 1。
top_pDoubleいいえ—
toolsTool[]いいえ最上位の {type, name, description, parameters}。
tool_choiceString|Objectいいえauto/none/required/{type,name}。
textObjectいいえ{format:{type, name, schema, strict}}; text/json_object/json_schema。
metadataMapいいえ—
previous_response_idStringいいえマルチターン用の前回のレスポンスID。
parallel_tool_callsBooleanいいえ—
curl --request POST \
  --url https://api.basicrouter.ai/api/v1/responses \
  --header "Authorization: Bearer $BASICROUTER_API_KEY" \
  --header "Content-Type: application/json" \
  --data '{
    "model": "glm-5.2",
    "input": "Describe Hangzhou in one sentence.",
    "instructions": "Be concise.",
    "stream": false
  }'
{
  "id": "resp_xxx",
  "object": "response",
  "model": "glm-5.2",
  "status": "completed",
  "created_at": 1721380000,
  "output": [
    {
      "id": "msg_xxx",
      "type": "message",
      "role": "assistant",
      "content": [{"type": "output_text", "text": "Hangzhou is ..."}],
      "status": "completed"
    }
  ],
  "usage": {"input_tokens": 12, "output_tokens": 18, "total_tokens": 30}
}

レスポンスフィールド(非ストリーミング):

フィールドタイプ説明
idStringレスポンスID。
objectString固定値 response。
modelStringモデル名。
statusString例: completed。
created_atLong作成タイムスタンプ(秒)。
outputArray出力項目。メッセージ項目: {id, type:"message", role, content:[{type:"output_text", text}], status}。ツール呼び出し項目: {type:"function_call", id, name, call_id, arguments, status}。
usageObject{input_tokens, output_tokens, total_tokens}。Claudeモデルの場合、 input_tokens には cache_read が含まれ、 output_tokens には cache_write が含まれます。

ストリーミングはResponses APIのイベントに従います:

イベント説明
response.createdレスポンスストリームの開始。
response.output_text.deltaテキスト出力の増分更新。
response.completedレスポンスストリームの終了。

Create Anthropic MessagePOSThttps://api.basicrouter.ai/api/v1/messages

Anthropic Messages互換エンドポイント。x-api-key と anthropic-version: 2023-06-01 ヘッダーを受け付けます。コンテンツブロックは text、image、tool_use、tool_result、 thinking、redacted_thinking をサポートします。

フィールドタイプ必須JSONフィールド説明
modelStringはいmodelモデル名。
messagesMessage[]はいmessages会話メッセージ。
systemString|Arrayいいえsystemシステムプロンプト、文字列または [{type,text}]。
maxTokensIntegerはいmax_tokens最大出力トークン数。
streamBooleanいいえstreamストリーミング。
temperatureDoubleいいえtemperature—
topPDoubleいいえtop_p—
topKIntegerいいえtop_k—
toolsTool[]いいえtoolsツール定義(input_schema)。
toolChoiceObjectいいえtool_choice—
metadataMapいいえmetadata—
thinkingObjectいいえthinking拡張思考設定。
stopSequencesObjectいいえstop_sequences—
anthropicBetaObjectいいえanthropic_betaベータ機能ヘッダー。
フィールドタイプ説明
roleStringメッセージロール、例:user / assistant。
contentString|ContentBlock[]プレーンテキストまたはコンテンツブロックの配列。
フィールドタイプ説明
typeStringtext、image、tool_use、 tool_result、thinking、 redacted_thinkingのいずれか。
textStringtypeがtextの場合に存在します。
sourceObjecttypeがimageの場合に存在します。

例:

{ "type": "image", "source": { "type": "base64", "media_type": "...", "data": "..." } }
{ "type": "image", "source": { "type": "url", "url": "..." } }
フィールドタイプ説明
nameString関数名。
descriptionString関数の説明。
input_schemaObject入力のJSONスキーマ。
cache_controlObjectオプションのキャッシュ制御。
curl --request POST \
  --url https://api.basicrouter.ai/api/v1/messages \
  --header "Authorization: Bearer $BASICROUTER_API_KEY" \
  --header "anthropic-version: 2023-06-01" \
  --header "Content-Type: application/json" \
  --data '{
    "model": "claude-sonnet-4.6",
    "max_tokens": 1024,
    "messages": [{"role": "user", "content": "Describe Hangzhou in one sentence."}]
  }'
{
  "id": "msg_xxx",
  "type": "message",
  "role": "assistant",
  "model": "claude-sonnet-4.6",
  "content": [{"type": "text", "text": "Hangzhou is ..."}],
  "stop_reason": "end_turn",
  "usage": {"input_tokens": 12, "output_tokens": 18}
}

レスポンスフィールド(非ストリーミング):

フィールドタイプ説明
idStringメッセージID。
typeString固定値 message。
roleString固定値 assistant。
modelStringモデル名。
contentContentBlock[]レスポンスコンテンツブロック(例:{type:"text", text}、 {type:"tool_use", ...})。
stop_reasonString例:end_turn、tool_use、max_tokens。
usageObject{input_tokens, output_tokens}。
イベント説明
message_startメッセージストリームの開始。
content_block_start新しいコンテンツブロックの開始。
content_block_deltaコンテンツブロックの増分更新。
content_block_stopコンテンツブロックの終了。
message_deltaメッセージの増分更新。
message_stopメッセージストリームの終了。

List ModelsGEThttps://api.basicrouter.ai/api/v1/models

オンラインの有効なすべてのAPIモデルを返します。

curl --request GET \
  --url https://api.basicrouter.ai/api/v1/models \
  --header "Authorization: Bearer $BASICROUTER_API_KEY"
{
  "object": "list",
  "data": [
    {
      "id": "glm-5.2",
      "object": "model",
      "display_name": "glm-5.2",
      "created": 1721380000,
      "owned_by": "Zai",
      "input_modalities": ["text", "image"],
      "output_modalities": ["text"],
      "context_length": 128000,
      "description": "..."
    }
  ]
}

各モデルエントリ(data[])のフィールド:

フィールドタイプ説明
idStringモデルID。
objectString固定値 model。
display_nameString表示名。
createdLong作成タイムスタンプ(秒)。
owned_byString所有者 / ベンダー。
input_modalitiesString[]例: ["text","image"]。
output_modalitiesString[]例: ["text"]。
context_lengthInteger最大コンテキスト長。
descriptionStringモデルの説明。

Retrieve ModelGEThttps://api.basicrouter.ai/api/v1/models/{model}

リストエントリと同じ形式の単一モデルを返します。モデルが存在しない場合はHTTP 404を返します。

curl --request GET \
  --url https://api.basicrouter.ai/api/v1/models/gpt-5.5 \
  --header "Authorization: Bearer $BASICROUTER_API_KEY"

成功レスポンス: /v1/models リストエントリと同じフィールドを持つ単一モデルオブジェクト。

モデルが存在しない場合、HTTP 404を返します:

{"error": {"message": "The model 'xxx' does not exist", "type": "invalid_request_error", "code": "invalid_model_error"}}

List Image ModelsGEThttps://api.basicrouter.ai/api/v1/image-models

画像モデルがサポートする解像度、比率、最大数を /v1/image-generations の呼び出し前に照会します。認証は不要です。

フィールドタイプ説明
idStringモデルID。
objectString固定値 image_model。
displayNameString表示名。
descriptionStringモデルの説明。
iconStringアイコンURL。
createdLong作成タイムスタンプ(秒)。
maxCountIntegerリクエストあたりの最大画像数。
fileMaxInteger最大参照画像数。0の場合、画像から画像の生成はサポートされません。
resolutionsString[]サポートされる解像度、例: ["720p","1080p"]。
ratiosString[]サポートされるアスペクト比、例: ["1:1","3:2"]。
curl --request GET \
  --url https://api.basicrouter.ai/api/v1/image-models \
  --header "Authorization: Bearer $BASICROUTER_API_KEY"
{
  "object": "list",
  "data": [
    {
      "id": "gpt-image-2",
      "object": "image_model",
      "displayName": "GPT Image 1",
      "description": "...",
      "icon": "...",
      "created": 1721380000,
      "maxCount": 4,
      "fileMax": 10,
      "resolutions": ["720p", "1080p"],
      "ratios": ["1:1", "3:2"]
    }
  ]
}

List Video ModelsGEThttps://api.basicrouter.ai/api/v1/video-models

動画モデルがサポートする videoType 値、長さの範囲、解像度、比率を /v1/video-generations の呼び出し前に照会します。認証は不要です。

フィールドタイプ説明
idStringモデルID。
objectString固定値 video_model。
displayNameString表示名。
descriptionStringモデルの説明。
iconStringアイコンURL。
createdLong作成タイムスタンプ(秒)。
allowedVideoTypesVideoTypeOption[]サポートされる videoType リスト。
videoDurationMinIntegerクリップあたりの最小秒数。
videoDurationMaxIntegerクリップあたりの最大秒数。
videoDurationSuggestInteger[]推奨される長さのステップ、例: [5,8,10]。
resolutionsString[]サポートされる解像度。
ratiosString[]サポートされるアスペクト比。
resolutionOptionsResolutionOption[]構造化された解像度+比率+サイズの組み合わせ。
fileMaxInteger最大参照アセット数。

VideoTypeOption のフィールド:

フィールドタイプ説明
codeInteger/v1/video-generations に渡す videoType 値。
nameStringローカライズされたタイプ名(テキストから動画 / 画像から動画 / ...)。
curl --request GET \
  --url https://api.basicrouter.ai/api/v1/video-models \
  --header "Authorization: Bearer $BASICROUTER_API_KEY"
{
  "object": "list",
  "data": [
    {
      "id": "sora-2",
      "object": "video_model",
      "displayName": "Sora 2",
      "description": "...",
      "icon": "...",
      "created": 1721380000,
      "allowedVideoTypes": [
        {"code": 1, "name": "text-to-video"},
        {"code": 2, "name": "image-to-video"},
        {"code": 3, "name": "image-to-video (first/last frame)"}
      ],
      "videoDurationMin": 5,
      "videoDurationMax": 10,
      "videoDurationSuggest": [5, 8, 10],
      "resolutions": ["1080p", "720p"],
      "ratios": ["16:9", "9:16"],
      "fileMax": 5
    }
  ]
}

価格ティア項目説明

/v1/models、/v1/models/{model}、/v1/image-models、/v1/video-models の 4 つのモデル照会エンドポイントのレスポンスは、現在の呼び出し元(API Key ユーザー)の有効な課金単価を返します。実際の課金と完全に一致し、かつそのモデルの全価格ティアを返します。

フィールド名の違い:/v1/models / /v1/models/{model} は OpenAI 流のスネークケース(price_tiers);/v1/image-models / /v1/video-models は camelCase(priceTiers)。構造は同じです。

price_tiers / priceTiers は配列で、各要素は 1 つの価格ティアです:

項目型説明
outputPricedecimal現在の呼び出し元の有効な出力単価
cachePricedecimalキャッシュ価格(汎用モデル、旧課金式用)
cacheReadPricedecimalキャッシュ読み取り単価(Bedrock Claude 専用)
cacheWritePricedecimalキャッシュ書き込み単価(Bedrock Claude 専用)
ratiodecimal課金倍率。FIXED モードは 1;RATIO モードはユーザー/グループ倍率
modestring価格設定モード:RATIO / FIXED
planIdstring適用された価格プラン ID、null 可

3 種類のモデル種別で同一の構造を共有し、記述項目の埋め方のみ異なります。該当しない項目は null です:

モデル種別UNIT有効な説明項目
テキストtokenregion / bandMin / bandMax
画像imageresolution / clarity
動画videoresolution / clarity

価格の意味:返される inputPrice / outputPrice / cacheReadPrice / cacheWritePrice などは、価格チェーン(chain)→ guidance → 基礎価格を順に解決した後の、現在の API Key ユーザーに対する最終課金単価であり、実際の課金と一致します。呼び出し元が見る単価は、自身が属する価格チェーン(reseller / distributor / 企業 / ユーザー単位設定)によって異なります。

実際の課金額 = 使用量 ÷ quantity × 対応単価 × ratio。動画が秒単位課金の場合、実際の課金 = duration × outputPrice × ratio。

境界と例外処理(読み取り専用エンドポイントは価格設定の問題で 500 を返しません)

シナリオ動作
単一ティアの解決失敗(価格ポリシーがアクセスを拒否、設定欠落)当該ティアをスキップし、warn ログを記録して残りのティア解決を続行
モデルの全ティアが解決失敗空配列 []、モデルは正常に返される
価格設定がないモデル空配列 []
価格解析で未捕捉例外全体を try-catch、空配列を返し、エンドポイントは 200

レスポンス例(/v1/models、テキストモデル):

{
  "object": "list",
  "data": [
    {
      "id": "gpt-4o",
      "object": "model",
      "display_name": "gpt-4o",
      "context_length": 128000,
      "price_tiers": [
        {
          "region": "GLOBAL",
          "bandMin": null,
          "bandMax": null,
          "resolution": null,
          "clarity": null,
          "unit": "token",
          "quantity": 1000,
          "description": "1000 トークンあたり",
          "inputPrice": 0.0025,
          "outputPrice": 0.01,
          "cachePrice": 0.00125,
          "cacheReadPrice": 0,
          "cacheWritePrice": 0,
          "ratio": 1,
          "mode": "RATIO",
          "planId": null
        }
      ]
    }
  ]
}

レスポンス例(/v1/image-models、画像モデル、priceTiers 構造は同じ、unit は image):

{
  "object": "list",
  "data": [
    {
      "id": "dall-e-3",
      "object": "image_model",
      "displayName": "dall-e-3",
      "resolutions": ["1024x1024", "1792x1024", "1024x1792"],
      "priceTiers": [
        {
          "region": null,
          "bandMin": null,
          "bandMax": null,
          "resolution": "1024x1024",
          "clarity": "standard",
          "unit": "image",
          "quantity": 1,
          "description": "1 枚あたり",
          "inputPrice": 0,
          "outputPrice": 0.04,
          "cachePrice": 0,
          "cacheReadPrice": 0,
          "cacheWritePrice": 0,
          "ratio": 1,
          "mode": "RATIO",
          "planId": null
        }
      ]
    }
  ]
}

Create Image GenerationPOSThttps://api.basicrouter.ai/api/v1/image-generations

非同期で画像生成タスクを送信します。taskId を即座に返します。結果は GET /v1/image-generations/{taskId} でポーリングするか、callbackUrl Webhook経由で取得します。

model、サポートされる resolution / ratio 値、 count の上限、参照画像のアップロード上限(fileMax)は、 最初に GET /v1/image-models から取得する必要があります。そのモデルの仕様で提示された値のみが受け付けられます。

フィールドタイプ必須説明
textStringはいプロンプト。
modelStringはいモデル名。
imageUrlsString[]いいえ参照画像URL(image-to-image)。
countIntegerいいえ画像数(≥0)。
resolutionStringいいえ解像度(/v1/image-modelsを参照)。
ratioStringいいえアスペクト比。
callbackUrlStringいいえタスクレベルのWebhook URL。
curl --request POST \
  --url https://api.basicrouter.ai/api/v1/image-generations \
  --header "Authorization: Bearer $BASICROUTER_API_KEY" \
  --header "Content-Type: application/json" \
  --data '{
    "model": "seedream-4.5",
    "text": "A cat drinking water by the river",
    "count": 1,
    "resolution": "2k",
    "ratio": "1:1",
    "imageUrls": []
  }'
{
  "code": 200,
  "message": "image task is commit",
  "data": {"taskId": "img_xxx"}
}

エラーレスポンス:

// Insufficient credit
{ "code": 500, "message": "Insufficient credit" }

// Model not found
{ "code": 404, "message": "Model not found: xxx" }

Retrieve Image GenerationGEThttps://api.basicrouter.ai/api/v1/image-generations/{taskId}

画像生成タスクをポーリングします。status は pending / success / failed です。images は画像URLのJSON文字列化された配列です。text はモデルが添付したテキスト説明(例: Geminiマルチモーダル出力)を運びます。それ以外の場合は null です。

curl --request GET \
  --url https://api.basicrouter.ai/api/v1/image-generations/img_xxx \
  --header "Authorization: Bearer $BASICROUTER_API_KEY"
{
  "code": 200,
  "message": "success",
  "data": {
    "taskId": "img_xxx",
    "status": "success",
    "errorMessage": null,
    "images": "[\"https://.../1.png\"]",
    "text": null
  }
}

レスポンス data フィールド:

フィールドタイプ説明
taskIdStringタスクID。
statusStringpending / success / failed。
errorMessageString失敗理由。成功時は null。
imagesString画像URLのJSON文字列化された配列、例: "[\"https://.../1.png\"]"。
textStringモデルが添付したテキスト説明(例: Geminiマルチモーダル出力)。それ以外の場合は null。

タスクが見つかりません:

{ "code": 500, "message": "task not found" }

送信時に callbackUrl が指定された場合、サーバーは同じ data 構造で最終的な success / failed 結果をWebhook経由でプッシュします。

完全な例(送信 + ポーリング)

import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.time.Duration;

public class ImageGenerationExample {
  private static final String BASE = "https://api.basicrouter.ai/api/v1";
  private static final String API_KEY = System.getenv("BASICROUTER_API_KEY");

  public static void main(String[] args) throws Exception {
    HttpClient http = HttpClient.newBuilder()
        .connectTimeout(Duration.ofSeconds(10)).build();

    // 1. Submit the task.
    String body = "{"
        + "\"model\":\"seedream-4.5\","
        + "\"text\":\"A cat drinking water by the river\","
        + "\"count\":1,"
        + "\"resolution\":\"2k\","
        + "\"ratio\":\"1:1\","
        + "\"imageUrls\":[]"
        + "}";
    HttpResponse<String> submit = http.send(
        HttpRequest.newBuilder(URI.create(BASE + "/image-generations"))
            .header("Authorization", "Bearer " + API_KEY)
            .header("Content-Type", "application/json")
            .POST(HttpRequest.BodyPublishers.ofString(body)).build(),
        HttpResponse.BodyHandlers.ofString());

    String taskId = extract(submit.body(), "taskId");
    System.out.println("taskId = " + taskId);

    // 2. Poll until terminal status.
    String status = "pending";
    while ("pending".equals(status)) {
      Thread.sleep(15_000L);
      HttpResponse<String> poll = http.send(
          HttpRequest.newBuilder(URI.create(BASE + "/image-generations/" + taskId))
              .header("Authorization", "Bearer " + API_KEY).GET().build(),
          HttpResponse.BodyHandlers.ofString());
      status = extract(poll.body(), "status");
      System.out.println("status = " + status);
    }

    if (!"success".equals(status)) {
      throw new RuntimeException("image generation failed: " + status);
    }
    // images is a JSON-stringified array of URLs.
    String images = extract(pollResult(http, taskId), "images");
    System.out.println("images = " + images);
  }

  // Minimal JSON field extractor — use Jackson/Gson in production.
  private static String extract(String json, String field) {
    int i = json.indexOf("\"" + field + "\":");
    if (i < 0) return null;
    i += field.length() + 3;
    if (json.charAt(i) == '\"') {
      int end = json.indexOf('\"', i + 1);
      return json.substring(i + 1, end);
    }
    int end = i;
    while (end < json.length() && "0123456789.".indexOf(json.charAt(end)) >= 0) end++;
    return json.substring(i, end);
  }

  private static String pollResult(HttpClient http, String taskId) throws Exception {
    return http.send(HttpRequest.newBuilder(URI.create(BASE + "/image-generations/" + taskId))
        .header("Authorization", "Bearer " + API_KEY).GET().build(),
        HttpResponse.BodyHandlers.ofString()).body();
  }
}
import os
import time
import requests

BASE = "https://api.basicrouter.ai/api/v1"
HEADERS = {"Authorization": f"Bearer {os.environ['BASICROUTER_API_KEY']}"}

# 1. Submit the task.
resp = requests.post(
    f"{BASE}/image-generations",
    headers={**HEADERS, "Content-Type": "application/json"},
    json={
        "model": "seedream-4.5",
        "text": "A cat drinking water by the river",
        "count": 1,
        "resolution": "2k",
        "ratio": "1:1",
        "imageUrls": [],
    },
)
resp.raise_for_status()
task_id = resp.json()["data"]["taskId"]
print(f"taskId = {task_id}")

# 2. Poll until terminal status.
while True:
    time.sleep(15)
    poll = requests.get(f"{BASE}/image-generations/{task_id}", headers=HEADERS)
    poll.raise_for_status()
    data = poll.json()["data"]
    status = data["status"]
    print(f"status = {status}")
    if status != "pending":
        break

if status != "success":
    raise RuntimeError(f"image generation failed: {data.get('errorMessage')}")

# images is a JSON-stringified array of URLs.
import json
images = json.loads(data["images"])
print(f"images = {images}")

Create Video GenerationPOSThttps://api.basicrouter.ai/api/v1/video-generations

非同期で動画生成タスクを送信します。taskId を即座に返します。結果は GET /v1/video-generations/{taskId} でポーリングするか、callbackUrl Webhook経由で取得します。

model、許可された videoType 値、長さの範囲 (videoDurationMin/Max)、サポートされる resolution / ratio、参照アセットのアップロード上限(fileMax)は、 最初に GET /v1/video-models から取得する必要があります。そのモデルの allowedVideoTypes にリストされた videoType コードのみが受け付けられます。

フィールドタイプ必須説明
textStringはいプロンプト。
modelStringはいモデル名。
videoTypeIntegerはい1 テキストから動画 / 2 画像から動画(先頭フレーム) / 3 画像から動画(先頭+末尾 フレーム) / 4 画像から動画(参照) / 5 すべて参照。
imageUrlsString[]いいえ画像アセットURL。
videoUrlsVideoUrl[]|String[]いいえ動画アセットURL。
audioUrlsString[]いいえオーディオアセットURL。
resolutionStringいいえ解像度。
ratioStringいいえアスペクト比。
durationLongいいえ秒(>0)。
callbackUrlStringいいえタスクレベルのWebhook URL。

各 videoType の例:

1. テキストから動画(videoType=1)

テキストプロンプトのみから動画を生成します。参照アセットは不要です。

curl --request POST \
  --url https://api.basicrouter.ai/api/v1/video-generations \
  --header "Authorization: Bearer $BASICROUTER_API_KEY" \
  --header "Content-Type: application/json" \
  --data '{
    "videoType": 1,
    "text": "A cat jumping on a bed",
    "resolution": "480p",
    "ratio": "16:9",
    "duration": 4,
    "model": "seedance-2.0"
  }'

2. 画像から動画 - 先頭フレーム(videoType=2)

imageUrls に単一の開始フレームを指定します。モデルはそのフレームから動画を生成します。

curl --request POST \
  --url https://api.basicrouter.ai/api/v1/video-generations \
  --header "Authorization: Bearer $BASICROUTER_API_KEY" \
  --header "Content-Type: application/json" \
  --data '{
    "videoType": 2,
    "text": "Happily shaking head",
    "resolution": "480p",
    "ratio": "16:9",
    "duration": 4,
    "model": "seedance-2.0",
    "imageUrls": ["https://basicrouter-flie.oss-accelerate.aliyuncs.com/test/first-frame.png"]
  }'

3. 画像から動画 - 先頭および末尾フレーム(videoType=3)

imageUrls に先頭フレームと末尾フレームの両方を指定します(順序: [first, last])。モデルは2つのフレーム間の遷移動画を生成します。

curl --request POST \
  --url https://api.basicrouter.ai/api/v1/video-generations \
  --header "Authorization: Bearer $BASICROUTER_API_KEY" \
  --header "Content-Type: application/json" \
  --data '{
    "videoType": 3,
    "text": "Put on the hat",
    "resolution": "480p",
    "ratio": "16:9",
    "duration": 4,
    "model": "seedance-2.0",
    "imageUrls": [
      "https://basicrouter-flie.oss-accelerate.aliyuncs.com/test/first-frame.png",
      "https://basicrouter-flie.oss-accelerate.aliyuncs.com/test/last-frame.png"
    ]
  }'

4. 画像から動画 - 参照(videoType=4)

imageUrls に1つ以上の参照画像を指定します。モデルはそれらのスタイル/コンテンツを参照(強制された先頭/末尾フレームとしてではなく)として使用し、動画を生成します。

curl --request POST \
  --url https://api.basicrouter.ai/api/v1/video-generations \
  --header "Authorization: Bearer $BASICROUTER_API_KEY" \
  --header "Content-Type: application/json" \
  --data '{
    "videoType": 4,
    "text": "Two cats playing together",
    "resolution": "480p",
    "ratio": "16:9",
    "duration": 4,
    "model": "kling-v3-omni-video",
    "imageUrls": [
      "https://basicrouter-flie.oss-accelerate.aliyuncs.com/test/ref-1.png",
      "https://basicrouter-flie.oss-accelerate.aliyuncs.com/test/ref-2.png"
    ]
  }'

5. すべて参照(videoType=5)

画像 / 動画 / 音声の混在参照です。プロンプト内の位置でアセットを参照します: imageUrls の1番目のエントリは @图片 1、videoUrls の1番目は @视频 1、audioUrls の1番目は @音频 1 です。videoUrls はプレーンなURL文字列も受け付けます。

curl --request POST \
  --url https://api.basicrouter.ai/api/v1/video-generations \
  --header "Authorization: Bearer $BASICROUTER_API_KEY" \
  --header "Content-Type: application/json" \
  --data '{
    "videoType": 5,
    "text": "Use the first-person framing of @视频 1 and @音频 1 as background music. First-person tea ad; start frame is @图片 1 ... end frame is @图片 2.",
    "model": "seedance-2.0",
    "imageUrls": [
      "https://ark-project.tos-cn-beijing.volces.com/doc_image/r2v_tea_pic1.jpg",
      "https://ark-project.tos-cn-beijing.volces.com/doc_image/r2v_tea_pic2.jpg"
    ],
    "videoUrls": ["https://ark-project.tos-cn-beijing.volces.com/doc_video/r2v_tea_video1.mp4"],
    "audioUrls": ["https://ark-project.tos-cn-beijing.volces.com/doc_audio/r2v_tea_audio1.mp3"],
    "resolution": "1080p",
    "ratio": "16:9",
    "duration": 11
  }'

送信レスポンス(5つのタイプすべて):

{
  "code": 200,
  "message": "success",
  "data": {"taskId": "vid_xxx"}
}

Retrieve Video GenerationGEThttps://api.basicrouter.ai/api/v1/video-generations/{taskId}

動画生成タスクをポーリングします。status は pending / success / failed です。videoUrl は生成された動画の URLで、lastFrameUrl は末尾フレームのURLです(画像から動画のシナリオ)。

curl --request GET \
  --url https://api.basicrouter.ai/api/v1/video-generations/vid_xxx \
  --header "Authorization: Bearer $BASICROUTER_API_KEY"
{
  "code": 200,
  "message": "success",
  "data": {
    "status": "success",
    "videoUrl": "https://.../out.mp4",
    "lastFrameUrl": null,
    "message": null
  }
}

レスポンス data フィールド:

フィールドタイプ説明
statusStringpending / success / failed。
videoUrlString生成された動画のURL。
lastFrameUrlString末尾フレームのURL(画像から動画のシナリオ)。それ以外の場合は null。
messageString失敗理由。成功時は null。

送信時に callbackUrl が指定された場合、サーバーは同じ data 構造で最終結果をWebhook経由でプッシュします。

完全な例(送信 + ポーリング)

import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.time.Duration;

public class VideoGenerationExample {
  private static final String BASE = "https://api.basicrouter.ai/api/v1";
  private static final String API_KEY = System.getenv("BASICROUTER_API_KEY");

  public static void main(String[] args) throws Exception {
    HttpClient http = HttpClient.newBuilder()
        .connectTimeout(Duration.ofSeconds(10)).build();

    // 1. Submit the task (videoType=1: text-to-video).
    String body = "{"
        + "\"videoType\":1,"
        + "\"text\":\"A cat jumping on a bed\","
        + "\"resolution\":\"480p\","
        + "\"ratio\":\"16:9\","
        + "\"duration\":4,"
        + "\"model\":\"seedance-2.0\""
        + "}";
    HttpResponse<String> submit = http.send(
        HttpRequest.newBuilder(URI.create(BASE + "/video-generations"))
            .header("Authorization", "Bearer " + API_KEY)
            .header("Content-Type", "application/json")
            .POST(HttpRequest.BodyPublishers.ofString(body)).build(),
        HttpResponse.BodyHandlers.ofString());

    String taskId = extract(submit.body(), "taskId");
    System.out.println("taskId = " + taskId);

    // 2. Poll until terminal status. Video tasks take longer — poll every 20s.
    String status = "pending";
    String lastBody = null;
    while ("pending".equals(status)) {
      Thread.sleep(20_000L);
      HttpResponse<String> poll = http.send(
          HttpRequest.newBuilder(URI.create(BASE + "/video-generations/" + taskId))
              .header("Authorization", "Bearer " + API_KEY).GET().build(),
          HttpResponse.BodyHandlers.ofString());
      lastBody = poll.body();
      status = extract(lastBody, "status");
      System.out.println("status = " + status);
    }

    if (!"success".equals(status)) {
      throw new RuntimeException("video generation failed: " + status);
    }
    String videoUrl = extract(lastBody, "videoUrl");
    System.out.println("videoUrl = " + videoUrl);
  }

  // Minimal JSON field extractor — use Jackson/Gson in production.
  private static String extract(String json, String field) {
    int i = json.indexOf("\"" + field + "\":");
    if (i < 0) return null;
    i += field.length() + 3;
    if (json.charAt(i) == '\"') {
      int end = json.indexOf('\"', i + 1);
      return json.substring(i + 1, end);
    }
    int end = i;
    while (end < json.length() && "0123456789.".indexOf(json.charAt(end)) >= 0) end++;
    return json.substring(i, end);
  }
}
import os
import time
import requests

BASE = "https://api.basicrouter.ai/api/v1"
HEADERS = {"Authorization": f"Bearer {os.environ['BASICROUTER_API_KEY']}"}

# 1. Submit the task (videoType=1: text-to-video).
resp = requests.post(
    f"{BASE}/video-generations",
    headers={**HEADERS, "Content-Type": "application/json"},
    json={
        "videoType": 1,
        "text": "A cat jumping on a bed",
        "resolution": "480p",
        "ratio": "16:9",
        "duration": 4,
        "model": "seedance-2.0",
    },
)
resp.raise_for_status()
task_id = resp.json()["data"]["taskId"]
print(f"taskId = {task_id}")

# 2. Poll until terminal status. Video tasks take longer — poll every 20s.
while True:
    time.sleep(20)
    poll = requests.get(f"{BASE}/video-generations/{task_id}", headers=HEADERS)
    poll.raise_for_status()
    data = poll.json()["data"]
    status = data["status"]
    print(f"status = {status}")
    if status != "pending":
        break

if status != "success":
    raise RuntimeError(f"video generation failed: {data.get('message')}")

print(f"videoUrl = {data['videoUrl']}")
if data.get("lastFrameUrl"):
    print(f"lastFrameUrl = {data['lastFrameUrl']}")

Retrieve Billing BalanceGEThttps://api.basicrouter.ai/api/v1/billing/balance

アカウント残高を月額プラン、リソースパック、従量課金クレジットの3つのウォレットに分割して返します。

curl --request GET \
  --url https://api.basicrouter.ai/api/v1/billing/balance \
  --header "Authorization: Bearer $BASICROUTER_API_KEY"
{
  "totalCredit": 128.50,
  "totalResourceCredit": 30.00,
  "wallets": {
    "monthlyPlan": {"id": "pkg_xxx", "credit": 50.00, "name": "Monthly plan"},
    "resourcePacks": [
      {"id": "rp_xxx", "credit": 30.00, "name": "Video resource pack"}
    ],
    "payAsYouGo": 48.50
  }
}

レスポンスフィールド:

フィールドタイプ説明
totalCreditBigDecimal合計残高。
totalResourceCreditBigDecimalリソースパック残高の合計。
wallets.monthlyPlanWalletDetail月額プラン(ない場合は null)。
wallets.resourcePacksWalletDetail[]リソースパックのリスト。
wallets.payAsYouGoBigDecimal従量課金残高。

WalletDetailVO fields::

フィールドタイプ説明
idStringウォレットID。
creditBigDecimal残高クレジット。
nameStringウォレット名。

List UsageGEThttps://api.basicrouter.ai/api/v1/usage

モデル呼び出しの課金詳細のページネーションリスト。価格 (priceSnapshotId) ごとにスナップショット化され、注文作成時刻の降順で並べ替えられます。通常の課金レコード (reason = model usage) のみが返されます。

クエリパラメータ:

パラメータタイプ必須デフォルト説明
pageIntegerいいえ1ページ番号(1始まり)。
sizeIntegerいいえ20ページサイズ(priceSnapshotId でページネーション)。
startTimeLocalDateTimeいいえ—開始時刻。フォーマット yyyy-MM-ddTHH:mm:ss。スナップショットの orderCreatedAt でフィルタリングします。
endTimeLocalDateTimeいいえ—終了時刻。フォーマット yyyy-MM-ddTHH:mm:ss。
curl --request GET \
  --url "https://api.basicrouter.ai/api/v1/usage?page=1&size=20&startTime=2026-07-01T00:00:00&endTime=2026-07-31T23:59:59" \
  --header "Authorization: Bearer $BASICROUTER_API_KEY"

レスポンスラッパー:

{
  "code": 0,
  "message": "success",
  "data": { ... }
}
フィールドタイプ説明
recordsUsageDetailVO[]現在のページのレコード。
totalLong合計件数。
currentLong現在のページ。
sizeLongページサイズ。
pagesLong総ページ数。

UsageDetailVO フィールド:

フィールドタイプ説明
priceSnapshotIdString価格スナップショットID。
taskIdStringタスクID。
creditBigDecimal課金額。
modelStringモデル名。
modelTypeStringtext / image / video。
inputTokensLong入力トークン。image/videoの場合は null。
outputTokensLong出力トークン。
totalTokensLong合計トークン。
cacheReadTokensLongキャッシュ読み取りトークン。
cacheWriteTokensLongキャッシュ書き込みトークン。
imageCountInteger画像数。画像モデルに設定されます。
imageResolutionString画像の解像度。例: 720P。
imageRatioString画像のアスペクト比。例: 1:1。
videoResolutionString動画の解像度。例: 1080p。
videoRatioString動画のアスペクト比。例: 16:9。
videoDurationSecLong動画の長さ(秒)。
orderCreatedAtLocalDateTime注文作成時刻(スナップショットの orderCreatedAt)。
creditDetailsCreditDetailItem[]このスナップショット下の注文詳細(credit_order_t から取得)。

CreditDetailItem フィールド:

フィールドタイプ説明
creditBigDecimalこの注文での課金額。
deductionSourceString控除元(Balance / Monthly Package / Resource Package)。
packageNameStringパッケージ名。パッケージがない場合は null。

Null値の規約: 各 modelType に関連するフィールドのみが設定され、それ以外は null になります。text はトークンフィールドを設定します; image は imageCount/imageResolution/imageRatio を設定します; video は videoResolution/videoRatio/videoDurationSec を設定します。

レスポンス例:

{
  "code": 200,
  "message": "success",
  "data": {
    "records": [
      {
        "priceSnapshotId": "snap_9f3c1a2b",
        "taskId": "task_5e8a1c33",
        "credit": 0.0342,
        "model": "glm-5.2",
        "modelType": "text",
        "inputTokens": 1280,
        "outputTokens": 642,
        "totalTokens": 1922,
        "cacheReadTokens": 0,
        "cacheWriteTokens": 0,
        "imageCount": null,
        "imageResolution": null,
        "imageRatio": null,
        "videoResolution": null,
        "videoRatio": null,
        "videoDurationSec": null,
        "orderCreatedAt": "2026-07-18T14:23:11",
        "creditDetails": [
          {
            "credit": 0.0342,
            "deductionSource": "balance",
            "packageName": ""
          }
        ]
      },
      {
        "priceSnapshotId": "snap_a12f77c0",
        "taskId": "task_c71e44a2",
        "credit": 1.8000,
        "model": "seedance-2.0",
        "modelType": "video",
        "inputTokens": null,
        "outputTokens": null,
        "totalTokens": null,
        "cacheReadTokens": null,
        "cacheWriteTokens": null,
        "imageCount": null,
        "imageResolution": null,
        "imageRatio": null,
        "videoResolution": "1080p",
        "videoRatio": "16:9",
        "videoDurationSec": 8,
        "orderCreatedAt": "2026-07-17T22:41:09",
        "creditDetails": [
          {
            "credit": 1.5000,
            "deductionSource": "Monthly Package",
            "packageName": "基础月度套餐"
          },
          {
            "credit": 0.3000,
            "deductionSource": "Resource Package",
            "packageName": "byteplus视频资源包"
          }
        ]
      }
    ],
    "total": 128,
    "current": 1,
    "size": 20,
    "pages": 7
  }
}

List Billing TransactionsGEThttps://api.basicrouter.ai/api/v1/billing/transactions

現在のユーザーの支払い済み(status=2)チャージ取引のページネーションリスト。created_at の降順で並べ替えられます。

パラメータタイプ必須デフォルト説明
pageIntegerいいえ1ページ番号。
sizeIntegerいいえ20ページサイズ。
startTimeStringいいえ—開始時刻。yyyy-MM-dd HH:mm:ss。境界を含みます。
endTimeStringいいえ—終了時刻。yyyy-MM-dd HH:mm:ss。境界を含みます。
curl --request GET \
  --url "https://api.basicrouter.ai/api/v1/billing/transactions?page=1&size=20&startTime=2026-07-01%2000:00:00&endTime=2026-07-31%2023:59:59" \
  --header "Authorization: Bearer $BASICROUTER_API_KEY"

レスポンスラッパー:

{
  "code": 0,
  "message": "success",
  "data": { ... }
}
フィールドタイプ説明
recordsTransactionVO[]現在のページの取引。
totalLong合計件数。
currentLong現在のページ。
sizeLongページサイズ。
pagesLong総ページ数。

TransactionVO フィールド:

フィールドタイプ説明
orderNoString注文番号。
thirdPartyOrderNoStringサードパーティの注文番号。
amountBigDecimal注文金額。
actualAmountBigDecimal実際の支払い額。
discountBigDecimal割引額。
paymentMethodString支払い方法(wechat / alipay / ustd / stripe / wallyt 等)。

TransactionVO フィールド:

フィールドタイプ説明
serviceFeeAmountBigDecimalサービス手数料。
paymentChannelString決済プラットフォーム。
sourceString注文元(recharge / package_purchase 等)。
packageNameStringパッケージ名(パッケージ購入時に設定。通常のチャージの場合は null)。
createdAtLocalDateTime作成日時。
{
  "code": 200,
  "message": "success",
  "data": {
    "records": [
      {
        "orderNo": "R20260718abc123",
        "thirdPartyOrderNo": "wx_pay_xxx",
        "amount": 50.00,
        "actualAmount": 48.50,
        "discount": 1.50,
        "paymentMethod": "wechat",
        "serviceFeeAmount": 0.00,
        "paymentChannel": "wechat",
        "source": "recharge",
        "packageName": null,
        "createdAt": "2026-07-18T14:23:11"
      }
    ],
    "total": 28,
    "current": 1,
    "size": 20,
    "pages": 2
  }
}