BazaarLinkBazaarLink
登入
文件API 参考SDK 参考Agent 应用AI Skills

API 参考

BazaarLink API 概览

BazaarLink 在不同模型和供应商之间提供统一且兼容 OpenAI 的请求与响应格式。你只需集成一次,即可切换模型,无需重写应用程序。

OpenAPI 规范

完整的 BazaarLink API 使用 OpenAPI 规范记录,并提供 YAML 与 JSON 格式:

你可以将这些规范导入 Swagger UI、Postman 或其他兼容 OpenAPI 的代码生成器,用于探索 API 或生成客户端库。

请求

对话完成请求格式

对话完成的请求正文会发送至以下端点:

POST/api/v1/chat/completions

如需完整的支持字段列表,请参阅 参数

请求结构
// Definitions of subtypes are below
type Request = {
  // Required by BazaarLink Chat Completions
  model: string;                    // Use a provider-qualified catalog ID
  messages: Message[];             // Must contain at least one message

  // Generation
  stream?: boolean;
  temperature?: number;            // Range: [0, 2]
  max_tokens?: number;             // Positive integer
  max_completion_tokens?: number;  // Alias mapped to max_tokens upstream
  n?: number;
  seed?: number;
  stop?: string | string[];

  // Sampling
  top_p?: number;
  top_k?: number;
  frequency_penalty?: number;      // Range: [-2, 2]
  presence_penalty?: number;       // Range: [-2, 2]
  repetition_penalty?: number;     // Range: (0, 2]
  min_p?: number;                  // Range: [0, 1]
  top_a?: number;                  // Range: [0, 1]

  // Token probabilities
  logit_bias?: Record<number, number>;
  logprobs?: boolean;
  top_logprobs?: number;

  // Stable end-user identifier for abuse prevention
  user?: string;

  // Tool calling
  tools?: Tool[];
  tool_choice?: ToolChoice;
  parallel_tool_calls?: boolean;

  // Structured output
  response_format?: ResponseFormat;
  structured_outputs?: boolean;

  // Plugin configuration — forwarded to upstreams that support plugins.
  plugins?: Plugin[];

  // Multimodal and image-generation options
  modalities?: Array<"text" | "image">;
  image_config?: Record<string, unknown>;
  input_audio?: InputAudio;

  // Provider-specific reasoning controls
  reasoning_effort?: "low" | "medium" | "high";
  reasoning?: ReasoningConfig;
  thinking?: ThinkingConfig;
  enable_thinking?: boolean;

  // BazaarLink message transforms and fallback routing
  transforms?: Array<"middle-out">;
  models?: string[];             // Fallback list — this drives waterfall routing, not route
  route?: "fallback";            // Passthrough only; forwarded as-is, no local effect
  provider?: ProviderPreferences;
};

// Message types
type Message =
  | SystemMessage
  | UserMessage
  | AssistantMessage
  | ToolMessage;

type SystemMessage = {
  role: "system";
  content: string | ContentPart[];
  name?: string;
};

type UserMessage = {
  role: "user";
  content: string | ContentPart[];
  name?: string;
};

type AssistantMessage = {
  role: "assistant";
  content?: string | ContentPart[] | null;
  name?: string;
  tool_calls?: ToolCall[];
};

type ToolMessage = {
  role: "tool";
  content: string;
  tool_call_id: string;
  name?: string;
};

// Multimodal content parts
type ContentPart =
  | TextContentPart
  | ImageContentPart
  | FileContentPart
  | AudioContentPart
  | VideoContentPart;

type TextContentPart = {
  type: "text";
  text: string;
};

type ImageContentPart = {
  type: "image_url";
  image_url: {
    url: string;                    // Remote URL or base64 data URI
    detail?: string;
  };
};

type FileContentPart = {
  type: "file";
  file: {
    filename?: string;
    file_data: string;              // Base64 data URI
  };
};

type AudioContentPart = {
  type: "input_audio";
  input_audio: InputAudio;
};

type InputAudio = {
  data: string;                     // Raw base64 without a data URI prefix
  format: string;                   // For example "wav" or "mp3"
};

type VideoContentPart = {
  type: "video_url";
  video_url: {
    url: string;                    // Remote URL or base64 data URI
  };
};

// Tool calling subtypes
type FunctionDescription = {
  name: string;
  description?: string;
  parameters: object;               // JSON Schema object
};

type Tool = {
  type: "function";
  function: FunctionDescription;
};

type ToolChoice =
  | "none"
  | "auto"
  | "required"
  | {
      type: "function";
      function: {
        name: string;
      };
    };

type ToolCall = {
  id: string;
  type: "function";
  function: {
    name: string;
    arguments: string;
  };
};

// Structured output
type ResponseFormat =
  | {
      type: "json_object";
    }
  | {
      type: "json_schema";
      json_schema: {
        name: string;
        strict?: boolean;
        schema: object;
      };
    };

// Upstream plugin configuration
type Plugin = {
  id: string;
  enabled?: boolean;
  [key: string]: unknown;
};

// Reasoning controls vary by model family
type ReasoningConfig = {
  effort?: "low" | "medium" | "high";
  max_tokens?: number;
  exclude?: boolean;
};

type ThinkingConfig = {
  type?: "enabled" | "disabled";
  budget_tokens?: number;
};

// Provider routing preferences
type ProviderPreferences = {
  order?: string[];
  only?: string[];
  ignore?: string[];
  allow_fallbacks?: boolean;
  sort?:
    | "price"
    | "latency"
    | "throughput"
    | {
        by: string;
        partition?: string;
      };
  require_parameters?: boolean;
  data_collection?: "allow" | "deny";
  quantizations?: string[];
  max_price?: Record<string, number>;
};

结构化输出

强制模型返回符合 Schema 的有效 JSON。这对于建立需要程式化解析模型输出的可靠应用程式至关重要。

  • json_object基础 JSON 模式;模型会返回有效的 JSON。
  • json_schema严格 Schema 模式;模型输出必须符合提供的 JSON Schema。

外挂

BazaarLink 会将 plugins 数组转发至选定的上游路由。插件可用性取决于模型和供应商;使用 :online 模型变体时也会启用 web 插件。

JSON
{
  "model": "openai/gpt-4.1",
  "messages": [
    { "role": "user", "content": "What happened today?" }
  ],
  "plugins": [
    { "id": "web" }
  ]
}

选填标头

透过请求标头识别您的应用程式,让系统追踪使用量、显示在仪表板上,并在未来提供更细致的分析。

TypeScript
await fetch("https://bazaarlink.ai/api/v1/chat/completions", {
  method: "POST",
  headers: {
    "Authorization": "Bearer <BAZAARLINK_API_KEY>",
    "Content-Type": "application/json",
    "HTTP-Referer": "https://your-app.example",
    "X-Title": "Your App"
  },
  body: JSON.stringify({
    model: "openai/gpt-4.1",
    messages: [{ role: "user", content: "Hello!" }]
  })
});

助手预填

在消息数组最后加入一条未完成的 assistant 消息,向兼容的模型路由请求接续生成。

运作方式
BazaarLink 会保留并转发最后一条 assistant 消息。接续行为由所选的上游模型与供应商实现,因此并非每条路由都保证支持。
TypeScript
const response = await client.chat.completions.create({
  model: "anthropic/claude-sonnet-4.6",
  messages: [
    { role: "user", content: "What is the meaning of life?" },
    // Intentional partial response; compatible routes continue from here.
    { role: "assistant", content: "My best answer is" }
  ]
});

响应

BazaarLink 将不同模型和供应商的完成响应标准化为统一、兼容 OpenAI 的格式。

完成响应格式

choices 始终是数组。流式响应使用 delta,非流式响应使用 message;可用时还会返回用量与成本明细。

回应结构
type Response = {
  id: string;
  object: "chat.completion" | "chat.completion.chunk";
  created: number;
  model: string;
  choices: Array<NonStreamingChoice | StreamingChoice>;
  usage?: {
    prompt_tokens: number;
    completion_tokens: number;
    total_tokens: number;
    cost?: number;
    prompt_tokens_details?: {
      cached_tokens: number;
      cache_write_tokens?: number;
      audio_tokens?: number;
    };
    completion_tokens_details?: {
      reasoning_tokens?: number;
      image_tokens?: number;
    };
  };
};

type NonStreamingChoice = {
  index: number;
  finish_reason: string | null;
  native_finish_reason: string | null;
  message: {
    role: "assistant";
    content: string | null;
    tool_calls?: ToolCall[];
  };
};

type StreamingChoice = {
  index: number;
  finish_reason: string | null;
  native_finish_reason: string | null;
  delta: {
    role?: string;
    content?: string | null;
    tool_calls?: ToolCall[];
  };
};

结束原因

finish_reason 使用 stop、length、tool_calls、content_filter、error 等标准化值;native_finish_reason 保留供应商的原始值。

JSON
{
  "finish_reason": "stop",
  "native_finish_reason": "stop"
}

查询成本与统计数据

依 generation ID 查询单次完成请求的详细统计数据(ID 来自 chat/completions 响应的 id,或流式的 x-bz-gen-id header)。

TypeScript
const generation = await fetch(
  "https://bazaarlink.ai/api/v1/generation?id=<GENERATION_ID>",
  {
    headers: {
      Authorization: "Bearer <BAZAARLINK_API_KEY>"
    }
  }
).then((response) => response.json());

对话完成

主要端点。与 OpenAI Chat Completions API 相容。

POST/api/v1/chat/completions

请求内文

model必填
string
模型 ID,例如 "openai/gpt-4o" 或 "anthropic/claude-3.5-sonnet"
messages必填
Message[]
包含 role 和 content 的讯息物件阵列
stream
boolean
若为 true,返回 Server-Sent Events 串流。预设:false
temperature
number
取样温度 0–2。越高越随机。预设:1
max_tokens
integer
要生成的最大 token 数量
max_completion_tokens
integer
max_tokens 的别名(OpenAI o 系列相容)。两者皆支援,以提供的为准
top_p
number
核取样概率质量。预设:1
top_k
integer
限制候选 token 数量。0 表示停用(考虑全部)。预设:0
frequency_penalty
number
惩罚重复的 token。范围:[-2, 2]。预设:0
presence_penalty
number
基于存在情况惩罚 token。范围:[-2, 2]。预设:0
repetition_penalty
number
降低输入中 token 重复的机率。范围:(0, 2]。预设:1
min_p
number
相对最高机率 token 的最低入选机率。范围:[0, 1]。预设:0
top_a
number
基于最高机率 token 的动态 Top-P。范围:[0, 1]。预设:0
seed
integer
整数随机种子,用于确定性取样。部分模型不保证
n
integer
产生的完成数量。预设:1
user
string
终端使用者识别码,用于监控与滥用侦测。对计费无影响。仅限 OpenAI 系列模型 —— 见下方说明。
stop
string | string[]
停止序列 — 遇到时停止生成
logit_bias
object
将 token ID 映射到偏差値 [-100, 100],在取样前加到机率。仅限 OpenAI 系列模型 —— 见下方说明。
logprobs
boolean
回传每个输出 token 的对数机率。仅限 OpenAI 系列模型 —— 见下方说明。
top_logprobs
integer
每个位置回传概率最高的 N 个候选 token(需配合 logprobs: true)。范围:0–20。仅限 OpenAI 系列模型 —— 见下方说明。
tools
Tool[]
模型可以呼叫的工具(函式)列表
tool_choice
string | object
控制工具使用:"auto"、"none" 或指定工具
parallel_tool_calls
boolean
启用并行工具呼叫功能。预设:true。仅限 OpenAI 系列模型 —— 见下方说明。
response_format
object
强制结构化 JSON 输出。请参阅结构化输出章节
structured_outputs
boolean
在支持的 provider 上要求严格符合 JSON schema 的输出。原样转发
reasoning
object
Provider 专属的 reasoning/thinking 设置。原样转发
reasoning_effort
string
OpenAI o 系列风格的 reasoning 强度:"low"、"medium" 或 "high"。原样转发
transforms
string[]
要套用的讯息转换,例如 ["middle-out"]。省略则在 ≤8k context 模型自动套用
models
string[]
备用模型清单——BazaarLink 依序尝试,主模型失败时自动切换
route
string
进阶路由兼容字段——大多数用户不需要。要用 fallback 请用 "models"。
provider
object
进阶路由偏好——大多数用户不需要。
user、logprobs、top_logprobs、logit_bias、parallel_tool_calls 只会传到 OpenAI 系列模型
只要解析出来的模型不是 OpenAI 自家的,这五个参数就会从上游请求中被拿掉 —— 发送到 anthropic/claude-*、google/gemini-* 或其他非 OpenAI 目标时,会返回 200,参数被悄悄忽略,不会报错。如果你设置了其中任何一个却没看到效果,先检查目标模型是不是 OpenAI 的。

