Tài liệu API
Quy ước chung
URL cơ sở
Tất cả các điểm cuối được phục vụ dưới tiền tố /v1.
Xác thực
Các lệnh gọi đến điểm cuối /v1/* sử dụng xác thực Khóa API (không phải JWT). Khóa API được truyền qua header sau:
| Header | Định dạng | Mô tả |
|---|---|---|
Authorization | Bearer <api_key> | Kiểu OpenAI. Điểm cuối tương thích Anthropic cũng chấp nhận x-api-key với anthropic-version: 2023-06-01. |
Các khóa bị thiếu hoặc không hợp lệ trả về 401.
Kiểm tra trước số dư
Tất cả các điểm cuối gọi mô hình chạy kiểm tra trước số dư trước khi thực thi:
- Số dư không đủ trả về
Insufficient credit, được ánh xạ tới:- Giao thức OpenAI: HTTP
400,code = insufficient_quota - Giao thức Anthropic: HTTP
402,type = billing_error
- Giao thức OpenAI: HTTP
- Một số điểm cuối cũng ước tính chi phí tối thiểu theo mô hình cho lần kiểm tra thứ hai.
Create Chat CompletionPOSThttps://api.basicrouter.ai/api/v1/chat/completions
Điểm cuối tương thích OpenAI Chat Completions. Hỗ trợ phát trực tuyến và không phát trực tuyến, gọi công cụ, chế độ JSON và đầu vào đa phương thức.
| Trường | Kiểu | Bắt buộc | Mô tả |
|---|---|---|---|
model | String | Có | Tên mô hình. |
messages | Message[] | Có | Tin nhắn hội thoại. |
stream | Boolean | Không | Chế độ phát trực tuyến, mặc định false. |
temperature | Double | Không | Nhiệt độ lấy mẫu. |
max_tokens | Integer | Không | Token đầu ra tối đa. |
top_p | Double | Không | Lấy mẫu hạt nhân. |
presence_penalty | Double | Không | — |
frequency_penalty | Double | Không | — |
tools | Tool[] | Không | Định nghĩa công cụ. |
tool_choice | String|Object | Không | auto / none / required / hàm cụ thể. |
response_format | Object | Không | {type, json_schema:{name,schema,strict}}; text/json_object/json_schema. |
parallel_tool_calls | Boolean | Không | — |
metadata | Map | Không | Siêu dữ liệu truyền qua. |
Các trường Message:
| Trường | Kiểu | Mô tả |
|---|---|---|
role | String | system / user / assistant / tool. |
content | String|Array | Văn bản thuần hoặc mảng khối nội dung đa phương thức ([{type:"text",text},{type:"image_url",image_url:{url}}]). |
tool_call_id | String | Liên kết đến tool_calls khi role=tool. |
tool_calls | ToolCall[] | Có mặt khi role=assistant thực hiện gọi công cụ. |
| Trường | Kiểu | Mô tả |
|---|---|---|
type | String | Cố định function. |
function | Object | Định nghĩa hàm. |
function.name | String | Tên hàm. |
function.description | String | Mô tả hàm. |
function.parameters | Object | JSON Schema cho đầu vào. |
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}
}Các trường phản hồi (không phát trực tuyến):
| Trường | Kiểu | Mô tả |
|---|---|---|
id | String | ID hoàn thành. |
object | String | Cố định chat.completion. |
created | Long | Dấu thời tạo (giây). |
model | String | Tên mô hình. |
choices | Choice[] | {index, message:{role, content, tool_calls?}, finish_reason}. |
usage | Object | {prompt_tokens, completion_tokens, total_tokens}. |
| Trường | Kiểu | Mô tả |
|---|---|---|
id | String | ID gọi công cụ. |
type | String | Cố định function. |
function | Object | Chi tiết gọi hàm. |
function.name | String | Tên hàm. |
function.arguments | Object | Đối số hàm. |
Ví dụ phản hồi phát trực tuyến:
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
Điểm cuối tương thích OpenAI Responses. Sử dụng input thay vì messages, instructions thay vì tin nhắn hệ thống và khối text thay vì response_format.
| Trường | Kiểu | Bắt buộc | Mô tả |
|---|---|---|---|
model | String | Có | Tên mô hình. |
input | String|Array | Có | Chuỗi thuần (tin nhắn người dùng) hoặc mảng đối tượng tin nhắn. |
instructions | String | Không | Prompt hệ thống. |
stream | Boolean | Không | Mặc định false. |
max_output_tokens | Integer | Không | Token đầu ra tối đa. |
temperature | Double | Không | Mặc định 1. |
top_p | Double | Không | — |
tools | Tool[] | Không | Cấp cao nhất {type, name, description, parameters}. |
tool_choice | String|Object | Không | auto/none/required/{type,name}. |
text | Object | Không | {format:{type, name, schema, strict}}; text/json_object/json_schema. |
metadata | Map | Không | — |
previous_response_id | String | Không | ID phản hồi trước đó cho hội thoại nhiều lượt. |
parallel_tool_calls | Boolean | Không | — |
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}
}Các trường phản hồi (không streaming):
| Trường | Kiểu | Mô tả |
|---|---|---|
id | String | ID phản hồi. |
object | String | Cố định response. |
model | String | Tên mô hình. |
status | String | vd. completed. |
created_at | Long | Dấu thời gian tạo (giây). |
output | Array | Các mục đầu ra. Mục tin nhắn: {id, type:"message", role, content:[{type:"output_text", text}], status}. Mục gọi công cụ: {type:"function_call", id, name, call_id, arguments, status}. |
usage | Object | {input_tokens, output_tokens, total_tokens}. Đối với mô hình Claude, input_tokens bao gồm cache_read và output_tokens bao gồm cache_write. |
Streaming tuân theo các sự kiện của API Responses:
| Sự kiện | Mô tả |
|---|---|
response.created | Bắt đầu luồng phản hồi. |
response.output_text.delta | Bản cập nhật văn bản đầu ra tăng dần. |
response.completed | Kết thúc luồng phản hồi. |
Create Anthropic MessagePOSThttps://api.basicrouter.ai/api/v1/messages
Điểm cuối tương thích Anthropic Messages. Chấp nhận header x-api-key và anthropic-version: 2023-06-01. Các khối nội dung hỗ trợ text, image, tool_use, tool_result, thinking và redacted_thinking.
| Trường | Kiểu | Bắt buộc | Trường JSON | Mô tả |
|---|---|---|---|---|
model | String | Có | model | Tên mô hình. |
messages | Message[] | Có | messages | Tin nhắn hội thoại. |
system | String|Array | Không | system | Prompt hệ thống, chuỗi hoặc [{type,text}]. |
maxTokens | Integer | Có | max_tokens | Token đầu ra tối đa. |
stream | Boolean | Không | stream | Phát trực tuyến. |
temperature | Double | Không | temperature | — |
topP | Double | Không | top_p | — |
topK | Integer | Không | top_k | — |
tools | Tool[] | Không | tools | Định nghĩa công cụ (input_schema). |
toolChoice | Object | Không | tool_choice | — |
metadata | Map | Không | metadata | — |
thinking | Object | Không | thinking | Cấu hình suy nghĩ mở rộng. |
stopSequences | Object | Không | stop_sequences | — |
anthropicBeta | Object | Không | anthropic_beta | Header tính năng beta. |
| Trường | Kiểu | Mô tả |
|---|---|---|
role | String | Vai trò tin nhắn, ví dụ user / assistant. |
content | String|ContentBlock[] | Văn bản thuần hoặc một mảng các khối nội dung. |
| Trường | Kiểu | Mô tả |
|---|---|---|
type | String | Một trong text, image, tool_use, tool_result, thinking, redacted_thinking. |
text | String | Có mặt khi type là text. |
source | Object | Có mặt khi type là image. |
Ví dụ:
{ "type": "image", "source": { "type": "base64", "media_type": "...", "data": "..." } }
{ "type": "image", "source": { "type": "url", "url": "..." } }| Trường | Kiểu | Mô tả |
|---|---|---|
name | String | Tên hàm. |
description | String | Mô tả hàm. |
input_schema | Object | JSON Schema cho đầu vào. |
cache_control | Object | Điều khiển bộ nhớ đệm tùy chọn. |
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}
}Các trường phản hồi (không phát trực tuyến):
| Trường | Kiểu | Mô tả |
|---|---|---|
id | String | ID tin nhắn. |
type | String | Cố định message. |
role | String | Cố định assistant. |
model | String | Tên mô hình. |
content | ContentBlock[] | Các khối nội dung phản hồi (ví dụ {type:"text", text}, {type:"tool_use", ...}). |
stop_reason | String | ví dụ end_turn, tool_use, max_tokens. |
usage | Object | {input_tokens, output_tokens}. |
| Sự kiện | Mô tả |
|---|---|
message_start | Bắt đầu luồng tin nhắn. |
content_block_start | Bắt đầu một khối nội dung mới. |
content_block_delta | Cập nhật tăng dần cho một khối nội dung. |
content_block_stop | Kết thúc một khối nội dung. |
message_delta | Cập nhật tăng dần cho tin nhắn. |
message_stop | Kết thúc luồng tin nhắn. |
List ModelsGEThttps://api.basicrouter.ai/api/v1/models
Trả về tất cả các mô hình API trực tuyến, đã được kích hoạt.
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": "..."
}
]
}Các trường của mỗi mục mô hình (data[]):
| Trường | Kiểu | Mô tả |
|---|---|---|
id | String | ID mô hình. |
object | String | Cố định model. |
display_name | String | Tên hiển thị. |
created | Long | Dấu thời gian tạo (giây). |
owned_by | String | Chủ sở hữu / nhà cung cấp. |
input_modalities | String[] | vd. ["text","image"]. |
output_modalities | String[] | vd. ["text"]. |
context_length | Integer | Độ dài ngữ cảnh tối đa. |
description | String | Mô tả mô hình. |
Retrieve ModelGEThttps://api.basicrouter.ai/api/v1/models/{model}
Trả về một mô hình đơn với cùng cấu trúc như một mục danh sách. Trả về HTTP 404 khi mô hình không tồn tại.
curl --request GET \
--url https://api.basicrouter.ai/api/v1/models/gpt-5.5 \
--header "Authorization: Bearer $BASICROUTER_API_KEY"Phản hồi thành công: một đối tượng mô hình đơn với cùng các trường như một mục danh sách /v1/models.
Khi mô hình không tồn tại, trả về 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
Truy vấn các độ phân giải, tỷ lệ và số lượng tối đa được hỗ trợ bởi một mô hình hình ảnh trước khi gọi /v1/image-generations. Không cần xác thực.
| Trường | Kiểu | Mô tả |
|---|---|---|
id | String | ID mô hình. |
object | String | Cố định image_model. |
displayName | String | Tên hiển thị. |
description | String | Mô tả mô hình. |
icon | String | URL biểu tượng. |
created | Long | Dấu thời gian tạo (giây). |
maxCount | Integer | Số hình ảnh tối đa mỗi yêu cầu. |
fileMax | Integer | Số hình ảnh tham chiếu tối đa. Khi bằng 0, không hỗ trợ tạo ảnh từ ảnh. |
resolutions | String[] | Các độ phân giải được hỗ trợ, vd. ["720p","1080p"]. |
ratios | String[] | Các tỷ lệ khung hình được hỗ trợ, vd. ["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
Truy vấn các giá trị videoType được hỗ trợ, phạm vi thời lượng, độ phân giải và tỷ lệ cho một mô hình video trước khi gọi /v1/video-generations. Không cần xác thực.
| Trường | Kiểu | Mô tả |
|---|---|---|
id | String | ID mô hình. |
object | String | Cố định video_model. |
displayName | String | Tên hiển thị. |
description | String | Mô tả mô hình. |
icon | String | URL biểu tượng. |
created | Long | Dấu thời gian tạo (giây). |
allowedVideoTypes | VideoTypeOption[] | Danh sách videoType được hỗ trợ. |
videoDurationMin | Integer | Số giây tối thiểu mỗi clip. |
videoDurationMax | Integer | Số giây tối đa mỗi clip. |
videoDurationSuggest | Integer[] | Các bước thời lượng đề xuất, vd. [5,8,10]. |
resolutions | String[] | Các độ phân giải được hỗ trợ. |
ratios | String[] | Các tỷ lệ khung hình được hỗ trợ. |
resolutionOptions | ResolutionOption[] | Các tổ hợp cấu trúc độ phân giải+tỷ lệ+kích thước. |
fileMax | Integer | Số tài sản tham chiếu tối đa. |
Các trường VideoTypeOption:
| Trường | Kiểu | Mô tả |
|---|---|---|
code | Integer | Giá trị videoType để truyền vào /v1/video-generations. |
name | String | Tên loại đã địa phương hóa (văn bản thành video / hình ảnh thành video / ...). |
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
}
]
}Mô tả trường mức giá
4 endpoint truy vấn mô hình /v1/models, /v1/models/{model}, /v1/image-models và /v1/video-models trả về giá thanh toán hiệu lực cho người gọi (người dùng API Key), hoàn toàn khớp với chi phí thực tế, và trả về toàn bộ các mức giá của mô hình.
Khác biệt tên trường: /v1/models / /v1/models/{model} dùng kiểu OpenAI snake_case (price_tiers); /v1/image-models / /v1/video-models dùng camelCase (priceTiers). Cấu trúc hoàn toàn giống nhau.
price_tiers / priceTiers là mảng, mỗi phần tử là một mức giá:
| Trường | Kiểu | Mô tả |
|---|---|---|
outputPrice | decimal | Đơn giá đầu ra hiệu lực của người gọi hiện tại |
cachePrice | decimal | Giá cache (mô hình chung, dùng cho công thức thanh toán cũ) |
cacheReadPrice | decimal | Đơn giá đọc cache (dành riêng cho Bedrock Claude) |
cacheWritePrice | decimal | Đơn giá ghi cache (dành riêng cho Bedrock Claude) |
ratio | decimal | Hệ số thanh toán. Chế độ FIXED là 1; chế độ RATIO là hệ số người dùng/nhóm |
mode | string | Chế độ định giá: RATIO / FIXED |
planId | string | ID kế hoạch định giá khớp, có thể null |
Ba loại mô hình dùng chung một cấu trúc, chỉ khác ở cách điền trường mô tả, các trường không áp dụng là null:
| Loại mô hình | UNIT | Trường mô tả hiệu lực |
|---|---|---|
| Văn bản | token | region / bandMin / bandMax |
| Hình ảnh | image | resolution / clarity |
| Video | video | resolution / clarity |
Ý nghĩa giá: Các giá trị inputPrice / outputPrice / cacheReadPrice / cacheWritePrice trả về là đơn giá thanh toán cuối cùng cho người dùng API Key hiện tại sau khi giải quyết qua chuỗi giá (chain) → guidance → giá cơ sở, khớp với chi phí thực tế. Đơn giá mà người gọi thấy khác nhau tùy theo chuỗi giá (reseller / distributor / doanh nghiệp / cấu hình cấp người dùng) mà họ thuộc về.
Số tiền thực tế = lượng sử dụng ÷ quantity × đơn giá tương ứng × ratio. Video tính theo giây: số tiền thực tế = duration × outputPrice × ratio.
Xử lý giới hạn & ngoại lệ (các endpoint chỉ đọc không trả về 500 do vấn đề cấu hình giá)
| Tình huống | Hành vi |
|---|---|
| Một mức giải quyết thất bại (chính sách giá từ chối truy cập, thiếu cấu hình) | Bỏ qua mức đó, ghi log warn, tiếp tục giải quyết các mức còn lại |
| Tất cả các mức của một mô hình đều giải quyết thất bại | Mảng rỗng [], mô hình vẫn trả về bình thường |
| Mô hình không có cấu hình giá nào | Mảng rỗng [] |
| Phân tích giá ném ra ngoại lệ không bắt được | Toàn bộ try-catch, trả về mảng rỗng, endpoint vẫn 200 |
Ví dụ phản hồi (/v1/models, mô hình văn bản):
{
"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": "mỗi 1000 token",
"inputPrice": 0.0025,
"outputPrice": 0.01,
"cachePrice": 0.00125,
"cacheReadPrice": 0,
"cacheWritePrice": 0,
"ratio": 1,
"mode": "RATIO",
"planId": null
}
]
}
]
}Ví dụ phản hồi (/v1/image-models, mô hình hình ảnh, cấu trúc priceTiers như trên, unit là 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": "mỗi hình",
"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
Gửi không đồng bộ một tác vụ tạo hình ảnh. Trả về taskId ngay lập tức; truy xuất kết quả bằng cách polling GET /v1/image-generations/{taskId} hoặc qua webhook callbackUrl.
Các giá trị model, resolution / ratio được hỗ trợ, giới hạn trên count, và giới hạn tải lên hình ảnh tham chiếu (fileMax) phải được lấy từ GET /v1/image-models trước. Chỉ các giá trị được quảng cáo bởi spec của mô hình đó mới được chấp nhận.
| Trường | Kiểu | Bắt buộc | Mô tả |
|---|---|---|---|
text | String | Có | Prompt. |
model | String | Có | Tên mô hình. |
imageUrls | String[] | Không | URL hình ảnh tham chiếu (hình ảnh thành hình ảnh). |
count | Integer | Không | Số hình ảnh (≥0). |
resolution | String | Không | Độ phân giải (xem /v1/image-models). |
ratio | String | Không | Tỷ lệ khung hình. |
callbackUrl | String | Không | URL webhook cấp tác vụ. |
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"}
}Phản hồi lỗi:
// 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}
Poll một tác vụ tạo hình ảnh. status là pending / success / failed. images là một mảng URL hình ảnh được chuỗi hóa JSON; text mang theo bất kỳ mô tả văn bản nào được mô hình đính kèm (vd. đầu ra đa phương thức Gemini), null nếu không có.
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
}
}Các trường phản hồi data:
| Trường | Kiểu | Mô tả |
|---|---|---|
taskId | String | ID tác vụ. |
status | String | pending / success / failed. |
errorMessage | String | Lý do thất bại, null nếu thành công. |
images | String | Mảng URL hình ảnh được chuỗi hóa JSON, vd. "[\"https://.../1.png\"]". |
text | String | Mô tả văn bản do mô hình đính kèm (vd. đầu ra đa phương thức Gemini); null nếu không có. |
Không tìm thấy tác vụ:
{ "code": 500, "message": "task not found" }Nếu callbackUrl được cung cấp khi gửi, máy chủ sẽ đẩy kết quả cuối cùng success / failed qua webhook với cùng cấu trúc data.
Ví dụ hoàn chỉnh (gửi + poll)
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
Gửi không đồng bộ một tác vụ tạo video. Trả về taskId ngay lập tức; truy xuất kết quả bằng cách polling GET /v1/video-generations/{taskId} hoặc qua webhook callbackUrl.
Các giá trị model, videoType được phép, phạm vi thời lượng (videoDurationMin/Max), resolution / ratio được hỗ trợ, và giới hạn tải lên tài sản tham chiếu (fileMax) phải được lấy từ GET /v1/video-models trước. Chỉ các mã videoType được liệt kê trong allowedVideoTypes của mô hình đó mới được chấp nhận.
| Trường | Kiểu | Bắt buộc | Mô tả |
|---|---|---|---|
text | String | Có | Prompt. |
model | String | Có | Tên mô hình. |
videoType | Integer | Có | 1 văn bản thành video / 2 hình ảnh thành video (khung đầu) / 3 hình ảnh thành video (khung đầu+cuối) / 4 hình ảnh thành video (tham chiếu) / 5 tất cả tham chiếu. |
imageUrls | String[] | Không | URL tài sản hình ảnh. |
videoUrls | VideoUrl[]|String[] | Không | URL tài sản video. |
audioUrls | String[] | Không | URL tài sản âm thanh. |
resolution | String | Không | Độ phân giải. |
ratio | String | Không | Tỷ lệ khung hình. |
duration | Long | Không | Giây (>0). |
callbackUrl | String | Không | URL webhook cấp tác vụ. |
Ví dụ cho từng videoType:
1. Văn bản thành video (videoType=1)
Tạo video chỉ từ prompt văn bản; không cần tài sản tham chiếu.
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. Hình ảnh thành video - khung đầu (videoType=2)
Cung cấp một khung hình bắt đầu đơn trong imageUrls; mô hình tạo video bắt đầu từ khung hình đó.
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. Hình ảnh thành video - khung đầu và khung cuối (videoType=3)
Cung cấp cả khung đầu và khung cuối trong imageUrls (thứ tự: [đầu, cuối]); mô hình tạo video chuyển tiếp giữa hai khung hình.
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. Hình ảnh thành video - tham chiếu (videoType=4)
Cung cấp một hoặc nhiều hình ảnh tham chiếu trong imageUrls; mô hình sử dụng phong cách/nội dung của chúng làm tham chiếu (không phải là khung đầu/cuối bắt buộc) để tạo video.
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. Tất cả tham chiếu (videoType=5)
Tham chiếu hình ảnh / video / âm thanh hỗn hợp. Tham chiếu tài sản theo vị trí trong prompt: mục thứ 1 trong imageUrls là @图片 1, mục thứ 1 trong videoUrls là @视频 1, mục thứ 1 trong audioUrls là @音频 1. videoUrls cũng chấp nhận chuỗi URL đơn giản.
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
}'Phản hồi gửi (tất cả năm loại):
{
"code": 200,
"message": "success",
"data": {"taskId": "vid_xxx"}
}Retrieve Video GenerationGEThttps://api.basicrouter.ai/api/v1/video-generations/{taskId}
Poll một tác vụ tạo video. status là pending / success / failed; videoUrl là URL video đã tạo và lastFrameUrl là URL khung cuối (trong trường hợp hình ảnh thành video).
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
}
}Các trường phản hồi data:
| Trường | Kiểu | Mô tả |
|---|---|---|
status | String | pending / success / failed. |
videoUrl | String | URL video đã tạo. |
lastFrameUrl | String | URL khung cuối (trong trường hợp hình ảnh thành video); null nếu không có. |
message | String | Lý do thất bại, null nếu thành công. |
Nếu callbackUrl được cung cấp khi gửi, máy chủ sẽ đẩy kết quả cuối cùng qua webhook với cùng cấu trúc data.
Ví dụ hoàn chỉnh (gửi + poll)
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
Trả về số dư tài khoản chia thành ba ví: gói tháng, gói tài nguyên và tín dụng trả theo mức dùng.
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
}
}Các trường phản hồi:
| Trường | Kiểu | Mô tả |
|---|---|---|
totalCredit | BigDecimal | Tổng số dư. |
totalResourceCredit | BigDecimal | Tổng số dư các gói tài nguyên. |
wallets.monthlyPlan | WalletDetail | Gói tháng (null nếu không có). |
wallets.resourcePacks | WalletDetail[] | Danh sách gói tài nguyên. |
wallets.payAsYouGo | BigDecimal | Số dư trả theo mức dùng. |
Các trường WalletDetailVO:
| Trường | Kiểu | Mô tả |
|---|---|---|
id | String | ID ví. |
credit | BigDecimal | Số dư tín dụng. |
name | String | Tên ví. |
List UsageGEThttps://api.basicrouter.ai/api/v1/usage
Chi tiết thanh toán cuộc gọi mô hình phân trang, được chụp nhanh theo giá (priceSnapshotId), sắp xếp theo thời gian tạo đơn hàng giảm dần. Chỉ các bản ghi tính phí bình thường (reason = model usage) được trả về.
Tham số truy vấn:
| Tham số | Kiểu | Bắt buộc | Mặc định | Mô tả |
|---|---|---|---|---|
page | Integer | Không | 1 | Số trang, bắt đầu từ 1. |
size | Integer | Không | 20 | Kích thước trang (phân trang theo priceSnapshotId). |
startTime | LocalDateTime | Không | — | Thời gian bắt đầu, định dạng yyyy-MM-ddTHH:mm:ss, lọc theo snapshot orderCreatedAt. |
endTime | LocalDateTime | Không | — | Thời gian kết thúc, định dạng 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"Bọc phản hồi:
{
"code": 0,
"message": "success",
"data": { ... }
}| Trường | Kiểu | Mô tả |
|---|---|---|
records | UsageDetailVO[] | Bản ghi trang hiện tại. |
total | Long | Tổng số. |
current | Long | Trang hiện tại. |
size | Long | Kích thước trang. |
pages | Long | Tổng số trang. |
Các trường UsageDetailVO:
| Trường | Kiểu | Mô tả |
|---|---|---|
priceSnapshotId | String | ID snapshot giá. |
taskId | String | ID tác vụ. |
credit | BigDecimal | Số tiền tính phí. |
model | String | Tên mô hình. |
modelType | String | text / image / video. |
inputTokens | Long | Token đầu vào; null với image/video. |
outputTokens | Long | Token đầu ra. |
totalTokens | Long | Tổng token. |
cacheReadTokens | Long | Token đọc cache. |
cacheWriteTokens | Long | Token ghi cache. |
imageCount | Integer | Số lượng hình ảnh; đặt cho mô hình hình ảnh. |
imageResolution | String | Độ phân giải hình ảnh, vd. 720P. |
imageRatio | String | Tỷ lệ khung hình hình ảnh, vd. 1:1. |
videoResolution | String | Độ phân giải video, vd. 1080p. |
videoRatio | String | Tỷ lệ khung hình video, vd. 16:9. |
videoDurationSec | Long | Thời lượng video tính bằng giây. |
orderCreatedAt | LocalDateTime | Thời gian tạo đơn hàng (snapshot orderCreatedAt). |
creditDetails | CreditDetailItem[] | Chi tiết đơn hàng trong snapshot này (từ credit_order_t). |
Các trường CreditDetailItem:
| Trường | Kiểu | Mô tả |
|---|---|---|
credit | BigDecimal | Số tiền tính phí bởi đơn hàng này. |
deductionSource | String | Nguồn khấu trừ (Balance / Monthly Package / Resource Package). |
packageName | String | Tên gói; null nếu không có gói. |
Quy ước giá trị null: chỉ các trường liên quan đến từng modelType mới được điền; các trường còn lại là null. text điền các trường token; image điền imageCount/imageResolution/imageRatio; video điền videoResolution/videoRatio/videoDurationSec.
Ví dụ phản hồi:
{
"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
Danh sách phân trang các giao dịch nạp tiền đã thanh toán (status=2) của người dùng hiện tại, sắp xếp theo created_at giảm dần.
| Tham số | Kiểu | Bắt buộc | Mặc định | Mô tả |
|---|---|---|---|---|
page | Integer | Không | 1 | Số trang. |
size | Integer | Không | 20 | Kích thước trang. |
startTime | String | Không | — | Thời gian bắt đầu, yyyy-MM-dd HH:mm:ss, bao gồm. |
endTime | String | Không | — | Thời gian kết thúc, yyyy-MM-dd HH:mm:ss, bao gồm. |
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"Bọc phản hồi:
{
"code": 0,
"message": "success",
"data": { ... }
}| Trường | Kiểu | Mô tả |
|---|---|---|
records | TransactionVO[] | Giao dịch trang hiện tại. |
total | Long | Tổng số. |
current | Long | Trang hiện tại. |
size | Long | Kích thước trang. |
pages | Long | Tổng số trang. |
Các trường TransactionVO:
| Trường | Kiểu | Mô tả |
|---|---|---|
orderNo | String | Mã đơn hàng. |
thirdPartyOrderNo | String | Mã đơn hàng bên thứ ba. |
amount | BigDecimal | Số tiền đơn hàng. |
actualAmount | BigDecimal | Số tiền thực tế đã thanh toán. |
discount | BigDecimal | Số tiền chiết khấu. |
paymentMethod | String | Phương thức thanh toán (wechat / alipay / ustd / stripe / wallyt v.v.). |
Các trường TransactionVO (tiếp theo):
| Trường | Kiểu | Mô tả |
|---|---|---|
serviceFeeAmount | BigDecimal | Số tiền phí dịch vụ. |
paymentChannel | String | Nền tảng thanh toán. |
source | String | Nguồn đơn hàng (recharge / package_purchase v.v.). |
packageName | String | Tên gói (đặt cho mua gói; null cho nạp tiền thông thường). |
createdAt | LocalDateTime | Thời gian tạo. |
{
"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
}
}