请求结构 (TypeScript)

// Definitions of subtypes are below
type Request = {
  // Required by BazaarLink Chat Completions
  model: string;                    // Use a provider-qualified catalog ID
  messages: Message[];             // Must contain at least one message

  // Generation
  stream?: boolean;
  temperature?: number;            // Range: [0, 2]
  max_tokens?: number;             // Positive integer
  max_completion_tokens?: number;  // Alias mapped to max_tokens upstream
  n?: number;
  seed?: number;
  stop?: string | string[];

  // Sampling
  top_p?: number;
  top_k?: number;
  frequency_penalty?: number;      // Range: [-2, 2]
  presence_penalty?: number;       // Range: [-2, 2]
  repetition_penalty?: number;     // Range: (0, 2]
  min_p?: number;                  // Range: [0, 1]
  top_a?: number;                  // Range: [0, 1]

  // Token probabilities
  logit_bias?: Record<number, number>;
  logprobs?: boolean;
  top_logprobs?: number;

  // Stable end-user identifier for abuse prevention
  user?: string;

  // Tool calling
  tools?: Tool[];
  tool_choice?: ToolChoice;
  parallel_tool_calls?: boolean;

  // Structured output
  response_format?: ResponseFormat;
  structured_outputs?: boolean;

  // Plugin configuration — forwarded to upstreams that support plugins.
  plugins?: Plugin[];

  // Multimodal and image-generation options
  modalities?: Array<"text" | "image">;
  image_config?: Record<string, unknown>;
  input_audio?: InputAudio;

  // Provider-specific reasoning controls
  reasoning_effort?: "low" | "medium" | "high";
  reasoning?: ReasoningConfig;
  thinking?: ThinkingConfig;
  enable_thinking?: boolean;

  // BazaarLink message transforms and fallback routing
  transforms?: Array<"middle-out">;
  models?: string[];             // Fallback list — this drives waterfall routing, not route
  route?: "fallback";            // Passthrough only; forwarded as-is, no local effect
  provider?: ProviderPreferences;
};

// Message types
type Message =
  | SystemMessage
  | UserMessage
  | AssistantMessage
  | ToolMessage;

type SystemMessage = {
  role: "system";
  content: string | ContentPart[];
  name?: string;
};

type UserMessage = {
  role: "user";
  content: string | ContentPart[];
  name?: string;
};

type AssistantMessage = {
  role: "assistant";
  content?: string | ContentPart[] | null;
  name?: string;
  tool_calls?: ToolCall[];
};

type ToolMessage = {
  role: "tool";
  content: string;
  tool_call_id: string;
  name?: string;
};

// Multimodal content parts
type ContentPart =
  | TextContentPart
  | ImageContentPart
  | FileContentPart
  | AudioContentPart
  | VideoContentPart;

type TextContentPart = {
  type: "text";
  text: string;
};

type ImageContentPart = {
  type: "image_url";
  image_url: {
    url: string;                    // Remote URL or base64 data URI
    detail?: string;
  };
};

type FileContentPart = {
  type: "file";
  file: {
    filename?: string;
    file_data: string;              // Base64 data URI
  };
};

type AudioContentPart = {
  type: "input_audio";
  input_audio: InputAudio;
};

type InputAudio = {
  data: string;                     // Raw base64 without a data URI prefix
  format: string;                   // For example "wav" or "mp3"
};

type VideoContentPart = {
  type: "video_url";
  video_url: {
    url: string;                    // Remote URL or base64 data URI
  };
};

// Tool calling subtypes
type FunctionDescription = {
  name: string;
  description?: string;
  parameters: object;               // JSON Schema object
};

type Tool = {
  type: "function";
  function: FunctionDescription;
};

type ToolChoice =
  | "none"
  | "auto"
  | "required"
  | {
      type: "function";
      function: {
        name: string;
      };
    };

type ToolCall = {
  id: string;
  type: "function";
  function: {
    name: string;
    arguments: string;
  };
};

// Structured output
type ResponseFormat =
  | {
      type: "json_object";
    }
  | {
      type: "json_schema";
      json_schema: {
        name: string;
        strict?: boolean;
        schema: object;
      };
    };

// Upstream plugin configuration
type Plugin = {
  id: string;
  enabled?: boolean;
  [key: string]: unknown;
};

// Reasoning controls vary by model family
type ReasoningConfig = {
  effort?: "low" | "medium" | "high";
  max_tokens?: number;
  exclude?: boolean;
};

type ThinkingConfig = {
  type?: "enabled" | "disabled";
  budget_tokens?: number;
};

// Provider routing preferences
type ProviderPreferences = {
  order?: string[];
  only?: string[];
  ignore?: string[];
  allow_fallbacks?: boolean;
  sort?:
    | "price"
    | "latency"
    | "throughput"
    | {
        by: string;
        partition?: string;
      };
  require_parameters?: boolean;
  data_collection?: "allow" | "deny";
  quantizations?: string[];
  max_price?: Record<string, number>;
};

范例请求

curl https://bazaarlink.ai/api/v1/chat/completions \
  -H "Authorization: Bearer $BAZAARLINK_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "openai/gpt-4.1",
    "messages": [
      {"role": "system", "content": "You are a helpful assistant."},
      {"role": "user", "content": "Explain quantum computing in one paragraph."}
    ],
    "temperature": 0.7,
    "max_tokens": 512
  }'

回应

{
  "id": "chatcmpl-abc123",
  "object": "chat.completion",
  "created": 1740000000,
  "model": "openai/gpt-4.1",
  "choices": [
    {
      "index": 0,
      "message": {
        "role": "assistant",
        "content": "Quantum computing leverages quantum mechanics..."
      },
      "finish_reason": "stop"
    }
  ],
  "usage": {
    "prompt_tokens": 28,
    "completion_tokens": 74,
    "total_tokens": 102,
    "cost": 0.0006480,
    "prompt_tokens_details": {
      "cached_tokens": 0
    },
    "completion_tokens_details": {
      "reasoning_tokens": 0
    }
  }
}

回应结构 (TypeScript)

BazaarLink 只正规化两个字段 —— model,以及移除 provider 字段 —— 其余上游响应原样转发。像 native_finish_reason、system_fingerprint、reasoning 这类字段只有在该上游供应商有填值时才会出现,不要预设每个模型都一定有。usage.cost 是例外 —— 永远是 BazaarLink 自己结算/计费的金额,不是上游转发过来的数值。

type Response = {
  id: string;
  object: "chat.completion" | "chat.completion.chunk";
  created: number;                 // Unix timestamp
  model: string;
  choices: (NonStreamingChoice | StreamingChoice)[];
  usage?: ResponseUsage;
  cost?: number;                   // Total cost in USD
};

type NonStreamingChoice = {
  index: number;
  finish_reason: "stop" | "length" | "tool_calls" | "content_filter" | null;
  native_finish_reason: string | null;  // Provider's original finish reason
  message: {
    role: "assistant";
    content: string | null;
    tool_calls?: ToolCall[];
  };
};

type StreamingChoice = {
  index: number;
  finish_reason: string | null;
  native_finish_reason: string | null;  // Provider's original finish reason
  delta: {
    role?: string;
    content?: string | null;
    tool_calls?: ToolCall[];
  };
};

type ResponseUsage = {
  prompt_tokens: number;
  completion_tokens: number;
  total_tokens: number;
  cost: number;                      // Total cost for this request in USD
  prompt_tokens_details?: {
    cached_tokens: number;           // Tokens served from prompt cache (reduced cost)
    cache_write_tokens?: number;     // Tokens written to cache in this request
    audio_tokens?: number;
  };
  completion_tokens_details?: {
    reasoning_tokens?: number;       // Thinking/reasoning tokens (e.g. o3, Qwen3, DeepSeek R1)
    image_tokens?: number;
  };
};

type ToolCall = {
  id: string;
  type: "function";
  function: { name: string; arguments: string };
};

图片生成

BazaarLink 提供两条图片生成路径:(A) /v1/chat/completions 并带 modalities: ["image"] — 原生路径,支持 SSE 流与混合 text+image 输出,推荐新接入使用。(B) /v1/images/generations — OpenAI DALL·E 兼容请求格式,响应为 SSE event stream(避免慢速模型撞 100s 上游超时)。两条路径的 SSE 事件协议一致,端点选择纯粹是请求形状偏好。 图片编辑(修改现有图片)走 POST /v1/images/edits —— 与 OpenAI images.edit 兼容,用 multipart/form-data 上传来源图。可编辑的模型 modality 是 text+image->image(例如 qwen/qwen-image-edit);纯生成模型是 text->image —— 各模型的 modality 可在 GET /v1/models 查。

Response format

/api/v1/images/generations 默认返回 OpenAI 兼容的同步 JSON(2026-07-25 起)——client.images.generate() 不需任何包装即可使用。传 stream: true 可改用 SSE 事件流,适合生成时间较长的模型获取进度。

A. /v1/chat/completions(原生,推荐)

POST/api/v1/chat/completions

The canonical streaming path. Recommended for any new integration.

curl -N https://bazaarlink.ai/api/v1/chat/completions \
  -H "Authorization: Bearer $BL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "openai/gpt-5.4-image-2",
    "messages": [{"role":"user","content":"a red cat on a sofa"}],
    "modalities": ["image","text"],
    "stream": true
  }'

图生图(image-to-image):在 content 数组带 image_url 部件即可,支持 data URI 或 https 图片网址(不接受 http://),最多 8 张、单张 data URI 约 10MB 内;带图的那条消息必须同时含 text 部件(编辑指令)。部分模型另支持 image_config(例如 {"strength": 0.7},0–1,值越低越贴近原图),原样透传给上游。

curl -N https://bazaarlink.ai/api/v1/chat/completions \
  -H "Authorization: Bearer $BL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "openai/gpt-5.4-image-2",
    "messages": [{"role":"user","content":[
      {"type":"image_url","image_url":{"url":"data:image/png;base64,..."}},
      {"type":"text","text":"change the background to a night city"}
    ]}],
    "modalities": ["image"],
    "stream": true
  }'

图片编辑(OpenAI 兼容)

POST/api/v1/images/edits

OpenAI SDK 的 client.images.edit() 可直接使用(multipart 上传、同步 JSON 响应,返回 data: [{ url }])。限制同图生图:最多 8 张、单张 10MB;mask 与 response_format=b64_json 暂不支持。

curl https://bazaarlink.ai/api/v1/images/edits \
  -H "Authorization: Bearer $BL_API_KEY" \
  -F model="openai/gpt-5.4-image-2" \
  -F image=@cat.png \
  -F prompt="change the background to a night city"

B. /v1/images/generations(DALL·E 兼容)

POST/api/v1/images/generations

OpenAI DALL-E request shape. Sync JSON ({ created, data: [{ url }] }) is the default and works with client.images.generate() out of the box; pass stream: true to get the SSE event stream documented below instead.

curl https://bazaarlink.ai/api/v1/images/generations \
  -H "Authorization: Bearer $BL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "openai/gpt-image-2",
    "prompt": "a red cat on a sofa",
    "size": "1024x1024"
  }'
model必填
string
模型 ID,例如 google/gemini-2.5-flash-image
prompt必填
string
文字提示
size
string
输出尺寸(自动映射)
n
integer
生成张数(默认 1)
# Streaming variant — progressive delivery for long generations
curl -N https://bazaarlink.ai/api/v1/images/generations \
  -H "Authorization: Bearer $BL_API_KEY" \
  -H "Accept: text/event-stream" \
  -H "Content-Type: application/json" \
  -d '{"model":"openai/gpt-5.4-image-2","prompt":"a red cat on a sofa","stream":true}'

SSE event protocol

Both endpoints emit the same event types:

event: heartbeat        # every 60 s, keeps Cloudflare happy
data: {}

event: image            # upstream URL, fastest path
data: {"index": 0, "url": "https://upstream/a.png"}

event: image-cached     # bazaarlink Redis-backed proxy URL (1 hr TTL)
data: {"index": 0, "url": "https://bazaarlink.ai/api/v1/images/proxy/<token>"}

event: usage            # final cost / token count
data: {"promptTokens": 12, "completionTokens": 7080, "cost": 0.226, "durationMs": 163400, "imageCount": 1}

event: done
data: {}

支持的图片模型

Model IDModalityi2i (edits)

视频生成

异步三步流程(submit → poll → content)。视频生成需要 30 秒到 5 分钟,无法套用 chat-completions 的同步请求/响应语义 — 因此 BazaarLink 把视频独立到 /api/v1/videos 路径,采用 job-id 模式:submit 拿到 vjob_* ID → poll 状态 → 完成后 fetch bytes。将 video model 通过 /chat/completions 或 /images/generations 调用会返回 400(code: wrong_endpoint_for_video)。费用于 completed 时按实际 usage.cost 结算。

视频任务类型

同一个端点涵盖多种任务,实际执行哪一种由你传入的字段决定 —— 同一个模型可以做图生视频、首尾帧、视频接续。并非每个模型都支持每种任务,不支持时返回 400。

文生视频
prompt
只给文字提示,从零生成,不需输入素材。
图生视频
frame_images: [ 首帧 ]
图片就是画面本身:当作第一帧让它动起来,内容忠于原图。例:一张猫的照片 → 那只猫在同一个场景里转头。
首尾帧生视频
frame_images: [ 首帧, 尾帧 ]
给起点与终点两张图,模型补出中间的运动过渡。
视频接续
input_video
延续一段既有视频。要求的 duration 必须大于来源视频的长度。
参考生视频
input_references: [ 参考图 ]
图片是「参考」不是画面:模型保留主体/风格,生成全新场景。例:一张猫的照片 +「在森林里跳舞」→ 全新视频,猫的长相保留但场景与动作都是新的(可放 1–9 张参考图)。与图生视频的差别:图生视频忠于原图;参考生视频是「照着这个角色演新戏」。
视频编辑
input_video + prompt
编辑一段既有视频 —— 换场景、风格或动作。计费 = 输入视频秒数 + 输出秒数。

1. 提交任务(立即返回 vjob_xxx)

POST/api/v1/videos
model必填
string
模型 ID,例如 alibaba/wan2.7-t2v
prompt必填
string
文字提示
duration
integer
秒数(依模型限制)
resolution
string
分辨率:480p / 720p / 1080p 等
generate_audio
boolean
是否生成音频(true/false)
frame_images
array
首/尾帧图片(图生视频、首尾帧)。对象 { type: "image_url", image_url: { url }, frame_type: "first_frame" | "last_frame" } 或纯 URL 字符串。
input_references
array
参考生视频用的参考图 —— 引导主体/风格,非精确帧。
input_video
string|object
视频接续与视频编辑的来源视频 URL,必须是上游可公开访问的网址。
aspect_ratio
string
宽高比,例如 16:9 或 9:16。当输入图已决定比例时会被忽略。
watermark
boolean
加上水印,默认 false。
callback_url
string
任务进入终态时调用的 webhook 网址——仅限 HTTPS,会做 SSRF 检查。v1 无签名;请视为提示,并用 GET /videos/{id} 回查确认。
curl https://bazaarlink.ai/api/v1/videos \
  -H "Authorization: Bearer $BL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "alibaba/wan2.7-t2v",
    "prompt": "a bird flying over mountains",
    "duration": 3,
    "resolution": "720p",
    "generate_audio": false
  }'
# → 202 { "id": "vjob_xxx", "status": "pending" }
Note
Submit 时按最坏情况 × duration × multiplier 预扣;completed 时以上游返回的 usage.cost 补扣/退差。

2. 轮询状态

GET/api/v1/videos/{id}
curl -H "Authorization: Bearer $BL_API_KEY" \
  https://bazaarlink.ai/api/v1/videos/vjob_xxx
Note
每次 GET 间隔需 ≥ 8 秒才会实际请求上游(避免限流)
Note
若 status=failed,reserve 金额全额退回用户。

3. 获取视频内容 (MP4)

GET/api/v1/videos/{id}/content
curl -H "Authorization: Bearer $BL_API_KEY" \
  -o output.mp4 \
  https://bazaarlink.ai/api/v1/videos/vjob_xxx/content

使用须知

  • 各模型支持的画质不同 —— 传不支持的值会返回 400 并列出可用画质。
  • 输入的图片/视频必须是公开可访问的 URL。防盗链的网站(例如部分 wiki)会失败。
  • 输入素材会经过上游内容审核,偶尔可能被误挡。
  • 视频接续时,要求的 duration 必须大于来源视频长度。
  • 输出宽高比会跟随输入图 —— 方形图会生成方形视频。
  • 视频编辑的计费为:输入视频秒数 + 生成输出秒数。
  • 视频编辑/接续的 input_video 必须是公开网址。你在这里生成的视频是凭 API 密钥才能访问的,上游抓不到,所以来源视频请放到公开可读的网址。
  • Webhook 没有签名——采取行动前请用 GET /videos/{id} 回查状态与金额,且其中的 unsigned_urls 是绝对网址(跟轮询响应的相对路径不同)。

支持的视频模型

Model IDModalityTasks
bytedance/seedance-2.0text+image+audio+video->videot2v, i2v
bytedance/seedance-2.0-fasttext+image+audio+video->videot2v, i2v
google/veo-3.1text+image->videot2v, i2v
openai/sora-2-protext+image->videot2v, i2v
bytedance/seedance-1-5-protext+image->videot2v, i2v
alibaba/wan2.6-i2vtext+image->videoi2v
alibaba/wan2.6-i2v-flashtext+image->videoi2v
alibaba/wan2.6-r2vtext+image+video->videor2v
alibaba/wan2.1-t2v-turbotext->videot2v
alibaba/wan2.2-i2v-plustext+image->videoi2v
alibaba/wan2.6-r2v-flashtext+image+video->videor2v
alibaba/happyhorse-1.1text+image->videot2v, i2v
alibaba/wan2.5-i2v-previewtext+image->videoi2v
alibaba/wan2.7-i2vtext+image+video->videoi2v, kf2v, continuation
alibaba/wan2.6-t2vtext->videot2v
alibaba/wan2.5-t2v-previewtext->videot2v
alibaba/wan2.2-t2v-plustext->videot2v
alibaba/wan2.7-t2vtext->videot2v
alibaba/wan2.7-r2vtext+image+video->videor2v
alibaba/happyhorse-1.0text+image->videot2v, i2v
alibaba/wan2.2-i2v-flashtext+image->videoi2v
alibaba/wan2.7-videoedittext+image+video->videovideoedit
alibaba/wan2.1-t2v-plustext->videot2v

影片输入

传送视频档案给支援视频输入的模型,用来分析内容、生成说明或回答场景与事件相关问题。可用直接 URL 或 base64 数据 URI — URL 适合公开可存取的视频;base64 用于本机档案或私有视频。

支援的格式

MP4(H.264)MPEGMOVWebM
response = client.chat.completions.create(
    model="google/gemini-2.5-flash",
    messages=[{
        "role": "user",
        "content": [
            {
                "type": "video_url",
                "video_url": {"url": "https://example.com/video.mp4"},
            },
            {"type": "text", "text": "What is happening in this video?"},
        ],
    }],
)

完整 API 参考 →

PDF 输入

直接在讯息中传送 PDF 文件,给原生支援 PDF 输入的模型(例如 Claude、Gemini)分析、摘要或回答问题。BazaarLink 会把档案直接转送给模型 — 算一般 input tokens,不额外收费、不额外处理。

支援的格式

  • PDF 文件(含文字、图片、表格、扫描件)
  • Base64 资料 URL(`data:application/pdf;base64,...`)
  • 多页文件
  • 仅限无密码保护的 PDF
import base64

with open("document.pdf", "rb") as f:
    pdf_data = base64.b64encode(f.read()).decode()

response = client.chat.completions.create(
    model="anthropic/claude-sonnet-4.6",
    messages=[{
        "role": "user",
        "content": [
            {
                "type": "file",
                "file": {
                    "filename": "document.pdf",
                    "file_data": f"data:application/pdf;base64,{pdf_data}",
                },
            },
            {"type": "text", "text": "Summarize this document."},
        ],
    }],
)

Responses API

相容 OpenAI Responses API 格式的端点,支援无状态多轮对话、工具呼叫与多模态输入。适用于使用 OpenAI Python SDK ≥ 1.x 的 client.responses.create() 的 Agent 框架。

POST/api/v1/responses
Note
使用与 Chat Completions 相同的身份验证与模型路由逻辑。

请求内文

model必填
string
模型 ID,例如 "openai/gpt-4o" 或 "anthropic/claude-3.5-sonnet"
input必填
string | Item[]
使用者输入 — 纯字串(单则讯息)或输入项目阵列(多轮 / 多模态对话)。
instructions
string
系统层级指令,等同于 system 角色的讯息。每次请求都必须重新传送。
stream
boolean
若为 true,回传 Responses API SSE 串流事件,包含 response.created、response.output_text.delta、response.completed 等事件类型。
max_output_tokens
integer
最大输出 Token 数量(o 系列推理模型包含推理 Token)。
temperature
number
取样温度 0–2。越高越随机。预设:1
top_p
number
核取样概率质量。预设:1
tools
Tool[]
工具(函数)定义,格式与 Chat Completions 相同的 JSON Schema(接受扁平的 Responses 格式,也接受嵌套格式)。不支持 OpenAI 专属的内建托管工具(web_search_preview、file_search、computer_use_preview);网页搜索可通过 plugins: [{id:"web"}] 启用,仅部分模型路由支持。
tool_choice
string | object
控制工具使用:"auto"、"none" 或指定工具
parallel_tool_calls
boolean
启用并行工具呼叫功能。预设:true。仅限 OpenAI 系列模型 —— 见下方说明。
response_format
object
强制结构化 JSON 输出。请参阅结构化输出章节
models
string[]
备用模型清单——BazaarLink 依序尝试,主模型失败时自动切换
transforms
string[]
要套用的讯息转换,例如 ["middle-out"]。省略则在 ≤8k context 模型自动套用
previous_response_id
string
本端点是无状态的——传入非 null 值会直接返回 400(invalid_prompt),不是被接受后忽略。请改用无状态模式:在 input 数组中带入完整对话历史。
provider
object
进阶路由偏好——大多数用户不需要。

请求结构 (TypeScript)

type ResponsesRequest = {
  model: string;                    // "provider/model-name"
  input: string | InputItem[];      // string or multi-turn array

  // Optional
  instructions?: string;            // System-level message
  stream?: boolean;                 // Default: false
  max_output_tokens?: number;
  temperature?: number;             // Range: [0, 2], default: 0.7
  top_p?: number;
  tools?: Tool[];
  tool_choice?: "auto" | "none" | "required" | object;
  parallel_tool_calls?: boolean;    // Default: true
  previous_response_id?: string;    // Not supported — use full input array
  provider?: ProviderPreferences;   // Same as Chat Completions
};

type InputItem =
  | { type?: "message"; role: "user" | "assistant" | "system" | "developer"; content: string | ContentBlock[] }
  | { type: "function_call_output"; call_id: string; output: string }   // tool result
  | { type: "function_call"; call_id: string; name: string; arguments: string };

type ContentBlock =
  | { type: "input_text"; text: string }
  | { type: "input_image"; image_url: string; detail?: "auto" | "low" | "high" };

范例请求

curl https://bazaarlink.ai/api/v1/responses \
  -H "Authorization: Bearer $BAZAARLINK_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "openai/gpt-4o-mini",
    "instructions": "You are a helpful assistant.",
    "input": "What is the capital of Taiwan?"
  }'

回应格式

// Non-streaming response object
type ResponsesResponse = {
  id: string;             // "resp_..."
  object: "response";
  created_at: number;
  completed_at: number;
  status: "completed" | "failed" | "incomplete";
  model: string;
  output: OutputItem[];
  usage: {
    input_tokens: number;   // equivalent to prompt_tokens
    output_tokens: number;  // equivalent to completion_tokens
    total_tokens: number;
    cost?: number;          // actual cost in credits
  } | null;
  error: null | { code: string; message: string };
};

type OutputItem =
  | {
      type: "message";
      id: string;
      role: "assistant";
      status: "completed";
      content: Array<{ type: "output_text"; text: string; annotations: [] }>;
    }
  | { type: "function_call"; id: string; call_id: string; name: string; arguments: string; status: "completed" };

从 Chat Completions 迁移

将 messages 改为 input(字串或阵列),以 instructions 取代 system 角色讯息,并从 output[0].content[0].text 读取回应内容(原为 choices[0].message.content)。

# Chat Completions (before)
response = client.chat.completions.create(
    model="openai/gpt-4o-mini",
    messages=[
        {"role": "system", "content": "You are helpful."},
        {"role": "user",   "content": "Hello"},
    ]
)
text = response.choices[0].message.content

# Responses API (after)
response = client.responses.create(
    model="openai/gpt-4o-mini",
    instructions="You are helpful.",
    input="Hello"
)
text = response.output[0].content[0].text

限制事项

  • previous_response_id 或 store: true 会被拒绝并返回 400(错误码 invalid_prompt)——不是被接受后忽略。请一律使用无状态模式,在 input 数组中带入完整对话历史。
  • 不支持 OpenAI 专属的内建托管工具(web_search_preview、file_search、computer_use_preview)。网页搜索可通过 plugins: [{id:"web"}] 启用,仅部分模型路由支持。
  • background: true 会被接受但忽略,请求一律同步执行到完成为止。

Messages(Anthropic 兼容)

与 Anthropic Claude SDK 兼容的 Messages API。使用方式和 Anthropic 官方 API 完全相同,只需更换 base URL 和 auth header。

POST/api/v1/messages
Note
支持 Bearer token 或 x-api-key header(兼容 Anthropic SDK)。最大请求 body 为 10 MB。

请求内文

model必填
string
模型 ID,例如 "openai/gpt-4o" 或 "anthropic/claude-3.5-sonnet"
max_tokens必填
integer
生成的最大 token 数(正整数)。
messages必填
Message[]
对话消息数组(不可为空)。
system
string
选填的 system prompt。
stream
boolean
若为 true,返回 Server-Sent Events 串流。预设:false
temperature
number
取样温度 0–2。越高越随机。预设:1
top_p
number
核取样概率质量。预设:1
top_k
integer
限制候选 token 数量。0 表示停用(考虑全部)。预设:0
stop_sequences
string[]
自定义停止序列字符串数组。
tools
Tool[]
模型可以呼叫的工具(函式)列表
tool_choice
string | object
控制工具使用:"auto"、"none" 或指定工具

范例请求

from anthropic import Anthropic

client = Anthropic(
    base_url="https://bazaarlink.ai/api/v1",
    api_key="sk-bl-YOUR_KEY"
)

response = client.messages.create(
    model="anthropic/claude-opus-4",
    max_tokens=1024,
    messages=[{"role": "user", "content": "Hello"}]
)
print(response.content[0].text)

回应

{
  "id": "msg_...",
  "type": "message",
  "role": "assistant",
  "model": "anthropic/claude-opus-4",
  "content": [
    { "type": "text", "text": "Hello! How can I help you today?" }
  ],
  "stop_reason": "end_turn",
  "usage": {
    "input_tokens": 10,
    "output_tokens": 12,
    "cache_read_input_tokens": 0,
    "cache_creation_input_tokens": 0,
    "bz_cost": 0.00042
  }
}

错误:400(验证失败)、402(额度不足)、429(rate limit)、502(上游错误或缺少密钥)、503(服务器重启中)。

模型

列出所有可用模型及其定价和能力资讯。 此端点不需要身份验证。

GET/api/v1/models
# Text models (default)
curl https://bazaarlink.ai/api/v1/models

# Complete catalog
curl "https://bazaarlink.ai/api/v1/models?output_modalities=all"

回应

{
  "data": [
    {
      "id": "openai/gpt-4.1",
      "name": "GPT 4.1",
      "context_length": 1047576,
      "modality": "text+image+file->text",
      "pricing": {
        "prompt": "2.00",
        "completion": "8.00"
      }
    }
  ]
}
// /v1/models — Response Schema
type ModelsResponse = {
  data: Model[];
};

type Model = {
  id: string;                    // Model ID (e.g. "openai/gpt-4.1")
  name: string;                  // Human-readable name
  context_length: number | null; // Max context window in tokens
  modality: string | null;       // e.g. "text->text", "text+image->text"
  architecture?: {
    input_modalities?: string[];
    output_modalities?: Array<
      "text" | "image" | "embeddings" | "audio" |
      "video" | "rerank" | "speech" | "transcription"
    >;
  };
  pricing: {
    prompt: string;              // Input price per 1M tokens (USD)
    completion: string;          // Output price per 1M tokens (USD)
  };
  description?: string | null;   // Model description
  top_provider?: {
    max_completion_tokens?: number;
  };
  supported_parameters?: string[]; // e.g. ["tools", "response_format", "reasoning"]
  pricing_tiers?: {               // Present only for models with input-length tiers
    above_prompt_tokens: number;  // Ascending; strict "greater than" threshold
    prompt: string;                // USD per token, override tier
    completion: string;            // USD per token, override tier
  }[];
};

按输入长度分档定价

部分模型在 prompt 超过 token 门槛后会切换到不同的整张价目表,并非只有超过门槛的部分套用新价 — 而是整张价目表切换。门槛为严格不等式:输入 token 数刚好等于 N 时仍套用 N 以下的那一档,仅当输入 token 数大于 N 时才套用更高档。

pricing_tiers 是 pricing 的同层字段,仅当模型有超出基础价的覆盖档位时才会出现。条目按 above_prompt_tokens 递增排序;prompt/completion 为每 token 的美元价(与 pricing.prompt/pricing.completion 同单位)。pricing.prompt 与 pricing.completion 永远是基础(最低)档位。

大多数模型没有分档定价 — 对这些模型,响应中完全不会有 pricing_tiers 这个字段。

{
  "id": "openai/gpt-4.1",
  "name": "GPT 4.1",
  "pricing": {
    "prompt": "2.00",
    "completion": "8.00"
  },
  "pricing_tiers": [
    {
      "above_prompt_tokens": 128000,
      "prompt": "4.00",
      "completion": "16.00"
    }
  ]
}

可用模型 (254)

以下是目前 BazaarLink 上可用的模型,从资料库动态载入:

OpenAI
openai/gpt-5.6-luna-pro1050K ctx · $0.50/$3.00text+image+file->text
openai/gpt-5.2-codex400K ctx · $1.75/$14.00text+image->text
openai/gpt-3.5-turbo-instruct4K ctx · $1.50/$2.00text->text
openai/gpt-5.4-nano400K ctx · $0.20/$1.25text+image+file->text
openai/gpt-5-codex400K ctx · $1.25/$10.00text+image->text
openai/text-embedding-ada-0028K ctx · $0.10/$0.00text->embeddings
openai/o4-mini200K ctx · $1.10/$4.40text+image+file->text
openai/o1-pro200K ctx · $150.00/$600.00text+image+file->text
openai/gpt-5.4-mini400K ctx · $0.75/$4.50text+image+file->text
openai/gpt-5.1400K ctx · $1.25/$10.00text+image+file->text
openai/o3-pro200K ctx · $20.00/$80.00text+image+file->text
openai/gpt-5.6-luna1050K ctx · $0.50/$3.00text+image+file->text
openai/gpt-48K ctx · $30.00/$60.00text->text
openai/gpt-5.6-sol1050K ctx · $5.00/$30.00text+image+file->text
openai/gpt-4o-mini-2024-07-18128K ctx · $0.15/$0.60text+image+file->text
openai/gpt-5-mini400K ctx · $0.25/$2.00text+image+file->text
openai/gpt-4o-2024-08-06128K ctx · $2.50/$10.00text+image+file->text
openai/o3-deep-research200K ctx · $10.00/$40.00text+image+file->text
openai/gpt-5.2-chat128K ctx · $1.75/$14.00text+image+file->text
openai/gpt-4-turbo-preview128K ctx · $10.00/$30.00text->text
openai/gpt-5.2400K ctx · $1.75/$14.00text+image+file->text
openai/gpt-5.1-chat128K ctx · $1.25/$10.00text+image+file->text
openai/o4-mini-deep-research200K ctx · $2.00/$8.00text+image+file->text
openai/text-embedding-3-small8K ctx · $0.02/$0.00text->embeddings
openai/gpt-4.1-nano1048K ctx · $0.10/$0.40text+image+file->text
openai/o3200K ctx · $2.00/$8.00text+image+file->text
openai/gpt-3.5-turbo16K ctx · $0.50/$1.50text->text
openai/gpt-5.51050K ctx · $5.00/$30.00text+image+file->text
openai/gpt-3.5-turbo-06134K ctx · $1.00/$2.00text->text
openai/gpt-4.11048K ctx · $2.00/$8.00text+image+file->text
openai/gpt-5-pro400K ctx · $15.00/$120.00text+image+file->text
openai/gpt-4.1-mini1048K ctx · $0.40/$1.60text+image+file->text
openai/gpt-oss-20b131K ctx · $0.03/$0.13text->text
openai/gpt-5.2-pro400K ctx · $21.00/$168.00text+image+file->text
openai/o4-mini-high200K ctx · $1.10/$4.40text+image+file->text
openai/gpt-3.5-turbo-16k16K ctx · $3.00/$4.00text->text
openai/gpt-5.3-codex400K ctx · $1.75/$14.00text+image+file->text
openai/gpt-4o-mini128K ctx · $0.15/$0.60text+image+file->text
openai/gpt-5.3-chat128K ctx · $1.75/$14.00text+image+file->text
openai/gpt-4o-2024-05-13128K ctx · $5.00/$15.00text+image+file->text
openai/gpt-oss-120b131K ctx · $0.15/$0.60text->text
openai/o3-mini200K ctx · $1.10/$4.40text+file->text
openai/gpt-4-turbo128K ctx · $10.00/$30.00text+image->text
openai/gpt-5.4-pro1050K ctx · $30.00/$180.00text+image+file->text
openai/text-embedding-3-large8K ctx · $0.13/$0.00text->embeddings
openai/gpt-5.41050K ctx · $2.50/$15.00text+image+file->text
openai/gpt-5.1-codex-max400K ctx · $1.25/$10.00text+image->text
openai/gpt-5-nano400K ctx · $0.05/$0.40text+image+file->text
openai/o1200K ctx · $15.00/$60.00text+image+file->text
openai/gpt-5.1-codex-mini400K ctx · $0.25/$2.00text+image->text
openai/gpt-5.6-terra-pro1050K ctx · $1.25/$7.50text+image+file->text
openai/gpt-5.6-terra1050K ctx · $1.25/$7.50text+image+file->text
openai/gpt-5.6-sol-pro1050K ctx · $5.00/$30.00text+image+file->text
openai/gpt-5.1-codex400K ctx · $1.25/$10.00text+image->text
openai/o3-mini-high200K ctx · $1.10/$4.40text+file->text
openai/gpt-4o-2024-11-20128K ctx · $2.50/$10.00text+image+file->text
openai/gpt-5400K ctx · $1.25/$10.00text+image+file->text
openai/sora-2-pro · $0.00/$0.00text+image->video
openai/gpt-4o128K ctx · $2.50/$10.00text+image+file->text
openai/gpt-oss-safeguard-20b131K ctx · $0.07/$0.30text->text
openai/gpt-5.4-image-2272K ctx · $8.00/$15.00text+image+file->text+image
openai/gpt-image-1-mini400K ctx · $2.50/$2.50text+image->image
openai/gpt-image-1400K ctx · $10.00/$10.00text+image->image
openai/gpt-image-2400K ctx · $8.00/$8.00text+image->image
Qwen
qwen/qwen3.7-max1000K ctx · $1.48/$4.42text->text
qwen/qwen3.7-plus1000K ctx · $0.32/$1.28text+image->text
qwen/qwen3-coder-flash1000K ctx · $0.20/$0.97text->text
qwen/qwen-2.5-coder-32b-instruct33K ctx · $0.66/$1.00text->text
qwen/qwen-plus1000K ctx · $0.26/$0.78text->text
qwen/qwen3.6-35b-a3b262K ctx · $0.14/$1.00text+image+video->text
qwen/qwen3-coder262K ctx · $0.30/$1.00text->text
qwen/qwen-plus-2025-07-281000K ctx · $0.26/$0.78text->text
qwen/qwen3-235b-a22b-2507262K ctx · $0.09/$0.55text->text
qwen/qwen3.5-plus-202604201000K ctx · $0.30/$1.80text+image+video->text
qwen/qwen3-embedding-4b33K ctx · $0.02/$0.00text->embeddings
qwen/qwen3-coder-30b-a3b-instruct262K ctx · $0.07/$0.27text->text
qwen/qwen-2.5-7b-instruct33K ctx · $0.04/$0.10text->text
qwen/qwen3-coder-plus1000K ctx · $0.65/$3.25text->text
qwen/qwen3-next-80b-a3b-instruct262K ctx · $0.10/$1.10text->text
qwen/qwen-2.5-72b-instruct33K ctx · $0.36/$0.40text->text
qwen/qwen3.5-plus-02-151000K ctx · $0.26/$1.56text+image+video->text
qwen/qwen-plus-2025-07-28:thinking1000K ctx · $0.40/$1.20text->text
qwen/qwen3-vl-235b-a22b-thinking131K ctx · $0.40/$4.00text+image->text
qwen/qwen3-vl-8b-thinking131K ctx · $0.18/$2.10text+image->text
qwen/qwen3-30b-a3b-instruct-2507262K ctx · $0.05/$0.19text->text
qwen/qwen3.5-flash-02-231000K ctx · $0.07/$0.26text+image+video->text
qwen/qwen3-vl-235b-a22b-instruct262K ctx · $0.21/$1.90text+image->text
qwen/qwen3.5-27b262K ctx · $0.20/$1.56text+image+video->text
qwen/qwen3-235b-a22b131K ctx · $0.46/$1.82text->text
qwen/qwen3.5-9b262K ctx · $0.10/$0.15text+image+video->text
qwen/qwen3-32b131K ctx · $0.08/$0.28text->text
qwen/qwen3-30b-a3b131K ctx · $0.13/$0.52text->text
qwen/qwen3-8b131K ctx · $0.12/$0.46text->text
qwen/qwen3-max-thinking262K ctx · $0.78/$3.90text->text
qwen/qwen3-vl-8b-instruct262K ctx · $0.12/$0.46text+image->text
qwen/qwen3.5-122b-a10b262K ctx · $0.26/$2.08text+image+video->text
qwen/qwen3-next-80b-a3b-thinking262K ctx · $0.15/$1.20text->text
qwen/qwen3-vl-30b-a3b-thinking262K ctx · $0.20/$2.40text+image->text
qwen/qwen2.5-vl-72b-instruct128K ctx · $0.80/$1.00text+image->text
qwen/qwen3-235b-a22b-thinking-2507262K ctx · $0.30/$3.00text->text
qwen/qwen3.5-35b-a3b262K ctx · $0.14/$1.00text+image+video->text
qwen/qwen3-coder-next262K ctx · $0.12/$0.80text->text
qwen/qwen3-max262K ctx · $0.78/$3.90text->text
qwen/qwen3-30b-a3b-thinking-250782K ctx · $0.20/$2.40text->text
qwen/qwen3-vl-30b-a3b-instruct262K ctx · $0.13/$0.52text+image->text
qwen/qwen3-vl-32b-instruct131K ctx · $0.10/$0.42text+image->text
qwen/qwen3-14b131K ctx · $0.23/$0.91text->text
qwen/qwen3.5-397b-a17b262K ctx · $0.39/$2.34text+image+video->text
qwen/qwen3.6-27b262K ctx · $0.29/$2.40text+image+video->text
qwen/qwen3.6-plus1000K ctx · $0.33/$1.95text+image+video->text
qwen/qwen3-embedding-8b33K ctx · $0.01/$0.00text->embeddings
qwen/qwen-imagetext->image
qwen/qwen3-tts-flash · $0.00/$0.00text->audio
qwen/qwen-image-maxtext->image
qwen/qwen-image-plustext->image
qwen/qwen-image-edit-plustext+image->image
qwen/qwen-image-2.0-protext->image
qwen/qwen-image-edittext+image->image
qwen/qwen-image-2.0text->image
qwen/qwen-image-edit-maxtext+image->image
Alibaba
alibaba/wan2.5-i2i-previewtext+image->image
alibaba/wan2.6-i2v · $0.00/$0.00text+image->video
alibaba/wan2.6-i2v-flash · $0.00/$0.00text+image->video
alibaba/wan2.6-r2v · $0.00/$0.00text+image+video->video
alibaba/wan2.1-t2v-turbo · $0.00/$0.00text->video
alibaba/wan2.2-i2v-plus · $0.00/$0.00text+image->video
alibaba/wan2.5-t2i-previewtext->image
alibaba/wan2.6-imagetext->image
alibaba/wan2.6-t2itext->image
alibaba/wan2.7-imagetext->image
alibaba/wan2.7-image-protext->image
alibaba/wan2.6-r2v-flash · $0.00/$0.00text+image+video->video
alibaba/happyhorse-1.1 · $0.00/$0.00text+image->video
alibaba/wan2.1-t2i-plustext->image
alibaba/wan2.1-t2i-turbotext->image
alibaba/z-image-turbotext->image
alibaba/wan2.2-t2i-plustext->image
alibaba/wan2.5-i2v-preview · $0.00/$0.00text+image->video
alibaba/wan2.7-i2v · $0.00/$0.00text+image+video->video
alibaba/wan2.6-t2v · $0.00/$0.00text->video
alibaba/wan2.5-t2v-preview · $0.00/$0.00text->video
alibaba/wan2.2-t2v-plus · $0.00/$0.00text->video
alibaba/wan2.7-t2v · $0.00/$0.00text->video
alibaba/wan2.7-r2v · $0.00/$0.00text+image+video->video
alibaba/happyhorse-1.0 · $0.00/$0.00text+image->video
alibaba/wan2.2-i2v-flash · $0.00/$0.00text+image->video
alibaba/wan2.2-t2i-flashtext->image
alibaba/wan2.7-videoedit · $0.00/$0.00text+image+video->video
alibaba/wan2.1-t2v-plus · $0.00/$0.00text->video
Google
google/gemma-3-4b-it131K ctx · $0.05/$0.10text+image->text
google/gemini-embedding-2-preview8K ctx · $0.20/$0.00text+image+file+audio+video->embeddings
google/gemini-3.1-pro-preview1049K ctx · $2.00/$12.00text+image+file+audio+video->text
google/gemini-2.5-flash-image33K ctx · $0.30/$2.50text+image->text+image
google/gemini-3.5-flash1049K ctx · $1.50/$9.00text+image+file+audio+video->text
google/gemini-2.5-pro-preview1049K ctx · $1.25/$10.00text+image+file+audio->text
google/gemma-3n-e4b-it33K ctx · $0.06/$0.12text->text
google/gemini-3.1-flash-image131K ctx · $0.50/$3.00text+image->text+image
google/gemini-2.5-flash1049K ctx · $0.30/$2.50text+image+file+audio+video->text
google/gemini-3-flash-preview1049K ctx · $0.50/$3.00text+image+file+audio+video->text
google/gemma-3-12b-it131K ctx · $0.05/$0.15text+image->text
google/gemini-2.5-flash-lite1049K ctx · $0.10/$0.40text+image+file+audio+video->text
google/gemma-2-27b-it8K ctx · $0.65/$0.65text->text
google/gemini-2.5-pro1049K ctx · $1.25/$10.00text+image+file+audio+video->text
google/gemma-4-31b-it262K ctx · $0.14/$0.40text+image+video->text
google/gemini-3.1-flash-lite-preview1049K ctx · $0.25/$1.50text+image+file+audio+video->text
google/gemini-embedding-00120K ctx · $0.15/$0.00text->embeddings
google/gemini-2.5-pro-preview-05-061049K ctx · $1.25/$10.00text+image+file+audio+video->text
google/gemini-3.5-flash-lite1049K ctx · $0.30/$2.50text+image+file+audio+video->text
google/gemma-3-27b-it262K ctx · $0.08/$0.45text+image->text
google/veo-3.1 · $0.00/$0.00text+image->video
google/gemini-3-pro-image131K ctx · $2.00/$12.00text+image->text+image
google/gemini-3.1-pro-preview-customtools1049K ctx · $2.00/$12.00text+image+file+audio+video->text
google/gemma-4-26b-a4b-it262K ctx · $0.07/$0.34text+image+video->text
google/gemini-3.6-flash1049K ctx · $1.50/$7.50text+image+file+audio+video->text
google/gemini-3.1-flash-image-preview66K ctx · $0.50/$3.00text+image->text+image
Anthropic
anthropic/claude-sonnet-41000K ctx · $3.00/$15.00text+image+file->text
anthropic/claude-opus-4.61000K ctx · $5.00/$25.00text+image+file->text
anthropic/claude-sonnet-51000K ctx · $2.00/$10.00text+image+file->text
anthropic/claude-haiku-4.5200K ctx · $1.00/$5.00text+image+file->text
anthropic/claude-sonnet-4.51000K ctx · $3.00/$15.00text+image+file->text
anthropic/claude-sonnet-4.61000K ctx · $3.00/$15.00text+image+file->text
anthropic/claude-fable-51000K ctx · $10.00/$50.00text+image+file->text
anthropic/claude-opus-4.81000K ctx · $5.00/$25.00text+image+file->text
anthropic/claude-opus-4.71000K ctx · $5.00/$25.00text+image+file->text
anthropic/claude-3-haiku200K ctx · $0.25/$1.25text+image->text
anthropic/claude-opus-4.5200K ctx · $5.00/$25.00text+image+file->text
anthropic/claude-opus-4200K ctx · $15.00/$75.00text+image+file->text
anthropic/claude-opus-4.1200K ctx · $15.00/$75.00text+image+file->text
anthropic/claude-opus-51000K ctx · $5.00/$25.00text+image+file->text
Zhipu AI
z-ai/glm-4.7205K ctx · $0.40/$1.75text->text
z-ai/glm-5205K ctx · $0.95/$2.55text->text
z-ai/glm-5.21049K ctx · $1.40/$4.40text->text
z-ai/glm-5.1205K ctx · $0.97/$3.04text->text
z-ai/glm-5v-turbo203K ctx · $1.20/$4.00text+image+video->text
z-ai/glm-4.6v131K ctx · $0.30/$0.90text+image+video->text
z-ai/glm-4.6205K ctx · $0.50/$2.00text->text
z-ai/glm-4.7-flash203K ctx · $0.06/$0.40text->text
z-ai/glm-4.5-air131K ctx · $0.13/$0.85text->text
z-ai/glm-5-turbo203K ctx · $1.20/$4.00text->text
z-ai/glm-4.5131K ctx · $0.60/$2.20text->text
z-ai/glm-4.5v66K ctx · $0.60/$1.80text+image->text
DeepSeek
deepseek/deepseek-v4-flash1049K ctx · $0.20/$0.40text->text
deepseek/deepseek-v3.2164K ctx · $0.27/$0.40text->text
deepseek/deepseek-v4-pro1049K ctx · $2.40/$4.80text->text
deepseek/deepseek-v3.2-exp164K ctx · $0.27/$0.41text->text
deepseek/deepseek-r1164K ctx · $0.70/$2.50text->text
deepseek/deepseek-v3.1-terminus164K ctx · $0.27/$1.00text->text
deepseek/deepseek-chat-v3-0324164K ctx · $0.27/$1.12text->text
deepseek/deepseek-r1-0528164K ctx · $0.50/$2.15text->text
deepseek/deepseek-r1-distill-llama-70b8K ctx · $0.80/$0.80text->text
deepseek/deepseek-chat-v3.1164K ctx · $0.25/$0.95text->text
deepseek/deepseek-chat164K ctx · $0.40/$1.30text->text
Moonshot AI
moonshotai/kimi-k2.7-code262K ctx · $0.78/$3.50text+image->text
moonshotai/kimi-k31049K ctx · $3.00/$15.00text+image->text
moonshotai/kimi-k2.5262K ctx · $0.57/$2.85text+image->text
moonshotai/kimi-k2131K ctx · $0.57/$2.30text->text
moonshotai/kimi-k2-0905262K ctx · $0.60/$2.50text->text
moonshotai/kimi-k2.6262K ctx · $0.65/$2.72text+image->text
moonshotai/kimi-k2-thinking262K ctx · $0.60/$2.50text->text
xAI
x-ai/grok-4.202000K ctx · $1.25/$2.50text+image+file->text
x-ai/grok-4.20-multi-agent2000K ctx · $1.25/$2.50text+image+file->text
x-ai/grok-4.31000K ctx · $1.25/$2.50text+image+file->text
x-ai/grok-4.5500K ctx · $2.00/$6.00text+image+file->text
x-ai/grok-build-0.1256K ctx · $1.00/$2.00text+image+file->text
Perplexity
perplexity/sonar-pro200K ctx · $3.00/$15.00text+image->text
perplexity/sonar-reasoning-pro128K ctx · $2.00/$8.00text+image->text
perplexity/sonar127K ctx · $1.00/$1.00text+image->text
perplexity/sonar-deep-research128K ctx · $2.00/$8.00text->text
perplexity/sonar-pro-search200K ctx · $3.00/$15.00text+image->text
bytedance-seed
bytedance-seed/seed-2.0-mini262K ctx · $0.10/$0.40text+image+video->text
bytedance-seed/seed-1.6-flash262K ctx · $0.07/$0.30text+image+video->text
bytedance-seed/seed-1.6262K ctx · $0.25/$2.00text+image+video->text
bytedance-seed/seed-2.0-lite262K ctx · $0.25/$2.00text+image+video->text
MiniMax
minimax/minimax-m2.1205K ctx · $0.30/$1.20text->text
minimax/minimax-m31049K ctx · $0.30/$1.20text+image+video->text
minimax/minimax-m2.5205K ctx · $0.30/$1.20text->text
minimax/minimax-m2.7205K ctx · $0.25/$1.00text->text
Nous
nousresearch/hermes-3-llama-3.1-70b131K ctx · $0.70/$0.70text->text
nousresearch/hermes-3-llama-3.1-405b131K ctx · $1.00/$1.00text->text
nousresearch/hermes-4-70b131K ctx · $0.13/$0.40text->text
nousresearch/hermes-4-405b131K ctx · $1.00/$3.00text->text
Mistral
mistralai/mistral-large128K ctx · $2.00/$6.00text+file->text
mistralai/voxtral-small-24b-250732K ctx · $0.10/$0.30text+file+audio->text
mistralai/mixtral-8x22b-instruct66K ctx · $2.00/$6.00text+file->text
ByteDance
bytedance/seedance-2.0 · $0.00/$0.00text+image+audio+video->video
bytedance/seedance-2.0-fast · $0.00/$0.00text+image+audio+video->video
bytedance/seedance-1-5-pro · $0.00/$0.00text+image->video
NVIDIA
nvidia/nemotron-3-super-120b-a12b1000K ctx · $0.30/$0.90text->text
nvidia/nemotron-3-nano-30b-a3b262K ctx · $0.05/$0.20text->text
xiaomi
xiaomi/mimo-v2.51050K ctx · $0.14/$0.28text+image+audio+video->text
xiaomi/mimo-v2.5-pro1050K ctx · $0.43/$0.87text->text
ibm-granite
ibm-granite/granite-4.0-h-micro131K ctx · $0.02/$0.11text->text
Meta
meta-llama/llama-3.2-1b-instruct60K ctx · $0.03/$0.20text->text
Tongyi-MAI
Tongyi-MAI/Z-Image-Turbotext->image

模型页面浏览所有模型。

串流

设定 stream: true 以接收 Server-Sent Events (SSE) 串流。每个事件包含一个回应片段。

from openai import OpenAI

client = OpenAI(
    base_url="https://bazaarlink.ai/api/v1",
    api_key="sk-bl-YOUR_API_KEY",
)

stream = client.chat.completions.create(
    model="anthropic/claude-sonnet-4.6",
    messages=[{"role": "user", "content": "Count to 10 slowly."}],
    stream=True,
)

for chunk in stream:
    content = chunk.choices[0].delta.content
    if content:
        print(content, end="", flush=True)

SSE 格式

data: {"id":"chatcmpl-abc","choices":[{"delta":{"content":"Hello"},"index":0}]}

data: {"id":"chatcmpl-abc","choices":[{"delta":{"content":" world"},"index":0}]}

data: {"id":"chatcmpl-abc","choices":[{"delta":{},"finish_reason":"stop","index":0}],"usage":{"prompt_tokens":10,"completion_tokens":4,"total_tokens":14}}

data: [DONE]
串流中的使用量
串流时,使用量资料会在 [DONE] 讯息之前的最后一个区块中返回,该区块的 choices 阵列带有一个空 delta 与 finish_reason: "stop"。

Keep-alive 与收尾行为

流式响应中可能出现 SSE 注释行(以冒号开头)或心跳事件作为 keep-alive — 解析时请跳过非 data: 行,不要直接对整行做 JSON.parse。最后一个 data chunk 会带 usage(token 用量与成本),之后才是 data: [DONE]。成功的响应会含 X-Request-Id header,报告问题时请附上。

: keepalive          <- SSE comment line — ignore, do NOT JSON.parse

data: {"id":"chatcmpl-abc","choices":[{"delta":{"content":"Hi"},"index":0}]}

data: {"id":"chatcmpl-abc","choices":[{"delta":{},"finish_reason":"stop","index":0}],"usage":{...}}

data: [DONE]

流取消

流式请求可以通过关闭客户端连接来取消 — 例如调用 AbortController.abort() 或关闭 stream 对象。BazaarLink 收到取消信号后会立即停止转发后续内容,并中止对上游供应商的请求。

import OpenAI from "openai";

const client = new OpenAI({
  baseURL: "https://bazaarlink.ai/api/v1",
  apiKey: "sk-bl-YOUR_API_KEY",
});

const controller = new AbortController();

const stream = await client.chat.completions.create(
  {
    model: "anthropic/claude-sonnet-4.6",
    messages: [{ role: "user", content: "Write a long story." }],
    stream: true,
  },
  { signal: controller.signal }
);

for await (const chunk of stream) {
  const content = chunk.choices[0]?.delta?.content;
  if (content) process.stdout.write(content);
}

// e.g. on a "Stop" button click:
controller.abort();
被中断的流不收费
如果流在最后的 usage chunk 到达前就结束 — 包括客户端主动取消的情况 — 这次请求就没有可信的 token 用量依据,BazaarLink 会全额退还预扣的额度。取消前已发送到你客户端的内容不会计费。
不保证上游立即停止
关闭连接会让 BazaarLink 立即停止转发并停止为后续 token 计费,但上游供应商是否会在自己的服务器上瞬间停止生成,取决于该供应商本身 — 有些供应商断线后仍会短暂继续运算。

串流中途出错

错误帧没有 choices 字段
如果串流已经开始后才发生失败(例如上游连接中断),您会收到一个 {error:{message,type,code}} 形状的 SSE 数据帧,而不是通常的 {choices:[...]} —— HTTP 状态不会变化,因为 header 早就发送了。读取 choices[0].delta 前请先检查是否有 error 字段;计费只会算到已经串流出去的 token(适用部分计费)。
data: {"id":"chatcmpl-abc","choices":[{"delta":{"content":"The capital of "},"index":0}]}

data: {"error":{"message":"Upstream connection lost.","type":"upstream_error","code":502}}

data: [DONE]

嵌入向量

嵌入向量(Embeddings)是能捕捉语义的数值表示法——把文字转换成向量(一串数字),可用于各种机器学习任务。BazaarLink 提供与 OpenAI Embeddings API 相容的统一端点,让您透过同一组接口调用多家供应商的嵌入模型。

什么是嵌入向量?

嵌入向量把文字转换成高维度向量,语义相近的文字在向量空间里的距离也会更接近——例如「猫」与「小猫」的嵌入会很相似,但「猫」与「飞机」会相距很远。这种向量表示法让机器能够理解文字之间的关联,是许多 AI 应用的基础。

常见应用场景

场景
说明
RAG(检索增强生成)打造能在生成答案前,先从知识库中检索相关内容的系统——嵌入向量能找出最相关的文件,放进 LLM 的上下文。
语义搜索把文件和查询都转成嵌入向量,再用向量相似度找出最相关的文件——比单纯比对关键字更能理解语义、效果更好。
推荐系统为商品、文章、视频等项目与用户偏好生成嵌入向量,借由向量比对推荐相近项目——即使没有共同关键字也能找到语义相关的内容。
分群与分类透过分析嵌入向量的模式,把相似的文件分群或分类——嵌入向量相近的文件通常属于相同主题或类别。
重复内容检测透过比对嵌入向量的相似度找出重复或近似重复的内容——即使内容经过改写或换句话说也能检测到。
异常检测找出嵌入向量明显偏离数据集一般模式的内容,借此识别异常或离群的内容。
POST/api/v1/embeddings
Note
并非所有上游供应商都支援嵌入向量。若您设定的供应商不支援所请求的模型,BazaarLink 将自动故障转移至下一个可用的供应商。

参数

model必填
string
要使用的嵌入模型,例如 "openai/text-embedding-3-small"。
input必填
string | string[] | ContentItem[]
要嵌入的文本 —— 可以是单个字符串、一次批量调用用的字符串数组,或(支持的模型)混合 text 和 image_url 部分的 {content:[...]} 项数组。
dimensions
integer
请求的输出向量维度。仅支持可变维度的模型会采用(例如 OpenAI text-embedding-3 系列);原样转发给上游供应商,不支持的模型会忽略此参数。
encoding_format
string
请求的嵌入编码格式,例如 "float" 或 "base64"。原样转发给上游供应商 —— 是否支持取决于模型。
provider
object
供应商路由偏好设置 —— order、allow_fallbacks、data_collection,以及 Provider Selection 中说明的其他字段。

基本请求

from openai import OpenAI

client = OpenAI(
    base_url="https://bazaarlink.ai/api/v1",
    api_key="sk-bl-YOUR_API_KEY",
)

response = client.embeddings.create(
    model="openai/text-embedding-3-small",
    input="The quick brown fox jumps over the lazy dog",
)

print(response.data[0].embedding)  # 1536-dimensional vector

批量处理

发送字符串数组,可在单次请求中嵌入多段文本 —— 比逐条调用更便宜也更快。

response = client.embeddings.create(
    model="openai/text-embedding-3-small",
    input=[
        "Machine learning is a subset of artificial intelligence",
        "Deep learning uses neural networks with multiple layers",
        "Natural language processing enables computers to understand text",
    ],
)

for i, item in enumerate(response.data):
    print(f"Embedding {i}: {len(item.embedding)} dimensions")

多模态输入(图片+文本)

支持图片输入的模型(output_modalities 含 "embeddings"、inputModalities 含 "image")接受 {content:[{type:"text",...}, {type:"image_url",...}]} 形式的输入项,可以单独嵌入图片,或图片与文本一起嵌入。

取决于模型
只有部分嵌入模型接受图片输入 —— 发送 image_url 内容前,请先在 Models 页面确认该模型支持的模态。纯文本模型会拒绝这种格式。
import requests

response = requests.post(
    "https://bazaarlink.ai/api/v1/embeddings",
    headers={
        "Authorization": "Bearer sk-bl-YOUR_API_KEY",
        "Content-Type": "application/json",
    },
    json={
        "model": "google/gemini-embedding-2-preview",
        "input": [{
            "content": [
                {"type": "text", "text": "A scenic boardwalk through a green meadow"},
                {"type": "image_url", "image_url": {"url": "https://example.com/boardwalk.jpg"}},
            ]
        }],
        "encoding_format": "float",
    },
)

embedding = response.json()["data"][0]["embedding"]
print(f"Embedding dimension: {len(embedding)}")

供应商路由

与 chat completions 一样,可以控制由哪个上游服务嵌入请求 —— 完整字段说明见 Provider Selection。

{
  "model": "openai/text-embedding-3-small",
  "input": "Your text here",
  "provider": {
    "order": ["openai"],
    "allow_fallbacks": true,
    "data_collection": "deny"
  }
}

查找嵌入模型

没有专门的嵌入模型列表端点 —— 调用 GET /api/v1/models,在前端筛选 output_modalities 包含 "embeddings" 的条目,或直接前往 Models 页面浏览。

限制

  • 不支持流式传输 —— 与 chat completions 不同,嵌入向量始终以完整响应形式返回。
  • 每个模型都有输入长度上限;超过上限的文本会在上游被截断或拒绝。
  • 相同输入的嵌入结果是确定性的(deterministic)—— 不涉及 temperature 或随机性。

最佳实践

  • 根据速度/质量/成本的取舍选择模型 —— 较小的模型(如 qwen/qwen3-embedding-4b)更便宜更快;较大的模型(如 openai/text-embedding-3-large)通常嵌入精度更高。
  • 把多段文本合并为一次请求,而不是逐条调用 —— 减少往返次数与额外开销。
  • 缓存结果 —— 相同输入的嵌入结果永远不变,应该存储起来而不是重新生成。
  • 比较时用余弦相似度(cosine similarity),而不是欧氏距离 —— 具有尺度不变性,对高维向量效果更好。
  • 留意每个模型的上下文长度 —— 长文档在嵌入前可能需要先分块(chunking)。

专用参数

取样参数影响 token 产生过程。BazaarLink 会将支援的参数传递给上游 provider;不支援的参数会被静默忽略。

取样参数

纯转发——没有本地预设值
这些参数会原封不动转发给上游 provider——BazaarLink 不会注入或强制任何预设值。下方的“预设”是指该字段省略时 provider 自己的行为,不是 BazaarLink 的保证。
temperature
number
取样温度 0–2。越高越随机。预设:1
top_p
number
核取样概率质量。预设:1
top_k
integer
限制候选 token 数量。0 表示停用(考虑全部)。预设:0
frequency_penalty
number
惩罚重复的 token。范围:[-2, 2]。预设:0
presence_penalty
number
基于存在情况惩罚 token。范围:[-2, 2]。预设:0
repetition_penalty
number
降低输入中 token 重复的机率。范围:(0, 2]。预设:1
min_p
number
相对最高机率 token 的最低入选机率。范围:[0, 1]。预设:0
top_a
number
基于最高机率 token 的动态 Top-P。范围:[0, 1]。预设:0
seed
integer
整数随机种子,用于确定性取样。部分模型不保证
max_tokens
integer
要生成的最大 token 数量
n
integer
产生的完成数量。预设:1
logit_bias
object
将 token ID 映射到偏差値 [-100, 100],在取样前加到机率。仅限 OpenAI 系列模型 —— 见下方说明。
logprobs
boolean
回传每个输出 token 的对数机率。仅限 OpenAI 系列模型 —— 见下方说明。
top_logprobs
integer
每个位置回传概率最高的 N 个候选 token(需配合 logprobs: true)。范围:0–20。仅限 OpenAI 系列模型 —— 见下方说明。
response_format
object
强制结构化 JSON 输出。请参阅结构化输出章节
structured_outputs
boolean
在支持的 provider 上要求严格符合 JSON schema 的输出。原样转发
reasoning
object
Provider 专属的 reasoning/thinking 设置。原样转发
reasoning_effort
string
OpenAI o 系列风格的 reasoning 强度:"low"、"medium" 或 "high"。原样转发
stop
string | string[]
停止序列 — 遇到时停止生成
tools
Tool[]
模型可以呼叫的工具(函式)列表
tool_choice
string | object
控制工具使用:"auto"、"none" 或指定工具
parallel_tool_calls
boolean
启用并行工具呼叫功能。预设:true。仅限 OpenAI 系列模型 —— 见下方说明。

BazaarLink 专属参数

transforms
string[]
要套用的讯息转换,例如 ["middle-out"]。省略则在 ≤8k context 模型自动套用
models
string[]
备用模型清单——BazaarLink 依序尝试,主模型失败时自动切换
route
string
进阶路由兼容字段——大多数用户不需要。要用 fallback 请用 "models"。
provider
object
进阶路由偏好——大多数用户不需要。

信用额度

查询当前信用额度余额与累积 API 使用量。

GET/api/v1/credits
Auth
需要 Bearer token(标准 API key sk-bl-...)。

范例请求

curl https://bazaarlink.ai/api/v1/credits \
  -H "Authorization: Bearer sk-bl-YOUR_KEY"

回应

{
  "data": {
    "total_credits": 100.00,
    "total_usage": 12.34
  }
}

错误:401(密钥无效或缺失)、403(账户已停权)。

生成详细资料

依 generation ID 查询单次完成请求的详细统计数据(ID 来自 chat/completions 响应的 id,或流式的 x-bz-gen-id header)。

GET/api/v1/generation?id=<generation-id>
Auth
需要 Bearer token(标准 API key)。必填 query 参数:id。

范例请求

curl "https://bazaarlink.ai/api/v1/generation?id=gen_abc123" \
  -H "Authorization: Bearer sk-bl-YOUR_KEY"

回应

{
  "data": {
    "id": "gen_xyz...",
    "model": "openai/gpt-4.1",
    "provider": "openai",
    "created_at": "2026-04-20T10:00:00.000Z",
    "app_name": "MyApp",
    "finish_reason": "stop",
    "status": 200,
    "duration_ms": 1234,
    "first_token_ms": 234,
    "throughput": 45.6,
    "usage": {
      "prompt_tokens": 100,
      "completion_tokens": 200,
      "total_tokens": 300,
      "prompt_tokens_details": { "cached_tokens": 50 },
      "completion_tokens_details": { "reasoning_tokens": 30 },
      "cost": 0.00123
    },
    "cost_breakdown": {
      "subtotal": 0.00123,
      "cache_discount": 0.00015,
      "total": 0.00108
    }
  }
}

错误:400(缺少 id)、401(auth)、404(找不到该 generation)。

API 密钥信息

查询当前 API key 的 rate limit 层级与累计使用量(响应格式与业界惯用的密钥查询 API 兼容)。

GET/api/v1/key
Auth
需要 Bearer token(标准 API key)。

回应

{
  "data": {
    "label": "Production Key",
    "limit": null,
    "limit_remaining": 100.00,
    "limit_reset": null,
    "expires_at": null,
    "is_free_tier": false,
    "is_management_key": false,
    "is_provisioning_key": false,
    "usage": 12.34,
    "usage_daily": 0.12,
    "usage_weekly": 0.45,
    "usage_monthly": 1.23,
    "requests": 1234,
    "requests_daily": 10,
    "requests_weekly": 50,
    "requests_monthly": 200,
    "rate_limit": { "requests": 600, "interval": "1m", "note": "Paid-tier rate limit." }
  }
}
Note
当信用余额低于 $10 时,is_free_tier 为 true。统计区间以 UTC 为准:daily = 当日、weekly = 周一至周日、monthly = 当月 1 日至月底。若该 API key 设置了个别用量上限(通过创建/更新 key 时的 limit 参数),limit / limit_remaining / limit_reset 会反映该上限与对应周期的已用量;未设置时 limit 为 null,limit_remaining 回退为账号信用余额。expires_at 为该 key 的到期时间(未设置则为 null)。is_management_key 与 is_provisioning_key 目前是同一概念的别名,都表示这是一把管理密钥。
BYOK
BazaarLink 目前未提供「自带密钥」(BYOK)方案,因此本端点不会返回 byok_usage 相关字段。

错误:401(auth)、404(找不到用户,极少发生)。

Agent 自助注册

供 AI agent(机器人、自主系统)自行注册,返回含试用额度的 API key 与用于升级的 claim token。

POST/api/v1/agents/register
Rate Limit
免认证,但每个 IP 每 24 小时限 1 次请求。

请求内文

name必填
string
Agent 名称(非空、trim 后长度上限 100)。
description
string
选填的 agent 说明。
referral_code
string
选填的推荐码。

范例请求

curl -X POST https://bazaarlink.ai/api/v1/agents/register \
  -H "content-type: application/json" \
  -d '{
    "name": "My Agent",
    "description": "Autonomous research bot"
  }'

回应

{
  "api_key": "sk-bl-xxxxx...",
  "credits": 0.10,
  "credits_usd": "$0.1000",
  "claim_token": "abc...xyz",
  "claim_expires": "2026-04-27T10:00:00.000Z",
  "upgrade_url": "https://bazaarlink.ai/claim?token=...",
  "referral_code": "aBcDeFgH",
  "free_model": "auto:free",
  "message": "Welcome to BazaarLink!...",
  "referral_message": "Share referral link:...",
  "base_url": "https://bazaarlink.ai/api/v1",
  "docs": "https://bazaarlink.ai/llms.txt"
}

错误:400(body 无效或缺少 name)、429(rate limit,1/IP/24h)、500(内部错误)。

错误代码

错误回应格式

模型推理端点会返回 OpenAI 兼容的错误 envelope。部分特殊端点可能省略 type,或依错误路径使用不同值;程序判断请使用 HTTP 状态与 error.code,不要解析 message 文本。

{
  "error": {
    "message": "Insufficient credits. Please top up to continue.",
    "type": "invalid_request_error",
    "code": "insufficient_credits"
  }
}

HTTP 状态与 error.code

串流开始前,HTTP 状态代表错误大类;error.code 可能是相同的数字,也可能是代表特定处理方式的稳定字符串。若有字符串代码应优先判断,否则使用 HTTP 状态;error.message 仅供人阅读。

代码
名称
说明
400请求无效请求格式错误、messages 阵列为空,或缺少必填栏位
401未授权API 密钥遗失、无效或已停用
402需要付款帐户点数不足、单一密钥花费上限已达,或每周 / 每月预算上限已达
403禁止存取帐户已停用或没有此操作的权限
404找不到资源指定的模型、生成任务、密钥或其他资源不存在
409状态冲突资源尚未进入必要状态,例如视频任务尚未完成
410资源已移除指定模型已退役,必须改用其他模型
413请求体过大请求 body 超过 10 MB;请缩小内容或分拆请求
416范围无法满足生成视频内容所要求的 byte range 无效
429请求过多已超过速率限制;请查看 Retry-After 标头后再重试
500伺服器错误BazaarLink 内部错误
502闸道错误所有上游提供者均失败;已尝试故障转移
503服务不可用此模型没有设定上游提供者;请联络管理员
504闸道超时上游连接或串流停滞并超过等待时间

机器可读的账务代码

同样是 402,也可能代表不同的账务控制。请依下列稳定代码显示正确的处理方式。

代码
说明
budget_cap_reached已达到每周或每月的提醒型预算上限;提高或重设预算上限。
credit_limit_exceeded月结组织已用尽硬性信用额度;请联系账务人员。
insufficient_credits预付用户或组织无法保留足够余额;请先充值。
spend_limit_exceededAPI 密钥已达到每日、每周或每月花费上限。

详细错误代码

API 请求失败时,error.code 会告诉你更具体的原因。即使两个错误都是 HTTP 400,处理方式也可能不同:例如 unknown_model 表示模型名称有误,image_too_large 则表示图片太大。请根据下表查找原因和对应的处理方向。

模型与端点
模型查找、生命周期、定价、模态和端点兼容性错误。
代码
HTTP 状态
unknown_model400
invalid_model_id400
model_not_found404
model_retired410
model_endpoint_mismatch400
embedding_on_chat_endpoint400
model_not_priced400
invalid_modality_for_model400
请求与安全
参数、上下文、工具、结构定义和内容安全拒绝。
代码
HTTP 状态
missing_required_field400
unsupported_param400
max_tokens_invalid400
context_too_long400
tool_use_unsupported400
malformed_tool_messages400
invalid_response_format_schema400
invalid_tools_definition400
content_moderation403
content_filter403
unknown_4xx400
图片生成与编辑
图片输入、multipart 编辑、输出和图片管线错误。
代码
HTTP 状态
invalid_image_url400
input_images_not_supported400
invalid_content_type400
mask_not_supported400
unsupported_response_format400
missing_prompt400
missing_image400
too_many_images400
invalid_image_type400
image_too_large400
invalid_n400
pipeline_error502
no_images502
上游路由
安全处理后的供应商连接、认证、限流和可用性错误。
代码
HTTP 状态
upstream_unreachable502
upstream_auth_failed502
upstream_rate_limited429
upstream_unavailable502/503

速率限制、预算与紧急刹车

这些控制可能拒绝原本有效的请求。它们与供应商故障不同,需要不同的恢复操作。

控制机制
HTTP 状态
识别方式
请求速率限制429数字 code 429;遵循 Retry-After 和 X-RateLimit-* 标头。
限流惩罚封锁429数字 code 429、临时限制消息和 Retry-After。
全局支出紧急刹车503数字 code 503、全局支出上限消息,以及 30 或 300 秒的 Retry-After。
组织/团队/成员/用户支出刹车429数字 code 429,消息会指出 spend circuit breaker 和受影响范围。
计费与预算控制402使用上方列出的稳定计费字符串代码。

兼容性提醒:速率限制与紧急刹车目前返回数字型 error.code。请勿假设尚未实现的字符串代码;请依据 HTTP 状态、Retry-After 和文档所述消息判断。

视频与媒体资源状态

视频验证通常返回数字 code 400;任务不存在为 404、模型退役为 410、视频内容尚未完成为 409、视频 byte range 无效为 416。重试前请先轮询至完成或修正 Range 标头。

重试策略

只有在不修改请求也可能恢复的错误才应重试。若有 Retry-After,请依指定秒数等待;否则使用带 jitter 的指数退避。限制重试次数,也不要同时叠加 SDK 自动重试与手动重试。

可退避重试
429、502、503、504。有 Retry-After 时必须优先遵守。生成类请求若遇到结果不明的网络中断,应先查询原任务,避免建立第二个任务。
修正后再重试
400、401、402、403、404、409、410、413、416。请先修正请求、凭证、余额、权限、资源状态或 Range 标头。

错误处理

import random
import time
from openai import OpenAI, APIStatusError

client = OpenAI(
    base_url="https://bazaarlink.ai/api/v1",
    api_key="sk-bl-YOUR_API_KEY",
    max_retries=0,  # Avoid double retries; this example handles them.
)

RETRYABLE = {429, 502, 503, 504}

for attempt in range(5):
    try:
        response = client.chat.completions.create(
            model="openai/gpt-4.1",
            messages=[{"role": "user", "content": "Hello!"}],
        )
        break
    except APIStatusError as error:
        if error.status_code not in RETRYABLE or attempt == 4:
            raise
        retry_after = error.response.headers.get("Retry-After")
        delay = (
            float(retry_after)
            if retry_after
            else min(8, 0.5 * (2 ** attempt)) + random.uniform(0, 0.25)
        )
        time.sleep(delay)

串流错误格式

在任何 token 串流之前发生的错误,会以标准 HTTP 错误回应(JSON body)回传。

串流一旦开始,HTTP 回应已经是 200。客户端必须解析每个 SSE data frame;只要出现顶层 error,或 choices[0].finish_reason === "error",就应视为失败且回应不完整。

串流中途失败时,BazaarLink 会发送最后一个 SSE 事件,内容为顶层 error 对象,接着是 data: [DONE]。部分上游原样转发的 chunk 则可能把错误放在 choice 上(choices[0].finish_reason === "error")— 两种都要处理。

// If the stream fails mid-flight, BazaarLink emits a final SSE event
// with a top-level "error" object, followed by data: [DONE]
data: {"error":{"message":"Upstream stream interrupted. The response is incomplete.","type":"upstream_error","code":502}}

data: [DONE]

// Chunks relayed verbatim from some upstreams may instead carry the error
// inline on the choice: choices[0].finish_reason === "error" with an
// "error" object ({ code, message }) on the choice — handle both shapes.
// Branch on error.code; error.type can vary by failure path.

版本管理

BazaarLink 只提供单一稳定的 API 路径 /api/v1 —— 没有按日期锁定的版本、也不需要管理版本 header。API 是持续演进,不是靠编号发布版本。

非破坏性变更

以下这些会在不事先预告的情况下上线:

  • 新增端点
  • 目录新增模型
  • 新增可选请求参数
  • 新增响应字段
  • 新增带可选属性的 schema
  • 新增响应状态/错误代码
用防御性写法实现客户端
请忽略您不认识的响应字段,也不要在遇到枚举类字段的未知值时直接失败 —— 随着目录与功能扩充,会持续新增新值。

破坏性变更

这些情况很少见,包括:

  • 删除或改名端点、参数、或响应字段
  • 改变字段类型
  • 把可选参数改成必填

就算真的发生,破坏性变更也只会影响特定端点,不会波及整个 /api/v1 —— 没有单一版本升级能一次弄坏所有对接。我们目前还没有发布正式、带 Breaking 标签的 changelog(见下方「掌握最新动态」)—— 若是对您的对接来说很关键的部分,建议先联系 Support 确认,不要依赖没有文档记录的行为。

下线政策

唯一该预期的常态性「破坏性」事件:个别模型会随上游供应商淘汰而下线。可通过 GET /api/v1/models 查询模型当前的状态。

GET https://bazaarlink.ai/api/v1/models
Authorization: Bearer sk-bl-YOUR_API_KEY

# A model within 30 days of its deprecation date shows in the catalog
# with an "EOL" badge on the Models page. After the effective date it's
# dropped from the catalog and calls return:
# 410 { "error": { "type": "model_not_available", "code": "model_retired" } }

掌握最新动态

我们目前还没有发布专属的 API changelog 或 RSS feed。现阶段请直接查看这个页面、通过 GET /api/v1/models 追踪模型状态,或若您有关键对接需要提前获知变更,可联系 Support。

客服
客服
您好!有什么可以协助?
请留下消息,我们会尽快回复。
API 参考文档|聊天、嵌入与模型路由