BazaarLinkBazaarLink
로그인
문서API 레퍼런스SDK 레퍼런스에이전트 사용법AI 스킬

API 레퍼런스

BazaarLink API 개요

BazaarLink는 모델과 제공업체 전반에서 통일된 OpenAI 호환 요청 및 응답 형식을 제공합니다. 한 번만 연동하면 애플리케이션을 다시 작성하지 않고 모델을 전환할 수 있습니다.

고객 라우팅 필드는 무시됩니다
provider(객체 전체), transforms, route, 최상위 service_tier 및 preset은 업스트림으로 보내기 전에 제거되며 업스트림이나 가격 등급을 선택할 수 없습니다. Chat Completions 및 Responses 엔드포인트에서는 models 배열을 로컬 대체 모델 목록으로 지원합니다. BazaarLink가 각 모델을 자체 라우팅으로 처리하고 해당 모델의 고객 가격을 적용하며, 목록은 업스트림으로 전달되지 않습니다. 고객이 지정한 :nitro, :floor, :exacto 접미사는 무시됩니다. :eco는 BazaarLink의 경제형 티어로 유지되며 내부적으로 BazaarLink :floor에 매핑됩니다. :free는 별도의 카탈로그 모델 변형입니다.
웹 검색 추가 비용
plugins, :online 또는 web_search_options로 요청하는 웹 검색 동작은 유지되지만 업스트림 추가 요금이 발생할 수 있습니다. 요금은 요청에 사용된 키, 즉 BazaarLink 플랫폼 키 또는 고객 BYOK 키에 청구됩니다.

OpenAPI 사양

전체 BazaarLink API는 OpenAPI 사양으로 문서화되어 있으며 YAML 및 JSON 형식으로 제공됩니다:

Swagger UI, Postman 또는 OpenAPI 호환 코드 생성기에서 이 사양을 사용해 API를 탐색하거나 클라이언트 라이브러리를 생성할 수 있습니다.

요청

채팅 완성 요청 형식

채팅 완성 요청 본문은 다음 엔드포인트로 전송됩니다:

POST/v1/chat/completions

지원되는 전체 필드 목록은 매개변수。

요청 스키마
// Definitions of subtypes are below
type Request = {
  // Required by BazaarLink Chat Completions
  model: string;                    // Use an id or alias from GET /v1/models
  messages: Message[];             // Must contain at least one message

  // Generation
  stream?: boolean;
  temperature?: number;
  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;
  presence_penalty?: number;
  repetition_penalty?: number;
  min_p?: number;
  top_a?: number;
  // Sampling values are forwarded without range validation; models may clamp or ignore them.

  // 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";
  include_reasoning?: boolean;
  reasoning?: ReasoningConfig;
  thinking?: ThinkingConfig;
  enable_thinking?: boolean;

};

// 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;
};

구조화된 출력

모델이 스키마에 맞는 유효한 JSON을 반환하도록 강제합니다. 모델 출력을 프로그래밍 방식으로 파싱하는 신뢰할 수 있는 애플리케이션 구축에 필수적입니다.

  • json_object — 기본 JSON 모드로, 모델이 유효한 JSON을 반환합니다.
  • json_schema — 엄격한 스키마 모드로, 출력이 제공된 JSON Schema와 일치해야 합니다.

플러그인

BazaarLink는 plugins 배열을 선택된 업스트림 경로로 전달합니다. 사용 가능 여부는 모델과 제공업체에 따라 다르며 :online 모델 변형은 web 플러그인도 활성화합니다.

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

선택적 헤더

요청 헤더에서 애플리케이션을 식별하여 사용량 추적, 대시보드 가시성, 세분화된 분석을 활성화합니다.

TypeScript
await fetch("https://api.bazaarlink.ai/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-4o",
    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;
  message: {
    role: "assistant";
    content: string | null;
    tool_calls?: ToolCall[];
    reasoning?: string;                                      // thinking text: when the request asked for it, or by default for the models listed in the reasoning docs section
    reasoning_details?: Array<{ type: string; text?: string }>;
  };
};

type StreamingChoice = {
  index: number;
  finish_reason: string | null;
  delta: {
    role?: string;
    content?: string | null;
    tool_calls?: ToolCall[];
    reasoning?: string;
    reasoning_details?: Array<{ type: string; text?: string }>;
  };
};

종료 이유

finish_reason은 stop, length, tool_calls, content_filter, error 등 BazaarLink 표준화 값을 사용합니다.

JSON
{
  "finish_reason": "stop"
}

비용 및 통계 조회

응답 id 또는 x-request-id 헤더의 불투명한 BazaarLink 요청 ID로 GET /v1/generation을 호출하세요. 비스트리밍 응답에도 같은 ID가 x-generation-id로 포함됩니다. 통계가 표시되기까지 몇 초 걸릴 수 있으므로 404는 잠시 재시도하세요.

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

에이전트 등록

활성화하면 에이전트가 미결제 또는 x402 결제 등록 경로로 계정을 만들 수 있습니다.

POSThttps://api.bazaarlink.ai/api/v1/agents/register

미결제 등록은 name, 선택적 description, 선택적 referral_code를 받습니다. 201 응답에는 API 키, 크레딧, 7일 claim token과 만료 시간, 업그레이드 URL, 추천 코드, free_model auto:free, 기본 URL과 문서 링크가 포함됩니다. 기존 무료 모델 메커니즘을 사용하며, 무료 웹 검색은 인증된 이메일이 필요하므로 미결제 에이전트는 사용할 수 없습니다.

POSThttps://api.bazaarlink.ai/api/v1/agents/register/x402

유료 등록은 scheme exact, network eip155:196, asset USD-T0, payTo가 포함된 HTTP 402 요구사항으로 시작합니다. X-PAYMENT 헤더와 함께 다시 보내면 같은 등록 필드와 payment { txHash, network, amountUsd }를 받습니다. 유료 에이전트는 일반 유료 계정 규칙을 따르며 기존 계정은 /api/x402/topup으로 충전할 수 있습니다.

사람은 7일 token 유효 기간 동안 /claim에서 미결제 에이전트를 인수할 수 있습니다. 등록은 IP당 24시간에 한 번이며 클라우드 제공업체 한도도 적용됩니다. 거부된 요청은 Retry-After가 있는 429를 반환합니다.

POSThttps://api.bazaarlink.ai/api/x402/topup

채팅 완성

기본 엔드포인트. OpenAI 채팅 완성 API와 호환됩니다.

POST/v1/chat/completions

요청 바디

model필수
string
GET /v1/models에 표시된 id 또는 alias를 사용하세요(예: "claude-sonnet-4.6" 또는 "anthropic/claude-sonnet-4.6").
messages필수
Message[]
role과 content를 가진 메시지 객체 배열
stream
boolean
true이면 Server-Sent Events 스트림을 반환합니다. 기본값: false
temperature
number
샘플링 값은 범위 검증 없이 전달됩니다. 모델이 지원 범위 밖의 값을 제한하거나 무시할 수 있습니다.
max_tokens
integer
생성할 최대 토큰 수
max_completion_tokens
integer
max_tokens의 별칭 (OpenAI o-시리즈 호환). 둘 다 허용; 제공된 것이 적용됨
top_p
number
핵 샘플링 확률 질량. 기본값: 1
top_k
integer
샘플링 값은 범위 검증 없이 전달됩니다. 모델이 지원 범위 밖의 값을 제한하거나 무시할 수 있습니다.
frequency_penalty
number
반복 토큰 패널티. 범위: [-2, 2]. 기본값: 0
presence_penalty
number
존재 기반 토큰 패널티. 범위: [-2, 2]. 기본값: 0
repetition_penalty
number
입력에서 토큰 반복 감소. 범위: (0, 2]. 기본값: 1
min_p
number
상위 토큰 대비 최소 확률. 범위: [0, 1]. 기본값: 0
top_a
number
최고 확률 토큰 기반 동적 top-P. 범위: [0, 1]. 기본값: 0
seed
integer
결정적 샘플링을 위한 정수 시드. 모든 모델에서 보장되지 않음
n
integer
생성할 완성 수. 기본값: 1
user
string
모니터링 및 남용 감지를 위한 최종 사용자 식별자. 과금에 영향 없음. OpenAI 계열 모델에만 적용 — 아래 참고 사항 확인.
stop
string | string[]
중지 시퀀스 — 만나면 생성 중단
logit_bias
object
토큰 ID를 바이어스 값 [-100, 100]에 매핑하여 샘플링 전 추가. OpenAI 계열 모델에만 적용 — 아래 참고 사항 확인.
logprobs
boolean
각 출력 토큰의 로그 확률 반환. OpenAI 계열 모델에만 적용 — 아래 참고 사항 확인.
top_logprobs
integer
위치당 반환할 최고 확률 토큰 수 (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
지원하는 제공자에서 엄격한 JSON 스키마 준수 출력을 요청. 그대로 전달
reasoning
object
제공자별 reasoning/thinking 설정. 그대로 전달
reasoning_effort
string
OpenAI o-시리즈 스타일 reasoning 강도: "low", "medium", 또는 "high". 그대로 전달
include_reasoning
boolean
true이면 message.reasoning(스트리밍에서는 delta.reasoning)에 생각 내용을 반환하고, false이면 기본으로 생각하는 모델의 생각을 끕니다(추론 섹션 참조). 따라서 생각 비용이 청구되지 않습니다. reasoning_effort, reasoning, thinking 중 아무것도 보내지 않으면 그 모델들만 기본으로 생각하고 반환하며, 다른 모델은 요청했을 때만 반환합니다
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 an id or alias from GET /v1/models
  messages: Message[];             // Must contain at least one message

  // Generation
  stream?: boolean;
  temperature?: number;
  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;
  presence_penalty?: number;
  repetition_penalty?: number;
  min_p?: number;
  top_a?: number;
  // Sampling values are forwarded without range validation; models may clamp or ignore them.

  // 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";
  include_reasoning?: boolean;
  reasoning?: ReasoningConfig;
  thinking?: ThinkingConfig;
  enable_thinking?: boolean;

};

// 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;
};

예제 요청

curl https://api.bazaarlink.ai/v1/chat/completions \
  -H "Authorization: Bearer $BAZAARLINK_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "openai/gpt-4o",
    "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": "85e6f35c71a31f19-SJC",
  "object": "chat.completion",
  "created": 1740000000,
  "model": "openai/gpt-4o",
  "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는 표준화된 응답을 반환하고 업스트림 전용 필드를 제거합니다. usage.cost는 이 요청에 대해 고객에게 청구된 USD 금액입니다.

100초를 초과하는 긴 요청에는 stream:true 사용을 권장합니다. 비스트리밍 요청은 약 12초 후(기본값이며 배포 설정으로 조정 가능) 먼저 200을 반환하고 keepalive 공백을 보내기 시작합니다. 이후 오류가 발생하면 200 + error JSON으로 반환됩니다. keepalive는 JSON 본문 앞의 공백이며 표준 JSON 파서는 이를 무시합니다.

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

type NonStreamingChoice = {
  index: number;
  finish_reason: "stop" | "length" | "tool_calls" | "content_filter" | null;
  message: {
    role: "assistant";
    content: string | null;
    tool_calls?: ToolCall[];
    reasoning?: string;                                      // thinking text: when the request asked for it, or by default for the models listed in the reasoning docs section
    reasoning_details?: Array<{ type: string; text?: string }>;
  };
};

type StreamingChoice = {
  index: number;
  finish_reason: string | null;
  delta: {
    role?: string;
    content?: string | null;
    tool_calls?: ToolCall[];
    reasoning?: string;
    reasoning_details?: Array<{ type: string; text?: string }>;
  };
};

type ResponseUsage = {
  prompt_tokens: number;
  completion_tokens: number;
  total_tokens: number;
  cost: number;                      // USD amount charged to the customer for this request
  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 };
};

이미지 생성

DALL·E 및 GPT-4o 같은 모델을 사용하여 텍스트 프롬프트에서 이미지를 생성합니다. `modalities` 파라미터를 사용하여 채팅 완성 엔드포인트에서 이미지 출력을 요청합니다. 이미지 편집(기존 이미지 수정)은 POST /v1/images/edits를 사용합니다 —— OpenAI images.edit 호환이며, multipart/form-data로 소스 이미지를 업로드합니다. 편집 가능한 모델은 modality가 text+image->image입니다(예: qwen/qwen-image-3). 순수 생성 모델은 text->image입니다 —— 각 모델의 modality는 GET /v1/models에서 확인하세요.

Response format

/v1/images/generations는 기본적으로 OpenAI 호환 동기 JSON을 반환합니다(2026-07-25부터) — client.images.generate()가 래퍼 없이 바로 동작합니다. stream: true를 전달하면 SSE 이벤트 스트림으로 전환되어 생성 시간이 긴 모델의 진행 상황을 받을 수 있습니다.

20초를 넘는 비스트리밍 요청은 먼저 HTTP 200을 반환하고(이후 공백 문자로 연결을 유지), 나중에 발생한 실패는 "200 + 오류 본문"으로 반환됩니다. 최상위 `error` 객체를 확인하세요(`"object": "error"`와 `"http_status"`도 추가됩니다). 클라이언트의 읽기 타임아웃이 길다면(OpenAI SDK 기본값은 10분) `X-BazaarLink-Sync-Wait: 90`(정수 초, 1–90, 기본 20)을 보내 해당 시간 안의 실패에 대해 실제 상태 코드를 받을 수 있습니다. Python SDK는 `default_headers={"X-BazaarLink-Sync-Wait": "90"}`, Node SDK는 `defaultHeaders: { "X-BazaarLink-Sync-Wait": "90" }`를 사용합니다. Windows에서는 JSON을 UTF-8 파일로 저장해 `curl --data-binary @body.json`으로 보내세요. 콘솔에서 `-d` 뒤에 입력한 한글은 UTF-8이 아니어서 즉시 400 `invalid_utf8`로 거부됩니다.

A. /v1/chat/completions (네이티브, 권장)

POST/v1/chat/completions

The canonical streaming path. Recommended for any new integration.

curl -N https://api.bazaarlink.ai/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
  }'

이미지-투-이미지: content 배열에 image_url 파트를 포함하세요. 데이터 URI 또는 https 이미지 URL(http:// 는 거부됨)을 지원하며, 최대 8장, 데이터 URI당 약 10MB입니다. 이미지를 포함한 메시지에는 text 파트(편집 지시)도 함께 있어야 합니다. 일부 모델은 image_config(예: {"strength": 0.7}, 0–1 — 낮을수록 원본 이미지에 가까움)를 추가로 지원하며, 그대로 업스트림에 전달됩니다.

curl -N https://api.bazaarlink.ai/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/v1/images/edits

OpenAI SDK의 client.images.edit()가 그대로 동작합니다(multipart 업로드, data: [{ url }] 을 반환하는 동기 JSON 응답). 제한은 이미지-투-이미지와 동일: 최대 8장, 각 10MB. mask와 response_format=b64_json은 아직 지원되지 않습니다.

curl https://api.bazaarlink.ai/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/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://api.bazaarlink.ai/v1/images/generations \
  -H "Authorization: Bearer $BL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "openai/gpt-image-1",
    "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://api.bazaarlink.ai/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

SSE 주석 줄과 알 수 없거나 ping인 이벤트는 무시하고 문서화된 image, usage, done 이벤트를 처리하세요.

: keep-alive

event: image
data: {"index": 0, "url": "https://api.bazaarlink.ai/v1/images/proxy/<token>"}

event: image-cached     # bazaarlink Redis-backed proxy URL (1 hr TTL)
data: {"index": 0, "url": "https://api.bazaarlink.ai/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)

비디오 생성

비동기 3단계 플로우(submit → poll → content)입니다. 비디오 생성은 30초~5분이 걸려 chat-completions의 동기 요청/응답 방식에 맞지 않습니다 — 그래서 BazaarLink는 비디오를 전용 /v1/videos 경로로 분리하고 job-id 패턴을 사용합니다: submit으로 vjob_* ID 수신 → 상태 poll → 완료 후 bytes fetch. video model을 /chat/completions 또는 /images/generations로 호출하면 400(code: wrong_endpoint_for_video)이 반환됩니다. 비용은 completed 시점에 실제 usage.cost로 정산됩니다.

동영상 작업 유형

하나의 엔드포인트가 여러 작업을 처리합니다. 실제로 어떤 작업이 실행되는지는 전송하는 필드로 결정됩니다 —— 하나의 모델로 이미지-투-비디오, 키프레임, 이어 붙이기를 모두 할 수 있습니다. 모든 모델이 모든 작업을 지원하지는 않으며, 미지원 요청은 400을 반환합니다.

텍스트→동영상
prompt
텍스트 프롬프트만으로 생성하며, 입력 미디어가 필요 없습니다.
이미지→동영상
frame_images: [ first frame ]
이미지 자체가 화면입니다. 첫 프레임이 되어 움직이며 원본에 충실합니다. 예: 고양이 사진 → 같은 장면에서 그 고양이가 고개를 돌립니다.
키프레임(첫+마지막)
frame_images: [ first, last ]
시작 이미지와 끝 이미지를 주면 모델이 그 사이의 움직임을 보간합니다.
이어 붙이기
input_video
기존 클립을 연장합니다. 요청한 duration은 원본 동영상 길이보다 커야 합니다.
참조→동영상
input_references: [ images ]
이미지는 프레임이 아니라 '참조'입니다. 모델은 피사체/스타일을 유지하면서 완전히 새로운 장면을 생성합니다. 예: 고양이 사진 + "숲에서 춤추기" → 고양이의 모습은 유지되지만 장면과 움직임은 새로운 영상(참조 1~9장). 이미지→동영상과의 차이: i2v는 원본 이미지에 충실하고, r2v는 피사체를 새 영상으로 다시 연출합니다.
동영상 편집
input_video + prompt
기존 동영상을 편집합니다 — 장면, 스타일, 움직임 변경. 입력 동영상 초 + 출력 초로 과금됩니다.

1. 작업 제출 (즉시 vjob_xxx 반환)

POST/v1/videos
model필수
string
모델 ID, 예: bytedance/seedance-2.0
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 URL — HTTPS만 가능, SSRF 검사 포함. v1에는 서명이 없으며, 힌트로 취급하고 GET /videos/{id}로 확인하세요.
curl https://api.bazaarlink.ai/v1/videos \
  -H "Authorization: Bearer $BL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "bytedance/seedance-2.0",
    "prompt": "a bird flying over mountains",
    "duration": 3,
    "resolution": "720p",
    "generate_audio": false
  }'
# → 202 { "id": "vjob_xxx", "status": "pending" }
Note
제출 시 최악의 경우 추정액을 기준으로 크레딧을 예약합니다. 작업 완료 후 usage.cost는 이 요청에 대해 고객에게 청구된 USD 금액입니다.

2. 상태 폴링

GET/v1/videos/{id}
curl -H "Authorization: Bearer $BL_API_KEY" \
  https://api.bazaarlink.ai/v1/videos/vjob_xxx
Note
각 GET 요청은 8초 이상 간격을 두어야 실제로 업스트림에 도달합니다 (레이트 리밋 방지)
Note
status=failed인 경우 reserve 금액 전액이 사용자에게 환불됩니다.

3. 비디오 콘텐츠 가져오기 (MP4)

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

알아두면 좋은 점

  • 허용 해상도는 모델마다 다릅니다 —— 미지원 값을 보내면 지원 값을 나열한 400을 반환합니다.
  • 입력 이미지/동영상은 공개 URL에서 접근 가능해야 합니다. 핫링크 보호된 호스트(일부 wiki 등)는 실패합니다.
  • 입력 미디어는 업스트림 콘텐츠 검열을 거치며 가끔 거부될 수 있습니다.
  • 이어 붙이기의 경우 요청한 duration이 원본 동영상 길이를 초과해야 합니다.
  • 출력 화면 비율은 입력 이미지를 따릅니다 —— 정사각형 이미지는 정사각형 동영상이 됩니다.
  • 동영상 편집은 입력 동영상의 초와 생성된 출력의 초로 과금됩니다.
  • 편집/이어 붙이기의 input_video는 공개 URL이어야 합니다. 여기서 생성한 동영상은 API 키 뒤에서 제공되므로 업스트림이 가져올 수 없습니다 —— 소스 동영상을 공개적으로 접근 가능한 URL에 호스팅하세요.
  • 웹훅 페이로드는 서명되지 않습니다 — 조치 전에 GET /videos/{id}로 상태/금액을 확인하세요. 거기의 unsigned_urls는 절대 경로입니다(폴링 응답의 상대 경로와 다름).

지원되는 비디오 모델

Model IDModalityTasks
minimax/hailuo-3-maxtext+image->videot2v, i2v
google/veo-3.1text+image->videot2v, i2v
bytedance/seedance-2.5text+image+audio+video->video—
x-ai/grok-imagine-video-1.5-litetext+image->videot2v, i2v
bytedance/seedance-2.0text+image+audio+video->videot2v, i2v
bytedance/seedance-1-5-protext+image->videot2v, i2v
bytedance/seedance-2.0-fasttext+image+audio+video->videot2v, i2v

음성 합성

/v1/models?output_modalities=speech의 모델 ID로 텍스트를 음성으로 변환합니다. 모델 페이지의 백만 문자당 가격으로 청구합니다. 전체 오디오를 버퍼링한 뒤 바이너리로 반환하며, 구간별 스트리밍은 지원하지 않습니다. provider, transforms, route, service_tier, preset 같은 라우팅 제어 필드는 무시됩니다.

POST/v1/audio/speech
curl https://api.bazaarlink.ai/v1/audio/speech \
  -H "$BAZAARLINK_AUTH_HEADER" \
  -H "Content-Type: application/json" \
  -d '{"model":"<speech-model-id>","input":"Hello","voice":"alloy","response_format":"mp3"}' \
  --output speech.mp3

# Voice settings (elevenlabs/* models; the X-Voice-Settings response header says applied or ignored)
curl -D - https://api.bazaarlink.ai/v1/audio/speech \
  -H "$BAZAARLINK_AUTH_HEADER" \
  -H "Content-Type: application/json" \
  -d '{"model":"elevenlabs/eleven-v4","input":"Hello","voice":"george","stability":0.4,"similarity_boost":0.8,"style":0.2,"use_speaker_boost":true,"language_code":"en","audio_effects":{"distance":0.3}}' \
  --output speech.mp3

음성 전사

multipart/form-data의 model, file 또는 JSON model, input_audio:{data,format} (원시 base64)를 보냅니다. 형식: wav, mp3, mp4, m4a, ogg, flac, webm, aac. 오디오 최대 25 MiB, 요청 본문 50 MiB. audio.transcription_max_seconds_by_model이 모델별 제한을 정하며, 없으면 audio.transcription_max_seconds와 기본 60초가 순서대로 적용됩니다. 초과한 오디오는 처리 전에 413 audio_too_long으로 거부되고 요금이 부과되지 않습니다. response_format은 json 또는 verbose_json; timestamp_granularities word/segment는 verbose_json이 필요합니다. stream 미지원 (400 unsupported_parameter), 크기 초과: 413 audio_too_large. provider는 무시됩니다. 데이터베이스 가격으로 usage.seconds 또는 입력/출력 token에 과금하며 분당 가격은 초당 가격의 60배입니다. usage.cost는 USD 고객 청구액입니다.

POST/v1/audio/transcriptions
curl https://api.bazaarlink.ai/v1/audio/transcriptions \
  -H "$BAZAARLINK_AUTH_HEADER" \
  -F model="<transcription-model-id>" \
  -F file=@audio.wav \
  -F response_format=json

curl https://api.bazaarlink.ai/v1/audio/transcriptions \
  -H "$BAZAARLINK_AUTH_HEADER" \
  -H "Content-Type: application/json" \
  -d '{"model":"<transcription-model-id>","input_audio":{"data":"<raw-base64-audio>","format":"wav"},"response_format":"verbose_json","timestamp_granularities":["word","segment"]}'

문서 재정렬

query와 documents로 관련성 순의 index와 relevance_score를 받습니다. 청구 단위는 search이며 모델 페이지 가격에 usage.search_units를 곱하고 문서 수로 청구하지 않습니다. 스트리밍(stream)은 지원하지 않습니다.

POST/v1/rerank
curl https://api.bazaarlink.ai/v1/rerank \
  -H "$BAZAARLINK_AUTH_HEADER" \
  -H "Content-Type: application/json" \
  -d '{"model":"your-rerank-model-id","query":"capital of France","documents":["Paris is the capital of France.","Berlin is in Germany."],"top_n":1}'
POST/v1/chat/completions

/v1/chat/completions에 audio 또는 input_audio와 오디오 지원 모델을 사용합니다. 보고된 텍스트와 오디오 토큰 총량에 설정된 입력 및 출력 단가를 동일하게 적용합니다.

curl https://api.bazaarlink.ai/v1/chat/completions \
  -H "$BAZAARLINK_AUTH_HEADER" \
  -H "Content-Type: application/json" \
  -d '{"model":"<audio-chat-model-id>","messages":[{"role":"user","content":"Say hi."}],"stream":true,"modalities":["text","audio"],"audio":{"voice":"alloy","format":"pcm16"},"max_tokens":32}'

음성 합성(TTS) 안내

POST /v1/audio/speech는 OpenAI-compatible 형식입니다. JSON을 보내면 오디오 파일을 바이너리로 받습니다. ElevenLabs 계열에는 elevenlabs/eleven-v4, eleven-v4-turbo, eleven-v3, eleven-v3-conversational, eleven-multilingual-v2, eleven-flash-v2.5, eleven-flash-v2, eleven-turbo-v2.5, eleven-turbo-v2가 있습니다. 최신 목록은 GET /v1/models?output_modalities=speech에서 확인하세요. GET /v1/models는 기본적으로 텍스트 모델만 반환하므로 ?output_modalities=speech(또는 all)를 붙여 목록을 확인하세요.

POST/v1/audio/speech

매개변수

매개변수형식필수설명
modelstring예음성 모델 ID. 예: elevenlabs/eleven-flash-v2.5.
inputstring예합성할 텍스트: 요청당 최대 4,096자(elevenlabs/eleven-v4와 eleven-v4-turbo는 10,000자). 더 긴 텍스트는 여러 요청으로 나누세요.
voicestring예사용할 음성. 형식은 모델에 따라 다릅니다. 아래 음성 규칙을 확인하세요.
response_formatstring아니요mp3(기본) 또는 pcm. opus·aac·flac·wav는 API가 받지만 현재 ElevenLabs 모델이 400으로 거부합니다.
speednumber아니요말하기 속도 0.25~4.0. 모델에 따라 적용되지 않을 수 있습니다.
instructionsstring아니요음성 스타일 지시문. 모델에 따라 적용되지 않을 수 있습니다.
stabilitynumber아니요목소리 안정성(0–1, 기본 0.5). 낮을수록 표현이 풍부하고 높을수록 균일합니다. 요청이 당사의 직접 음성 경로로 처리되는 elevenlabs/* 모델에서 적용되며, 응답 헤더 X-Voice-Settings가 applied 또는 ignored를 알려 줍니다.
similarity_boostnumber아니요원래 목소리와의 유사도(0–1, 기본 0.75). Eleven v3에서는 사용되지 않습니다.
stylenumber아니요스타일 강조도(0–1, 기본 0). 0보다 크면 지연이 늘어납니다. Eleven v4에서는 사용되지 않습니다.
use_speaker_boostboolean아니요원래 화자와의 유사도를 높입니다(기본 true). 지연이 약간 늘어납니다.
clone_strengthnumber아니요클론 강도(0–1, 대부분 0 권장). Eleven v4용으로 학습한 본인의 전문 클론 음성(voice_…)에만 적용됩니다.
language_codestring아니요낭독 언어를 지정하는 두 글자 소문자 언어 코드(ISO 639-1, 예: ar, ja, en). multilingual-v2 모델에서는 사용되지 않습니다.
audio_effectsobject아니요선택적 오디오 효과 객체: filter_preset_id(필터, 예: phone, old_radio), environment_id(잔향 공간, 예: small_room, hall), background_noise_id(배경음, 예: cafe), distance(0–1), send_level(잔향량, 0–1), pan(−1…1). ID는 소문자, 숫자, 밑줄만 사용하며 추가 요금은 없습니다. 잔향 또는 0이 아닌 pan은 스테레오로 출력되어 pcm 출력과 함께 쓸 수 없습니다.

위의 음성 설정 7개는 모두 선택 사항이며, 보내지 않으면 아무것도 바뀌지 않습니다. 범위를 벗어난 값은 400을 반환하며 전송도 과금도 되지 않습니다. 응답 헤더 X-Voice-Settings는 설정이 사용되었는지 알려 줍니다: applied = 사용됨; ignored = 예비 경로가 응답하여 설정이 사용되지 않았습니다(오디오는 정상적으로 생성됩니다); 헤더 없음 = 음성 설정을 보내지 않았습니다. 예: stability 0은 더 표현력 있게, 1은 더 고르게 읽습니다.

음성 규칙

ElevenLabs 모델(elevenlabs/…)에는 다음 음성 이름(대소문자 무관) 중 하나를 넣으세요: george, sarah, adam, alice, bella, bill, brian, callum, charlie, chris, daniel, eric, harry, jessica, laura, liam, lily, matilda, river, roger, will. ElevenLabs 모델은 voice를 생략할 수 있습니다(기본 george). 그 외 값은 400 invalid_voice를 반환합니다. 내 사용자 지정 음성(voice_…)은 아래 ‘사용자 지정 음성’ 섹션을 참조하세요.

alloy, echo, nova 같은 OpenAI-style 음성 이름은 해당 이름을 나열한 모델에서만 작동합니다. 모델 페이지에서 지원 음성을 확인하세요.

사용자 지정 음성(복제)은 단계적으로 공개 중입니다. 아래 ‘사용자 지정 음성’ 섹션(POST /v1/voices)을 참조하세요. 계정에서 활성화되기 전에는 위의 21개 프리셋 이름이나 공개 음성 ID를 사용하세요.

ElevenLabs 모델에 alloy를 보내면 실패합니다
ElevenLabs 모델에 voice ID도 지원 이름도 아닌 값(예: alloy, Rachel)을 보내면 400 invalid_voice를 반환하며 메시지에 허용되는 이름이 나열됩니다. 실패한 요청은 과금되지 않습니다.

기본 제공 음성 목록

voice에는 아래 표의 음성 이름(소문자)을 지정할 수 있습니다. 각 음성에는 짧은 미리듣기 클립이 있으며, GET /api/v1/audio/voices로 전체 목록(성별, 연령대, 억양, 스타일, 미리듣기 URL)을 가져올 수 있습니다.

?lang=(en, zh-TW, zh-CN, 기본값은 Accept-Language)은 description의 언어만 정합니다. 미리듣기 URL은 바뀌지 않습니다: preview_urls.en(preview_url과 동일)은 영어, preview_urls.zh(preview_url_zh와 동일)는 중국어 클립입니다.

음성설명미리듣기
georgeMale, middle-aged, British accent. Mature and steady, suited to narration and storytelling.
sarahFemale, young adult, American accent. Professional and clear, suited to broadcast-style reading.
adamMale, middle-aged, American accent. Everyday and approachable, suited to short social videos.
aliceFemale, middle-aged, British accent. Professional and informative, suited to explainers and teaching.
bellaFemale, middle-aged, American accent. Professional and informative, suited to explainers and teaching.
billMale, senior, American accent. Crisp and direct, suited to advertising voice-overs.
brianMale, middle-aged, American accent. Polished and refined, suited to social and brand content.
callumMale, middle-aged, American accent. Expressive, suited to characters and animation.
charlieMale, young adult, Australian accent. Energetic and lively, suited to conversation.
chrisMale, middle-aged, American accent. Relaxed and casual, suited to conversation.
danielMale, middle-aged, British accent. Formal and measured, suited to news-style and educational reading.
ericMale, middle-aged, American accent. Polished and warm, suited to conversation.
harryMale, young adult, American accent. Rough and gritty, suited to character voices.
jessicaFemale, young adult, American accent. Bright and cute, suited to conversation.
lauraFemale, young adult, American accent. Playful with attitude, suited to social content.
liamMale, young adult, American accent. Confident and upbeat, suited to social content.
lilyFemale, middle-aged, British accent. Confident and clear, suited to explainers and teaching.
matildaFemale, middle-aged, American accent. Upbeat and friendly, suited to explainers and teaching.
riverNeutral voice, middle-aged, American accent. Calm and even, suited to conversation.
rogerMale, middle-aged, American accent. Polished and confident, suited to conversation.
willMale, young adult, American accent. Laid-back and easygoing, suited to conversation.

감정·동작 태그(audio tags)

input 안에 대괄호로 태그를 직접 적습니다. 예: [laughs], [whispers], [excited], [sighs], [crying], [curious], [softly]. 태그는 입력한 그대로 모델에 전달되어 뒤따르는 말의 연기 방식을 정합니다. 본문이 한국어여도 태그는 영어로 유지하세요.

curl https://api.bazaarlink.ai/v1/audio/speech \
  -H "Authorization: Bearer $BAZAARLINK_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model":"elevenlabs/eleven-v3","input":"[laughs] That was actually funny. [whispers] Do not tell anyone.","voice":"george","response_format":"mp3"}' \
  --output audio-tags.mp3

elevenlabs/eleven-v3 와 elevenlabs/eleven-v4 계열이 지원합니다. 다른 음성 모델은 태그를 해석하지 않고 대괄호 안 글자를 그대로 읽을 수 있으니 먼저 짧은 문장으로 시험해 보세요.

태그도 input 글자 수에 포함되며 나머지 텍스트와 같은 방식으로 과금됩니다.

출력 형식

response_format을 생략하면 mp3(Content-Type audio/mpeg)가 기본입니다. pcm(audio/pcm, 원시 16-bit PCM)도 동작합니다. API는 opus, aac, flac, wav도 받지만 ElevenLabs 모델은 현재 400으로 거부합니다. 파일은 응답의 Content-Type 헤더에 따라 저장하세요.

요금

음성 합성은 입력 문자 수에 따라 청구됩니다. 문자당 가격은 /models의 모델 페이지와 GET /v1/models의 pricing.character에 있습니다. 모델 페이지에는 백만 문자 기준으로 표시됩니다.

예제

curl https://api.bazaarlink.ai/v1/audio/speech \
  -H "Authorization: Bearer $BAZAARLINK_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model":"elevenlabs/eleven-flash-v2.5","input":"Hello from BazaarLink.","voice":"george","response_format":"mp3"}' \
  --output speech.mp3

흔한 오류

상태원인 및 해결 방법
400잘못된 요청: model, input 또는 voice 누락; input 4,096자 초과; speed가 0.25–4.0 범위 밖; 지원되지 않는 response_format; Unknown voice; unknown_model(/models에서 ID 확인).
401API 키가 없거나 유효하지 않습니다. BazaarLink 키를 Authorization: Bearer로 보내세요.
402잔액이 부족합니다. 충전 후 다시 시도하세요.
403관리 키로는 모델을 호출할 수 없거나 계정이 정지되었습니다. 일반 API 키를 사용하세요.
429요청 제한에 도달했습니다. Retry-After 헤더에 따라 기다린 뒤 다시 시도하세요.
502모델 서비스가 일시적으로 중단되었거나 오디오 전송이 끊겼습니다. 다시 시도하세요. 실패한 요청에는 요금이 부과되지 않습니다.

전체 매개변수 참조: 음성 합성

음성 텍스트 변환 안내

POST /v1/audio/transcriptions는 OpenAI-compatible 형식입니다. multipart/form-data로 오디오를 업로드하거나 JSON으로 base64 input_audio를 보내면 텍스트를 받습니다. 모델에는 elevenlabs/scribe-v2와 elevenlabs/scribe-v2-medical이 있습니다. 최신 목록은 GET /v1/models?output_modalities=transcription에서 확인하세요. GET /v1/models는 기본적으로 텍스트 모델만 반환하므로 ?output_modalities=transcription(또는 all)를 붙여 목록을 확인하세요.

POST/v1/audio/transcriptions

매개변수

매개변수형식필수설명
modelstring예전사 모델 ID. 예: elevenlabs/scribe-v2.
filefile예오디오 파일(multipart). wav, mp3, mp4, m4a, ogg, flac, webm, aac 지원. 최대 25 MiB. JSON 클라이언트는 input_audio: {data: base64, format}을 대신 보낼 수 있습니다.
response_formatstring아니요json(기본값)은 {text}를 반환하고 verbose_json은 언어, 길이, segments/words를 추가합니다.
languagestring아니요en 또는 zh 같은 선택적 언어 힌트. 비워두면 자동 감지합니다.
promptstring아니요이름과 용어 인식을 돕는 선택적 문맥 텍스트. 모델에 따라 적용되지 않을 수 있습니다.
timestamp_granularities[]string[]아니요word 및/또는 segment. response_format=verbose_json에서만 적용되고 다른 형식에서는 무시됩니다. 단어 단위 타임스탬프는 아직 반환되지 않으며 segments는 반환됩니다.

출력 형식

response_format은 json 또는 verbose_json만 허용합니다(text, srt, vtt 미지원). stream은 지원되지 않습니다. 오디오 길이 제한은 모델별로 정해지며 기본값은 60초입니다. 초과하면 처리 전에 413 audio_too_long으로 거부되고 요금이 부과되지 않습니다. 긴 녹음은 나누세요.

요금

전사는 오디오 초 단위로 청구됩니다. 초당 가격은 /models의 모델 페이지와 GET /v1/models의 pricing.second에 있으며 분당 가격은 그 60배입니다. 응답의 usage는 청구 초를, usage.cost는 청구 금액을 보여 줍니다.

예제

curl https://api.bazaarlink.ai/v1/audio/transcriptions \
  -H "Authorization: Bearer $BAZAARLINK_API_KEY" \
  -F model="elevenlabs/scribe-v2" \
  -F file=@audio.mp3 \
  -F response_format=verbose_json \
  -F "timestamp_granularities[]=word"

흔한 오류

상태원인 및 해결 방법
400잘못된 요청: model 또는 file 누락, 빈 오디오, json/verbose_json 이외의 response_format, stream=true(unsupported_parameter), 또는 word/segment 이외의 timestamp_granularities.
401API 키가 없거나 유효하지 않습니다.
402잔액이 부족합니다. 충전 후 다시 시도하세요.
413audio_too_large: 디코딩한 오디오가 25 MiB를 초과합니다. audio_too_long: 모델별 길이 제한(기본 60초)을 초과한 오디오는 처리 전에 거부되며 요금이 부과되지 않습니다. 압축하거나 나누세요.
429요청 제한에 도달했습니다. Retry-After에 따라 기다린 뒤 다시 시도하세요.
502모델 서비스를 일시적으로 사용할 수 없거나 오디오 전송이 중단되었습니다. 다시 시도하세요. 실패한 요청에는 요금이 부과되지 않습니다.

전체 매개변수 참조: 음성 전사

사용자 지정 음성(음성 복제)

사용자 지정 음성(음성 복제)
신청 후 이용할 수 있습니다. 사용자 지정 음성은 계정별로 열어 드립니다. 고객 지원에 문의해 신청하세요. 계정에서 활성화되기 전에는 모든 /v1/voices 요청이 403 voice_cloning_not_enabled 를 반환합니다(기능이 전체적으로 꺼져 있으면 404 not_found). 이 페이지의 한도와 가격은 기본값이며 변경될 수 있습니다.

사용할 권리가 있는 목소리의 짧은 녹음을 업로드하면 우리 쪽 voice id(voice_…)를 받습니다. 이 id 를 POST /v1/audio/speech 의 voice 로 전달하세요. 음성은 만든 본인만 사용할 수 있습니다.

엔드포인트

POST/v1/voices

음성 만들기(multipart/form-data)

GET/v1/voices

내 음성 목록(limit 1–100, after 에 voice id 를 주면 다음 페이지)

GET/v1/voices/{id}

내 음성 하나 조회

DELETE/v1/voices/{id}

음성 삭제(즉시 적용)

POST/v1/voices/report

음성 신고(API 키 불필요)

음성 만들기: 필드

필드타입필수설명
namestring예음성 이름, 1–60자.
filesfile[]예해당 목소리의 녹음 파일 1~5개(mp3, wav, m4a, ogg, flac, webm).
consentboolean예true 여야 합니다: 이 목소리를 복제하고 사용할 권리가 있음을 확인합니다(‘동의’ 참조).
consent_statement_versionstring예확인한 동의 문구의 버전. 현재 "v1".
descriptionstring아니요선택, 최대 200자.
remove_background_noiseboolean아니요선택 불리언, 기본값 false. 복제 전에 샘플의 배경 소음을 제거합니다.

요청은 동기식입니다. 201 이 오면 음성을 바로 사용할 수 있습니다. Idempotency-Key 헤더(고유한 임의 문자열)를 보내고 재시도할 때 같은 값을 사용하세요. 그러면 재시도해도 두 번째 음성이 만들어지거나 청구되지 않습니다.

응답

201, id(voice_…), object("voice"), name, description, status("ready"), created_at(Unix 초), usage.cost_usd(청구된 생성 요금)를 포함합니다. 음성이 어떻게 만들어지는지에 대한 다른 정보는 외부로 나가지 않습니다.

GET /v1/voices 는 내 음성만 반환합니다: { "object": "list", "data": [ … ], "has_more": false }. 다른 사람의 voice id 는 존재하지 않는 id 와 똑같이 404 voice_not_found 를 반환합니다.

GET /v1/voices/{id} 는 음성 하나를 반환합니다(위와 같은 필드, usage 제외).

DELETE /v1/voices/{id} 는 { "id": "voice_…", "object": "voice", "deleted": true } 를 반환하며 즉시 적용됩니다. 해당 음성을 쓰는 음성 요청은 바로 실패합니다. 삭제는 무료이며 생성 요금은 환불되지 않습니다.

한도(기본값)

  • 1인당 최대 3개의 음성.
  • 음성마다 오디오 파일 1~5개, 파일당 최대 10 MB, 합계 25 MB. 형식: mp3, wav, m4a, ogg, flac, webm. 깨끗한 음성이 합계 30초~5분 정도면 가장 좋습니다.
  • 하루(UTC 기준) 최대 3회 생성할 수 있습니다.
  • 이메일 인증이 완료되고 잔액이 US$5 이상인 계정이 필요합니다.
  • 유명인을 흉내 내는 이름·설명, 공식 또는 직원 목소리처럼 들리는 이름·설명은 거부됩니다(invalid_voice_name).
  • 녹음은 음성을 만드는 데만 쓰이며 저장하지 않습니다. 음성 이름, 소유자, 동의 기록, 타임스탬프만 보관합니다.

가격

음성을 만들 때 1회성 요금이 부과됩니다(기본 US$1.00). 실제 청구 금액은 usage.cost_usd 로 반환되며, 음성이 성공적으로 만들어졌을 때만 청구됩니다. 음성 합성에서 사용자 지정 음성을 쓰는 요금은 해당 모델의 다른 음성과 같은 글자당 요금입니다. 삭제는 무료입니다.

동의

생성할 때마다 consent=true 와 consent_statement_version="v1" 를 보내야 합니다. 문구가 업데이트되면 400 consent_version_mismatch 가 반환되므로 새 버전으로 다시 확인하세요.

확인하게 되는 동의 문구 초안(최종 문구는 검토 중이며 변경될 수 있습니다):

I confirm that I own the voice in these recordings or have the written permission of the person whose voice it is, that this person is an adult and has agreed to have their voice cloned and synthesized, and that I will not use the voice to impersonate a real person, to deceive, to harass, or for political persuasion, fraud or any unlawful purpose. I understand the voice can be removed and my account suspended if I break these rules.

사용자 지정 음성 사용

voice id 를 POST /v1/audio/speech (voice=voice_…) 의 voice 로 전달하고 elevenlabs/* 계열 음성 모델과 함께 사용합니다. 입력 한도, 형식, 글자당 요금은 모델의 것입니다. 존재하지 않거나 삭제·차단되었거나 다른 사람의 voice id 는 400 invalid_voice 를 반환하며, 사용자 지정 음성은 다른 모델에서는 쓸 수 없습니다.

예제

curl https://api.bazaarlink.ai/v1/voices \
  -H "Authorization: Bearer $BAZAARLINK_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -F name="My narrator" \
  -F description="Warm and calm" \
  -F consent=true \
  -F consent_statement_version=v1 \
  -F files=@sample-1.mp3 \
  -F files=@sample-2.wav

curl "https://api.bazaarlink.ai/v1/voices?limit=20" \
  -H "Authorization: Bearer $BAZAARLINK_API_KEY"

curl -X DELETE https://api.bazaarlink.ai/v1/voices/voice_0123456789abcdef01234567 \
  -H "Authorization: Bearer $BAZAARLINK_API_KEY"

curl https://api.bazaarlink.ai/v1/audio/speech \
  -H "Authorization: Bearer $BAZAARLINK_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model":"elevenlabs/eleven-flash-v2.5","input":"Hello, this is my own voice.","voice":"voice_0123456789abcdef01234567","response_format":"mp3"}' \
  --output my-voice.mp3

음성 신고

허락 없이 나나 다른 사람을 흉내 내는 음성을 발견하면 신고하세요: POST /v1/voices/report(API 키 불필요), JSON 본문에 voice_id(voice_…) 또는 sample_url, reason(impersonation, fraud, harassment, minor, political, other), 선택 사항으로 details 와 contact(이메일). 항상 202 를 반환합니다. 신고는 검토하여 규정을 어긴 음성을 삭제하며, 계정이 정지될 수 있습니다.

curl https://api.bazaarlink.ai/v1/voices/report \
  -H "Content-Type: application/json" \
  -d '{"voice_id":"voice_0123456789abcdef01234567","reason":"impersonation","details":"...","contact":"me@example.com"}'

책임 있는 사용

유명인, 연예인, 정치인 또는 동의하지 않은 사람의 목소리를 복제하지 마세요. 복제한 목소리로 실제 본인과 대화한다고 믿게 하거나, 속이거나 괴롭히거나 정치적 설득·사기에 사용하는 것은 금지됩니다.

오류

상태코드의미
400bad_request잘못된 요청: multipart/form-data 가 아니거나, 오디오 파일이 없거나, description 이 너무 길거나, limit 이 1–100 범위를 벗어났습니다.
400consent_requiredconsent=true 가 없습니다.
400consent_version_mismatch동의 문구 버전이 오래되었습니다. 현재 버전으로 다시 확인하세요.
400invalid_voice_name이름이 비어 있거나 60자를 넘거나 허용되지 않습니다.
400too_many_files오디오 파일이 5개를 넘습니다.
401invalid_api_keyAPI 키가 없거나 유효하지 않습니다.
402insufficient_balance잔액 부족(생성 요금 또는 최소 잔액).
403email_unverified먼저 이메일을 인증하세요.
403voice_cloning_not_enabled계정에서 사용자 지정 음성이 아직 활성화되지 않았습니다. 고객 지원에 문의해 신청하세요.
403voice_cloning_disabled현재 이 서비스에서는 사용자 지정 음성이 활성화되어 있지 않습니다.
404voice_not_found해당 음성이 없습니다(또는 내 음성이 아닙니다).
404not_found찾을 수 없음. 기능이 계정에서 활성화되기 전의 모든 /v1/voices 요청을 포함합니다.
405method_not_allowed이 경로에서는 해당 메서드를 사용할 수 없습니다.
409duplicate_request같은 Idempotency-Key 가 아직 처리 중입니다. 잠시 후 다시 시도하세요.
413file_too_large파일이 10 MB 를 넘거나 전체 합계가 25 MB 를 넘습니다.
415unsupported_file_type지원하지 않는 오디오 형식입니다. mp3, wav, m4a, ogg, flac, webm 를 사용하세요.
422voice_rejected음성 제공자의 검사에서 샘플이 받아들여지지 않았습니다(예: 유명하거나 내장된 목소리, 알려진 AI 합성 목소리). 음성은 보관되지 않고 요금도 청구되지 않습니다. 본인 목소리의 선명한 녹음 또는 사용할 권리가 있는 목소리를 사용하세요.
429voice_create_rate_limited일일 생성 한도에 도달했습니다. 내일(UTC) 다시 시도하세요.
429voice_limit_reached사용자 지정 음성의 최대 개수에 도달했습니다.
502upstream_failed음성을 만들지 못했습니다. 청구되지 않았습니다. 새 Idempotency-Key 로 다시 시도하세요.
503voice_capacity_full사용자 지정 음성 정원이 일시적으로 가득 찼습니다. 청구되지 않았습니다. 나중에 다시 시도하세요.
504upstream_timeout음성 서비스가 제때 응답하지 않았습니다. 청구되지 않았습니다. 같은 Idempotency-Key 로 다시 시도하세요.

데이터 API

곧 제공 예정 — 세 개의 BazaarLink 엔드포인트로 공개 소셜 및 커머스 데이터를 이용하세요. 이 서비스는 기본적으로 꺼져 있으며 활성화될 때까지 요청은 service_paused를 반환합니다.

소셜 데이터 요청 제출

POST/v1/data/social

요청 매개변수

코드유형필수의미
platformstring예카탈로그의 플랫폼 ID(예: twitter 또는 instagram).
actionstring예해당 플랫폼이 지원하는 작업입니다. 사용 가능한 조합은 카탈로그를 확인하세요.
paramsobject아니요작업별 입력입니다. 카탈로그의 required_params와 optional_params를 사용하세요.
modesync | async아니요선택 사항입니다. async는 폴링할 작업을 반환하며, 비동기 전용 작업은 생략해도 작업을 반환합니다.

응답 형식

HTTP 200 · data.social · id · object · platform · action · count · results · usage.cost

{
  "id": "req_example",
  "object": "data.social",
  "platform": "twitter",
  "action": "search",
  "count": 1,
  "results": [
    {
      "id": "post_example",
      "url": "https://x.com/someone/status/post_example",
      "text": "Example post",
      "like_count": 120,
      "reply_count": 8,
      "retweet_count": 14,
      "view_count": 5400,
      "posted_at": "2026-10-07T00:48:38+00:00",
      "author_username": "someone",
      "author_name": "Someone",
      "platform": "twitter"
    }
  ],
  "usage": {
    "cost": 0.0048
  }
}

비동기 작업

비동기 전용 작업이나 mode async는 불투명한 작업 ID와 함께 HTTP 202를 반환합니다. GET /v1/data/jobs/{id}를 폴링하세요. HTTP 202는 대기 중, HTTP 200은 완료된 data.social 응답을 의미합니다. 작업은 15분 후 만료됩니다(HTTP 410 job_expired). 알 수 없는 작업이나 다른 계정의 작업은 HTTP 404 not_found를 반환합니다. 완료된 작업은 처음 성공적으로 가져올 때 한 번만 과금됩니다.

{
  "platform": "instagram",
  "action": "discover",
  "params": {
    "keyword": "coffee"
  },
  "mode": "async"
}

HTTP 202

{
  "id": "job_example",
  "object": "data.job",
  "status": "pending",
  "platform": "instagram",
  "action": "discover"
}

비동기 작업 폴링

GET/v1/data/jobs/{id}

HTTP 202 pending → HTTP 200 data.social · HTTP 410 job_expired · HTTP 404 not_found

{
  "id": "job_example",
  "object": "data.social",
  "platform": "instagram",
  "action": "discover",
  "count": 1,
  "results": [
    {
      "id": "post_example",
      "url": "https://www.instagram.com/p/example/",
      "text": "Example result",
      "platform": "instagram"
    }
  ],
  "usage": {
    "cost": 0.0096
  }
}

사용 가능한 작업과 요금 보기

GET/v1/data/catalog

object · product · platforms · actions · required_params · optional_params · max_limit · async · price_usd

{
  "object": "data.catalog",
  "product": "BazaarLink Data API",
  "platforms": [
    {
      "platform": "twitter",
      "actions": [
        {
          "action": "search",
          "label": "Keyword search",
          "required_params": [
            "keyword"
          ],
          "optional_params": [
            "sort"
          ],
          "max_limit": 200,
          "async": false,
          "price_usd": 0.0048
        }
      ]
    },
    {
      "platform": "instagram",
      "actions": [
        {
          "action": "discover",
          "label": "Discover",
          "required_params": [
            "keyword"
          ],
          "optional_params": [],
          "max_limit": null,
          "async": true,
          "price_usd": 0.0096
        }
      ]
    }
  ]
}

요금

요금은 플랫폼과 작업에 따라 단계별로 적용됩니다. GET /v1/data/catalog에서 활성화된 각 작업의 고객 요금을 확인할 수 있습니다. 성공한 호출은 한 번만 과금되며 실패한 호출과 결과가 없는 호출은 무료입니다. Data API와 웹 검색은 하나의 일일 무료 사용량을 공유합니다.

오류 코드

{"error":{"code":"<code>","message":"<fixed message>"}}

코드HTTP의미
unauthorized401API 키가 없거나 유효하지 않습니다.
forbidden403요청이 허용되지 않습니다.
invalid_request400요청 본문이 유효하지 않습니다.
invalid_params400작업 매개변수가 거부되었습니다.
unsupported_capability400플랫폼 또는 작업을 사용할 수 없습니다.
insufficient_credits402크레딧이 부족합니다.
budget_cap_reached402 or policy status계정 지출 한도에 도달했습니다.
body_too_large413요청 본문이 크기 제한을 초과했습니다.
free_quota_exhausted432일일 무료 사용량을 모두 사용했습니다.
rate_limited429속도 제한에 도달했습니다. Retry-After를 준수하세요.
data_unavailable503데이터 서비스를 일시적으로 사용할 수 없습니다.
timeout504요청 시간이 초과되었습니다.
bad_upstream_response502데이터 서비스가 유효하지 않은 응답을 반환했습니다.
job_expired410작업이 15분 후 만료되었습니다.
not_found404작업이 없거나 다른 계정에 속해 있습니다.
job_failed503비동기 작업에 실패했습니다.
service_paused503서비스가 아직 활성화되지 않았거나 일시 중지되었습니다.

예시

curl

curl https://api.bazaarlink.ai/v1/data/social \
  -H "Authorization: Bearer $BAZAARLINK_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"platform":"twitter","action":"search","params":{"keyword":"BazaarLink","limit":5}}'

Python (requests)

import os
import requests

response = requests.post(
    "https://api.bazaarlink.ai/v1/data/social",
    headers={"Authorization": f"Bearer {os.environ['BAZAARLINK_API_KEY']}"},
    json={"platform": "twitter", "action": "search", "params": {"keyword": "BazaarLink", "limit": 5}},
    timeout=30,
)
response.raise_for_status()
print(response.json())

JavaScript (fetch)

const response = await fetch("https://api.bazaarlink.ai/v1/data/social", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.BAZAARLINK_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ platform: "twitter", action: "search", params: { keyword: "BazaarLink", limit: 5 } }),
});
if (!response.ok) throw new Error(`HTTP ${response.status}`);
console.log(await response.json());

Submit a decisions request

Evaluate a state against named questions with a decisions-output model. This alpha endpoint returns non-streaming JSON. Find available model ids with GET /v1/models?output_modalities=decisions; use this endpoint for Clef instead of chat/completions. Input tokens are billed at the selected model's customer price. Sufficient credits are required. Set BAZAARLINK_API_KEY to your API key; the sample builds its complete Authorization header in BAZAARLINK_AUTH_HEADER.

View the decisions API reference

export BAZAARLINK_AUTH_HEADER="Authorization: $(printf '%s %s' 'Bearer' "$BAZAARLINK_API_KEY")"

curl https://api.bazaarlink.ai/v1/alpha/decisions \
  -H "$BAZAARLINK_AUTH_HEADER" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "cloudflare/clef-flash",
    "state": "The support agent issued a full refund.",
    "questions": {
      "refunded": {
        "type": "noul",
        "instructions": "Was a refund issued?"
      }
    }
  }'

비디오 입력

동영상 입력을 지원하는 모델에 동영상 파일을 전송하여 분석, 캡션 생성, 장면 및 이벤트에 대한 질문에 답하게 합니다. 직접 URL 또는 base64 데이터 URI를 사용할 수 있습니다 — URL은 공개적으로 접근 가능한 동영상에 효율적이며, base64는 로컬 파일이나 비공개 동영상에 사용합니다.

지원 형식

MP4(H.264)MPEGMOVWebM
response = client.chat.completions.create(
    model="google/gemini-3.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를 네이티브로 지원하는 모델(Claude, Gemini 등)에 메시지로 PDF 문서를 직접 전송할 수 있습니다. 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 호환 엔드포인트. client.responses.create()를 사용하는 OpenAI Python SDK ≥ 1.x 에이전트 및 프레임워크에 적합합니다.

POST/v1/responses
Note
채팅 완성과 동일한 인증 및 모델 라우팅을 지원합니다.

요청 바디

model필수
string
GET /v1/models에 표시된 id 또는 alias를 사용하세요(예: "claude-sonnet-4.6" 또는 "anthropic/claude-sonnet-4.6").
input필수
string | Item[]
사용자 입력 — 일반 문자열(단일 메시지) 또는 멀티턴/멀티모달 대화를 위한 입력 항목 배열.
instructions
string
시스템 수준 지시사항, 시스템 메시지와 동일. 매 요청마다 다시 보내야 합니다.
stream
boolean
true이면 Responses API SSE 스트림 이벤트를 반환합니다. 이벤트 유형: response.created, response.output_text.delta, response.completed.
max_output_tokens
integer
생성할 최대 출력 토큰 수 (o-시리즈 모델의 경우 추론 토큰 포함).
temperature
number
샘플링 값은 범위 검증 없이 전달됩니다. 모델이 지원 범위 밖의 값을 제한하거나 무시할 수 있습니다.
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 출력 강제. 구조화된 출력 섹션 참조
previous_response_id
string
이 엔드포인트는 상태 비저장입니다 — null이 아닌 값을 전달하면 즉시 400(invalid_prompt)을 반환하며, 절대 수락된 후 무시되지 않습니다. 대신 상태 비저장 모드를 사용하세요: input 배열에 전체 대화 기록을 전달하세요.

요청 스키마 (TypeScript)

type ResponsesRequest = {
  model: string;                    // Listed id or alias from GET /v1/models
  input: string | InputItem[];      // string or multi-turn array

  // Optional
  instructions?: string;            // System-level message
  stream?: boolean;                 // Default: false
  max_output_tokens?: number;
  temperature?: number;
  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
};

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://api.bazaarlink.ai/v1/responses \
  -H "Authorization: Bearer $BAZAARLINK_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "openai/gpt-5.4-mini",
    "instructions": "You are a helpful assistant.",
    "input": "What is the capital of Taiwan?"
  }'

응답 형식

BazaarLink는 표준화된 응답을 반환하고 업스트림 전용 필드를 제거합니다. 응답의 불투명한 BazaarLink 요청 ID는 x-request-id와 같으며 GET /v1/generation에서 사용할 수 있습니다. 비스트리밍 응답은 같은 ID를 x-generation-id에도 반환합니다. usage.cost는 고객에게 청구된 USD 금액입니다. 통계는 완료 후 몇 초 뒤에 표시될 수 있으므로 404는 잠시 재시도하세요.

// Non-streaming response object
type ResponsesResponse = {
  id: string;             // Opaque BazaarLink request id; format may change
  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;          // USD amount charged to the customer for this request
  } | 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" };

채팅 완성에서 마이그레이션

messages를 input(문자열 또는 배열)으로 바꾸고, system-role 메시지 대신 instructions를 사용하며, choices[0].message.content 대신 output[0].content[0].text를 읽으세요.

# Chat Completions (before)
response = client.chat.completions.create(
    model="openai/gpt-5.4-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-5.4-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 호환)

Claude SDK용 Anthropic 호환 Messages API입니다. SDK를 BazaarLink로 연결하고 BazaarLink API 키를 사용하세요. 응답 필드와 청구 메타데이터는 아래에 문서화된 BazaarLink 규격을 따릅니다.

POST/v1/messages
Note
Bearer token 또는 x-api-key header 지원 (Anthropic SDK 호환). 최대 body 크기: 10 MB.

요청 바디

model필수
string
GET /v1/models에 표시된 id 또는 alias를 사용하세요(예: "claude-sonnet-4.6" 또는 "anthropic/claude-sonnet-4.6").
max_tokens필수
integer
생성할 최대 토큰 수 (양의 정수).
messages필수
Message[]
대화 메시지 배열 (비어 있지 않음).
system
string
선택적 system prompt.
stream
boolean
true이면 Server-Sent Events 스트림을 반환합니다. 기본값: false
temperature
number
샘플링 값은 범위 검증 없이 전달됩니다. 모델이 지원 범위 밖의 값을 제한하거나 무시할 수 있습니다.
top_p
number
핵 샘플링 확률 질량. 기본값: 1
top_k
integer
샘플링 값은 범위 검증 없이 전달됩니다. 모델이 지원 범위 밖의 값을 제한하거나 무시할 수 있습니다.
stop_sequences
string[]
사용자 정의 정지 시퀀스 문자열 배열.
tools
Tool[]
모델이 호출할 수 있는 도구(함수) 목록
tool_choice
string | object
도구 사용 제어: "auto", "none", 또는 특정 도구

예제 요청

from anthropic import Anthropic

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

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

응답

BazaarLink는 표준화된 응답을 반환하고 업스트림 전용 필드를 제거합니다. 응답의 불투명한 BazaarLink 요청 ID는 x-request-id와 같으며 GET /v1/generation에서 사용할 수 있습니다. 비스트리밍 응답은 같은 ID를 x-generation-id에도 반환합니다. usage.cost와 usage.bz_cost에는 고객에게 청구된 동일한 USD 금액이 들어 있습니다. 통계는 완료 후 몇 초 뒤에 표시될 수 있으므로 404는 잠시 재시도하세요.

{
  "id": "85e6f35c71a31f19-SJC",
  "type": "message",
  "role": "assistant",
  "model": "anthropic/claude-opus-4.6",
  "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,
    "cost": 0.00042,
    "bz_cost": 0.00042
  }
}

오류 envelope는 실패 유형에 따라 다릅니다. HTTP 상태와 존재하는 경우 error.type으로 분기하세요. error.code는 문자열, 숫자 HTTP 상태이거나 없을 수 있습니다. 처리 방법은 오류 섹션을 참조하세요.

모델

가격 및 기능 정보와 함께 사용 가능한 모든 모델을 나열합니다. 이 엔드포인트는 인증이 필요하지 않습니다.

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

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

응답

{
  "data": [
    {
      "id": "openai/gpt-4o",
      "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-4o")
  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)
    input_cache_read?: string;   // Cache read price per token (USD); only when the model publishes one
    input_cache_write?: string;  // Cache write price per token (USD); only when the model publishes one
    image_output?: string;       // Image output price per token (USD); only token-billed image models (display only)
  };
  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
    input_cache_read?: string;     // USD per token, only when the tier overrides it
    input_cache_write?: string;    // USD per token, only when the tier overrides it
  }[];
};

입력 길이 기반 단계별 가격

일부 모델은 프롬프트가 token 임계값을 초과하면 전체 가격표가 전환됩니다(임계값을 초과한 부분만이 아닙니다). 임계값은 엄격한 부등식입니다: 입력 token 수가 정확히 N이면 N 이하 단계가 적용되고, N을 초과할 때만 상위 단계가 적용됩니다.

pricing_tiers는 pricing과 동일한 레벨의 필드로, 기본 가격을 초과하는 오버라이드 단계가 있는 모델에만 존재합니다. 항목은 above_prompt_tokens 오름차순으로 정렬되며, prompt/completion은 token당 USD 가격입니다(pricing.prompt/pricing.completion과 동일한 단위). pricing.prompt와 pricing.completion은 항상 기본(최저) 단계입니다.

대부분의 모델에는 단계가 없습니다 — 이 경우 응답에 pricing_tiers 키 자체가 없습니다.

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

사용 가능한 모델 (171)

다음은 BazaarLink에서 현재 사용 가능한 모델로, 데이터베이스에서 동적으로 로드됩니다:

Qwen
qwen/qwen3.8-max1000K ctx · $1.65/$4.95text+image+video->text
qwen/qwen3.7-plus1000K ctx · $0.32/$1.28text+image->text
qwen/qwen3.7-max1000K ctx · $1.65/$4.95text->text
qwen/qwen3.7-flash1000K ctx · $0.03/$0.13text+image+video->text
qwen/qwen3.5-35b-a3b262K ctx · $0.31/$1.25text+image+video->text
qwen/qwen3.5-27b262K ctx · $0.26/$2.60text+image+video->text
qwen/qwen3-next-80b-a3b-instruct262K ctx · $0.14/$0.57text->text
qwen/qwen3.5-397b-a17b262K ctx · $0.55/$3.50text+image+video->text
qwen/qwen3.6-plus1000K ctx · $0.33/$1.95text+image+video->text
qwen/qwen3-coder-flash1000K ctx · $0.20/$0.97text->text
qwen/qwen3.5-122b-a10b262K ctx · $0.40/$3.20text+image+video->text
qwen/qwen3-vl-235b-a22b-instruct262K ctx · $0.20/$0.88text+image->text
qwen/qwen3.8-27b1000K ctx · $0.50/$3.00text+image+video->text
qwen/qwen3.8-2.4t-a95b1049K ctx · $2.00/$6.00text->text
qwen/qwen3-embedding-8b33K ctx · $0.01/$0.00text->embeddings
qwen/qwen3-embedding-0.6b33K ctx · $0.01/$0.00text->embeddings
qwen/qwen3-embedding-4b33K ctx · $0.02/$0.00text->embeddings
qwen/qwen3.5-flash-02-231000K ctx · $0.07/$0.26text+image+video->text
qwen/qwen3-coder-30b-a3b-instruct262K ctx · $0.07/$0.28text->text
qwen/qwen3.6-35b-a3b262K ctx · $0.15/$1.00text+image+video->text
qwen/qwen3-coder-next262K ctx · $0.12/$0.80text->text
qwen/qwen3-vl-30b-a3b-instruct262K ctx · $0.15/$0.60text+image->text
qwen/qwen3.5-plus-02-151000K ctx · $0.26/$1.56text+image+video->text
qwen/qwen3.6-27b262K ctx · $0.29/$2.40text+image+video->text
qwen/qwen3.5-plus-202604201000K ctx · $0.30/$1.80text+image+video->text
qwen/qwen3-coder262K ctx · $0.30/$1.00text->text
qwen/qwen-2.5-72b-instruct33K ctx · $0.36/$0.40text->text
qwen/qwen-image-3 · $0.00/$0.00text+image->image
qwen/qwen-image-3-pro · $0.00/$0.00text+image->image
Google
google/gemini-4-argon1049K ctx · $2.00/$10.00text+image+file+audio+video->text
google/gemini-3.1-flash-lite-preview1049K ctx · $0.25/$1.50text+image+file+audio+video->text
google/gemini-3.1-pro-preview1049K ctx · $2.00/$12.00text+image+file+audio+video->text
google/gemma-3-4b-it131K ctx · $0.05/$0.10text+image->text
google/gemini-3.1-flash-lite1049K ctx · $0.25/$1.50text+image+file+audio+video->text
google/gemini-3.5-flash-lite1049K 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/gemini-3.7-flash1049K ctx · $0.75/$3.75text+image+file+audio+video->text
google/gemini-3.8-flash1049K ctx · $0.75/$3.75text+image+file+audio+video->text
google/gemini-3.6-flash1049K ctx · $0.75/$3.75text+image+file+audio+video->text
google/gemini-3.5-flash1049K ctx · $1.50/$9.00text+image+file+audio+video->text
google/text-embedding-0052K ctx · $0.03/$0.00text->embeddings
google/text-multilingual-embedding-0022K ctx · $0.03/$0.00text->embeddings
google/gemini-embedding-00120K ctx · $0.15/$0.00text->embeddings
google/gemma-4-26b-a4b-it262K ctx · $0.09/$0.34text+image+video->text
google/gemma-4-31b-it262K ctx · $0.09/$0.34text+image+video->text
google/gemini-2.5-flash-image33K ctx · $0.30/$2.50text+image->text+image
google/gemini-3.1-flash-image-preview66K ctx · $0.50/$3.00text+image->text+image
google/gemini-3.1-flash-image131K ctx · $0.50/$3.00text+image->text+image
google/gemini-3-pro-image131K ctx · $2.00/$12.00text+image->text+image
google/veo-3.1 · $0.00/$0.00text+image->video
google/gemini-embedding-2-preview8K ctx · $0.20/$0.00text+image+file+audio+video->embeddings
google/gemini-nano-banana-2.166K ctx · $1.50/$7.50text+image->text+image
OpenAI
openai/gpt-5.3-codex400K ctx · $1.75/$14.00text->text
openai/gpt-6-luna1050K ctx · $0.10/$0.50text+image+file->text
openai/gpt-5.6-luna1050K ctx · $0.20/$1.20text+image+file->text
openai/gpt-5.4-mini400K ctx · $0.75/$4.50text+image+file->text
openai/gpt-6.1-sol1050K ctx · $2.00/$10.00text+image+file->text
openai/gpt-6-sol1050K ctx · $2.00/$10.00text+image+file->text
openai/gpt-5.41050K ctx · $2.50/$15.00text+image+file->text
openai/gpt-5.51050K ctx · $5.00/$30.00text+image+file->text
openai/gpt-6-astra1050K ctx · $10.00/$50.00text+image+file->text
openai/gpt-5.6-terra1050K ctx · $2.00/$12.00text+image+file->text
openai/text-embedding-3-small8K ctx · $0.02/$0.00text->embeddings
openai/gpt-oss-safeguard-20b128K ctx · $0.07/$0.30text->text
openai/gpt-oss-120b131K ctx · $0.15/$0.60text->text
openai/text-embedding-ada-0028K ctx · $0.10/$0.00text->embeddings
openai/text-embedding-3-large · $0.13/$0.00text->embeddings
openai/gpt-5.6-sol1050K ctx · $4.00/$20.00text+image+file->text
openai/gpt-oss-20b131K ctx · $0.03/$0.13text->text
openai/gpt-4o128K ctx · $2.50/$10.00text+image+file->text
openai/gpt-image-1-mini400K ctx · $2.50/$2.50text+image->image
openai/gpt-5.4-image-2272K ctx · $8.00/$15.00text+image+file->text+image
openai/gpt-image-2.5-flare400K ctx · $8.00/$8.00text+image->image
openai/gpt-image-2.5-sunburst400K ctx · $8.00/$8.00text+image->image
openai/gpt-image-1400K ctx · $10.00/$10.00text+image->image
Anthropic
anthropic/claude-sonnet-4.61000K ctx · $3.00/$15.00text+image+file->text
anthropic/claude-opus-4.61000K ctx · $5.00/$25.00text+image+file->text
anthropic/claude-haiku-5.51000K ctx · $0.10/$0.50text+image+file->text
anthropic/claude-haiku-4.5200K ctx · $1.00/$5.00text+image+file->text
anthropic/claude-sonnet-51000K ctx · $2.00/$10.00text+image+file->text
anthropic/claude-sonnet-5.51000K ctx · $2.00/$10.00text+image+file->text
anthropic/claude-sonnet-4.51000K ctx · $3.00/$15.00text+image+file->text
anthropic/claude-opus-5.51000K ctx · $4.00/$20.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-opus-51000K ctx · $5.00/$25.00text+image+file->text
anthropic/claude-opus-4.5200K ctx · $5.00/$25.00text+image+file->text
anthropic/claude-fable-5.11000K ctx · $10.00/$50.00text+image+file->text
anthropic/claude-fable-51000K ctx · $10.00/$50.00text+image+file->text
anthropic/claude-opus-4.1200K ctx · $15.00/$75.00text+image+file->text
DeepSeek
deepseek/deepseek-v4.1-flash-10171049K ctx · $0.21/$0.85text+image->text
deepseek/deepseek-v4-flash1049K ctx · $0.14/$0.28text->text
deepseek/deepseek-v4-pro1049K ctx · $1.65/$3.30text->text
deepseek/deepseek-v4.1-flash1049K ctx · $0.21/$0.85text+image->text
deepseek/deepseek-chat-v3.1164K ctx · $0.21/$0.79text->text
deepseek/deepseek-chat164K ctx · $0.26/$0.38text->text
deepseek/deepseek-r164K ctx · $0.50/$2.15text->text
deepseek/deepseek-v4-pro-08131049K ctx · $0.89/$2.67text->text
deepseek/deepseek-v4-flash-07311000K ctx · $0.44/$1.32text->text
deepseek/deepseek-r1-0528164K ctx · $0.50/$2.15text->text
deepseek/deepseek-v4-flash-0731free1049K ctx · $0.20/$0.40text->text
elevenlabs
elevenlabs/eleven-v4-turbo · $0.00/$0.00text->speech
elevenlabs/eleven-multilingual-v2 · $0.00/$0.00text->speech
elevenlabs/eleven-v4 · $0.00/$0.00text->speech
elevenlabs/eleven-turbo-v2.5 · $0.00/$0.00text->speech
elevenlabs/eleven-flash-v2 · $0.00/$0.00text->speech
elevenlabs/eleven-v3-conversational · $0.00/$0.00text->speech
elevenlabs/eleven-flash-v2.5 · $0.00/$0.00text->speech
elevenlabs/eleven-v3 · $0.00/$0.00text->speech
elevenlabs/eleven-turbo-v2 · $0.00/$0.00text->speech
elevenlabs/scribe-v2 · $0.00/$0.00audio->transcription
elevenlabs/scribe-v2-medical · $0.00/$0.00audio->transcription
Zhipu AI
z-ai/glm-5v-turbo203K ctx · $1.20/$4.00text+image+video->text
z-ai/glm-5.3-flash1049K ctx · $0.15/$0.50text+image+video->text
z-ai/glm-4.6205K ctx · $0.60/$2.20text->text
z-ai/glm-5.3-flashx1049K ctx · $0.37/$1.25text+image+video->text
z-ai/glm-5.31049K ctx · $1.13/$4.40text->text
z-ai/glm-4.7-flash200K ctx · $0.06/$0.40text->text
z-ai/glm-4.5-air131K ctx · $0.13/$0.85text->text
z-ai/glm-4.6v131K ctx · $0.30/$0.90text+image+video->text
z-ai/glm-4.5v66K ctx · $0.60/$1.80text+image->text
z-ai/glm-4.5131K ctx · $0.60/$2.20text->text
voyage
voyage/voyage-4-lite32K ctx · $0.02/$0.00text->embeddings
voyage/voyage-3.5-lite32K ctx · $0.02/$0.00text->embeddings
voyage/voyage-3.532K ctx · $0.06/$0.00text->embeddings
voyage/voyage-432K ctx · $0.06/$0.00text->embeddings
voyage/voyage-4-large32K ctx · $0.12/$0.00text->embeddings
voyage/voyage-law-216K ctx · $0.12/$0.00text->embeddings
voyage/voyage-finance-232K ctx · $0.12/$0.00text->embeddings
voyage/voyage-code-216K ctx · $0.12/$0.00text->embeddings
voyage/voyage-3-large32K ctx · $0.18/$0.00text->embeddings
voyage/voyage-code-332K ctx · $0.18/$0.00text->embeddings
xAI
x-ai/grok-build-0.1256K ctx · $1.00/$2.00text+image+file->text
x-ai/grok-4.31000K ctx · $1.25/$2.50text+image+file->text
x-ai/grok-4.6500K ctx · $2.00/$6.00text+image+file->text
x-ai/grok-4.5500K ctx · $2.00/$6.00text+image+file->text
x-ai/grok-4.7500K ctx · $2.00/$6.00text+image->text
x-ai/grok-4.202000K ctx · $1.25/$2.50text+image+file->text
x-ai/grok-imagine-video-1.5-lite · $0.00/$0.00text+image->video
x-ai/grok-imagine-image-2.0 · $0.00/$0.00text+image->image
bytedance-seed
bytedance-seed/seed-1.6-flash262K ctx · $0.07/$0.30text+image+video->text
bytedance-seed/seed-2.0-mini262K ctx · $0.10/$0.40text+image+video->text
bytedance-seed/seed-2.0-lite262K ctx · $0.25/$2.00text+image+video->text
bytedance-seed/seed-1.6262K ctx · $0.25/$2.00text+image+video->text
ByteDance
bytedance/seedance-2.5 · $0.00/$0.00text+image+audio+video->video
bytedance/seedance-2.0 · $0.00/$0.00text+image+audio+video->video
bytedance/seedance-1-5-pro · $0.00/$0.00text+image->video
bytedance/seedance-2.0-fast · $0.00/$0.00text+image+audio+video->video
Moonshot AI
moonshotai/kimi-k31049K ctx · $2.83/$14.13text+image+video->text
moonshotai/kimi-k3.1-pro1049K ctx · $2.00/$10.00text+image+video->text
moonshotai/kimi-k2-0905262K ctx · $0.60/$2.50text->text
Cohere
cohere/rerank-v3.54K ctx · $0.00/$0.00text->rerank
cohere/rerank-4-pro33K ctx · $0.00/$0.00text->rerank
cohere/rerank-4-fast33K ctx · $0.00/$0.00text->rerank
MiniMax
minimax/minimax-m31049K ctx · $0.30/$1.20text+image+video->text
minimax/hailuo-3-max · $0.00/$0.00text+image->video
xiaomi
xiaomi/mimo-v2.6-flash1049K ctx · $0.14/$0.28text+image+video+audio->text
xiaomi/mimo-v2.6-pro1049K ctx · $0.43/$0.87text+image+video+audio->text
reflection
reflection/beam-free1049K ctx · $0.00/$0.00text->text
reflection/beam1049K ctx · $0.00/$0.00text->text
Perplexity
perplexity/pplx-embed-v1-0.6b32K ctx · $0.00/$0.00text->embeddings
perplexity/pplx-embed-v1-4b32K ctx · $0.03/$0.00text->embeddings
Mistral
mistralai/mistral-embed-23128K ctx · $0.10/$0.00text->embeddings
mistralai/codestral-embed-25058K ctx · $0.15/$0.00text->embeddings
cloudflare
cloudflare/clef-flash25K ctx · $0.09/$0.00text+image->decisions
cloudflare/clef66K ctx · $0.24/$0.00text+image->decisions
NVIDIA
nvidia/nemotron-3.5-lightning-free1000K ctx · $0.00/$0.00text->text
stealth
stealth/glyph-cluster256K ctx · $0.00/$0.00text->text
Meta
meta/muse-wonder1049K ctx · $4.00/$20.00text+image+file->text
amazon
amazon/titan-embed-text-v28K ctx · $0.02/$0.00text->embeddings
typesafe-ai
typesafe-ai/jev32K ctx · $0.04/$0.00text->decisions

다음에서 모든 모델을 탐색하세요 모델 페이지.

구조화 평가(Jev)

Jev는 JSON 상태를 이름이 지정된 질문으로 평가하고 boolean, choice 또는 score 유형의 답변을 반환합니다. 명확한 기준을 프로그램에서 처리할 수 있는 평가 결과로 바꿀 때 사용하세요.

평가 및 판단 전용
Jev는 채팅을 지원하지 않습니다. Jev 요청은 POST /v1/evaluations로 보내세요. POST /v1/chat/completions로 보내면 HTTP 400을 반환합니다.
POST/v1/evaluations

BazaarLink API 키로 다음 엔드포인트를 호출하세요. 전체 URL: https://api.bazaarlink.ai/v1/evaluations.

필드 설명

model
string
선택 사항입니다. 생략하면 typesafe-ai/jev가 기본값입니다. 다른 모델 ID는 HTTP 400과 model_not_available 코드를 반환합니다.
state
string | object | array
필수입니다. 평가할 상태를 JSON 문자열, 객체 또는 배열로 제공합니다. 직렬화된 state와 questions의 합계가 32,000 tokens를 넘으면 context_length_exceeded를 반환합니다.
questions
record<string, Question>
필수이며 이름이 지정된 질문을 하나 이상 포함하는 객체입니다. 각 질문 이름은 응답 answers 객체의 키가 됩니다.
type
boolean | choice | score
각 질문에 필수이며 boolean, choice 또는 score 중 하나입니다.
instructions
string | object | array
각 질문에 필수입니다. 판단할 내용을 설명하는 JSON 문자열, 객체 또는 배열입니다.
criteria
object | array
type에 따라 다릅니다. boolean에서는 선택 사항이며, 제공할 경우 키는 true 또는 false만 허용됩니다. choice에는 비어 있지 않은 객체가 필요하고 score에는 순서가 있는 항목 두 개 이상의 배열이 필요합니다.

답변 유형

  • boolean — criteria는 생략할 수 있으며, 지정하는 경우 true와 false 키만 허용됩니다. 답변에는 숫자 probability가 포함됩니다.
  • choice — criteria는 선택지 이름을 JSON 기준에 연결하는 비어 있지 않은 객체여야 합니다. 답변에는 문자열 choice가 포함되며 probabilities의 키는 선택지 이름입니다.
  • score — criteria는 두 항목 이상을 순서대로 담은 배열이어야 합니다. 숫자 score는 criteria 배열 순서에 따른 인덱스 0..N-1의 기댓값이며, probabilities의 키는 해당 인덱스를 문자열로 나타낸 값입니다.

요청 예시

curl --fail-with-body https://api.bazaarlink.ai/v1/evaluations \
  -H "Authorization: Bearer $BAZAARLINK_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "model": "typesafe-ai/jev",
  "state": "The support agent issued a full refund and apologised for the delay.",
  "questions": {
    "refunded": {
      "type": "boolean",
      "instructions": "Was a refund issued?"
    },
    "tone": {
      "type": "choice",
      "instructions": "Tone of the agent?",
      "criteria": {
        "apologetic": "The agent apologises",
        "neutral": "No emotional language",
        "hostile": "The agent is rude"
      }
    },
    "quality": {
      "type": "score",
      "instructions": "How complete was the resolution?",
      "criteria": [
        "poor",
        "partial",
        "complete"
      ]
    }
  }
}'

성공 응답 예시

예시 응답에는 id, object, model, answers, usage, rounding, warnings가 포함됩니다. answers의 키는 질문 이름입니다. usage에는 input_tokens, output_tokens, total_tokens가 있고 rounding에는 probabilityDecimals와 scoreDecimals가 표시됩니다. warnings는 배열이며 이 예시에서는 비어 있습니다. answers에서 choice의 probabilities는 선택지 이름을 키로 사용하고, score의 probabilities는 criteria 인덱스를 문자열로 바꾼 값을 키로 사용합니다.

{
  "id": "eval-a3d350e5-2705-4a9b-be7c-838fa4e4eb2b",
  "object": "evaluation",
  "model": "typesafe-ai/jev",
  "answers": {
    "refunded": {
      "type": "boolean",
      "probability": 0.99
    },
    "tone": {
      "type": "choice",
      "choice": "apologetic",
      "probabilities": {
        "apologetic": 1,
        "neutral": 0,
        "hostile": 0
      }
    },
    "quality": {
      "type": "score",
      "score": 1.98,
      "probabilities": {
        "0": 0,
        "1": 0.02,
        "2": 0.98
      }
    }
  },
  "usage": {
    "input_tokens": 394,
    "output_tokens": 74,
    "total_tokens": 468
  },
  "rounding": {
    "probabilityDecimals": 2,
    "scoreDecimals": 2
  },
  "warnings": []
}

채팅 엔드포인트 오류 응답

Jev를 채팅 엔드포인트로 보내면 HTTP 400을 반환합니다. 아래 필드와 값은 처리 코드와 일치합니다. message는 자리표시자이며 실제 문구는 서버가 제공합니다.

{
  "error": {
    "message": "<server-generated message>",
    "type": "invalid_request_error",
    "code": 400
  }
}

스트리밍

설정 stream: true 하여 Server-Sent Events(SSE) 스트림을 받으세요. 각 이벤트에는 응답 청크가 포함됩니다.

from openai import OpenAI

client = OpenAI(
    base_url="https://api.bazaarlink.ai/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":"85e6f35c71a31f19-SJC","choices":[{"delta":{"content":"Hello"},"index":0}]}

data: {"id":"85e6f35c71a31f19-SJC","choices":[{"delta":{"content":" world"},"index":0}]}

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

data: [DONE]
스트리밍에서의 사용량
스트리밍 시, 사용량 데이터는 [DONE] 메시지 이전의 마지막 청크에서 빈 delta와 finish_reason: "stop"을 가진 choices 배열과 함께 반환됩니다.

Keep-alive 및 마지막 청크

스트림에는 SSE 주석 줄과 알 수 없는 또는 ping keep-alive 이벤트가 포함될 수 있습니다. 이를 무시하고 data 프레임을 파싱하세요. 마지막 data 프레임에는 data: [DONE] 전에 usage가 포함될 수 있습니다.

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

data: {"id":"85e6f35c71a31f19-SJC","choices":[{"delta":{"content":"Hi"},"index":0}]}

data: {"id":"85e6f35c71a31f19-SJC","choices":[{"delta":{},"finish_reason":"stop","index":0}],"usage":{...}}

data: [DONE]

스트림 취소

클라이언트 연결을 종료하면 스트리밍 요청을 취소할 수 있습니다 — 예: AbortController.abort() 호출 또는 stream 객체 종료. BazaarLink는 취소 신호를 받는 즉시 이후 청크 전달을 중단하고 공급자로 나가는 요청을 취소합니다.

import OpenAI from "openai";

const client = new OpenAI({
  baseURL: "https://api.bazaarlink.ai/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 청크가 도착하기 전에 스트림이 끝나면 — 클라이언트 측 취소를 포함해서 — 해당 요청의 신뢰할 수 있는 토큰 수 근거가 없으므로 BazaarLink는 예약된 금액 전액을 환불합니다. 취소 전에 클라이언트로 이미 전달된 내용에 대해서는 과금되지 않습니다.
공급자 측 즉시 중단은 보장되지 않습니다
연결을 종료하면 BazaarLink는 즉시 이후 토큰 전달과 과금을 중단하지만, 업스트림 공급자가 연결이 끊기는 순간 자사 서버에서 생성을 멈추는지 여부는 해당 공급자에 따라 다릅니다 — 일부는 연결 종료 후에도 잠시 계속 계산할 수 있습니다.

스트림 도중 오류

오류 프레임에는 choices 필드가 없음
스트리밍이 이미 시작된 후 실패가 발생하면(예: 업스트림 연결 끊김), 일반적인 {choices:[...]} 대신 {error:{message,type,code}} 형태의 SSE 데이터 프레임을 받게 됩니다 — 헤더는 이미 전송되었으므로 HTTP 상태 변경은 없습니다. choices[0].delta를 읽기 전에 error 키가 있는지 확인하세요. 이미 스트리밍된 토큰에 대해서만 과금됩니다(부분 과금 적용).
data: {"id":"85e6f35c71a31f19-SJC","choices":[{"delta":{"content":"The capital of "},"index":0}]}

data: {"error":{"message":"The request could not be completed.","type":"upstream_error","code":502}}

data: [DONE]

임베딩

임베딩(Embeddings)은 의미를 포착하는 수치 표현으로, 텍스트를 벡터(숫자 배열)로 변환하여 다양한 머신러닝 작업에 활용할 수 있습니다. BazaarLink는 OpenAI 임베딩 API와 호환되는 통합 엔드포인트를 제공하여 하나의 인터페이스로 여러 공급자의 임베딩 모델을 호출할 수 있습니다.

Embedding 응답은 x-request-id와 같은 불투명한 BazaarLink 요청 ID를 사용하며 GET /v1/generation에서 사용할 수 있습니다. 비스트리밍 응답은 같은 ID를 x-generation-id에도 반환합니다. usage.cost는 이 요청에 대해 고객에게 청구된 USD 금액입니다. 통계는 완료 후 몇 초 뒤에 표시될 수 있으므로 404는 잠시 재시도하세요.

임베딩이란?

임베딩은 텍스트를 고차원 벡터로 변환하며, 의미적으로 유사한 텍스트는 벡터 공간에서 더 가깝게 위치합니다——예를 들어 "고양이"와 "새끼 고양이"의 임베딩은 비슷하지만, "고양이"와 "비행기"는 멀리 떨어져 있습니다. 이러한 벡터 표현 덕분에 기계가 텍스트 간의 관계를 이해할 수 있으며, 많은 AI 애플리케이션의 기반이 됩니다.

일반적인 사용 사례

사용 사례
설명
RAG (검색 증강 생성)답변을 생성하기 전에 지식 베이스에서 관련 컨텍스트를 검색하는 시스템을 구축——임베딩은 LLM 컨텍스트에 포함할 가장 관련성 높은 문서를 찾아줍니다.
시맨틱 검색문서와 쿼리를 임베딩으로 변환한 후 벡터 유사도로 가장 관련성 높은 문서를 찾습니다——키워드 일치만이 아니라 의미를 이해하므로 키워드 검색보다 더 나은 결과를 제공합니다.
추천 시스템상품, 기사, 동영상 등의 항목과 사용자 선호도에 대한 임베딩을 생성하여 유사한 항목을 추천——공통 키워드가 없어도 벡터 비교로 의미적으로 관련된 항목을 찾을 수 있습니다.
클러스터링 및 분류임베딩 패턴을 분석하여 유사한 문서를 그룹화하거나 분류——임베딩이 비슷한 문서는 보통 같은 주제나 카테고리에 속합니다.
중복 감지임베딩 유사도를 비교하여 중복 또는 거의 중복된 콘텐츠를 감지——내용이 바꿔 표현되었더라도 감지할 수 있습니다.
이상 감지데이터셋의 일반적인 패턴에서 크게 벗어난 임베딩을 찾아 이상치나 특이한 콘텐츠를 식별합니다.
POST/v1/embeddings
Note
업스트림 소스가 요청한 임베딩 모델을 지원하지 않으면 다른 사용 가능한 소스를 시도할 수 있습니다. 해당 모델을 지원하는 소스가 없으면 요청에 오류가 반환됩니다.

매개변수

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
Unsupported. The entire object is ignored and removed before forwarding; it cannot select an upstream or price tier.

기본 요청

from openai import OpenAI

client = OpenAI(
    base_url="https://api.bazaarlink.ai/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://api.bazaarlink.ai/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)}")

임베딩 모델 찾기

임베딩 전용 모델 목록 엔드포인트는 없습니다 — GET /v1/models를 호출한 뒤 output_modalities에 "embeddings"가 포함된 항목을 클라이언트 측에서 필터링하거나, Models 페이지를 둘러보세요.

제한사항

  • 스트리밍 미지원 — 채팅 완성과 달리 임베딩은 항상 완전한 응답으로 반환됩니다.
  • 각 모델에는 최대 입력 길이가 있으며, 이를 초과하는 텍스트는 업스트림에서 잘리거나 거부됩니다.
  • 동일한 입력에 대한 임베딩은 결정론적입니다 — temperature나 무작위성이 개입하지 않습니다.

모범 사례

  • 속도/품질/비용 트레이드오프에 맞는 모델을 선택하세요 — 작은 모델(예: qwen/qwen3-embedding-4b)은 저렴하고 빠르며, 큰 모델(예: openai/text-embedding-3-large)은 일반적으로 더 높은 정확도로 임베딩합니다.
  • 텍스트별로 호출하는 대신 여러 텍스트를 한 번의 요청에 배치로 담으세요 — 왕복 횟수와 오버헤드가 줄어듭니다.
  • 결과를 캐시하세요 — 동일한 입력의 임베딩은 절대 변하지 않으므로, 다시 생성하지 말고 저장해 두세요.
  • 유클리드 거리 대신 코사인 유사도로 비교하세요 — 스케일에 불변하며 고차원 벡터에 더 적합합니다.
  • 각 모델의 컨텍스트 길이에 유의하세요 — 긴 문서는 임베딩 전에 청크로 나눠야 할 수 있습니다.

파라미터

샘플링 파라미터는 토큰 생성 과정을 조정합니다. BazaarLink은 지원되는 파라미터를 업스트림 공급자에 전달합니다; 지원되지 않는 파라미터는 조용히 무시됩니다.

샘플링 파라미터

순수 패스스루 — 로컬 기본값 없음
샘플링 값은 범위 검증 없이 전달됩니다. 모델이 지원 범위 밖의 값을 제한하거나 무시할 수 있습니다.
temperature
number
샘플링 값은 범위 검증 없이 전달됩니다. 모델이 지원 범위 밖의 값을 제한하거나 무시할 수 있습니다.
top_p
number
핵 샘플링 확률 질량. 기본값: 1
top_k
integer
샘플링 값은 범위 검증 없이 전달됩니다. 모델이 지원 범위 밖의 값을 제한하거나 무시할 수 있습니다.
frequency_penalty
number
반복 토큰 패널티. 범위: [-2, 2]. 기본값: 0
presence_penalty
number
존재 기반 토큰 패널티. 범위: [-2, 2]. 기본값: 0
repetition_penalty
number
입력에서 토큰 반복 감소. 범위: (0, 2]. 기본값: 1
min_p
number
상위 토큰 대비 최소 확률. 범위: [0, 1]. 기본값: 0
top_a
number
최고 확률 토큰 기반 동적 top-P. 범위: [0, 1]. 기본값: 0
seed
integer
결정적 샘플링을 위한 정수 시드. 모든 모델에서 보장되지 않음
max_tokens
integer
생성할 최대 토큰 수
n
integer
생성할 완성 수. 기본값: 1
logit_bias
object
토큰 ID를 바이어스 값 [-100, 100]에 매핑하여 샘플링 전 추가. OpenAI 계열 모델에만 적용 — 아래 참고 사항 확인.
logprobs
boolean
각 출력 토큰의 로그 확률 반환. OpenAI 계열 모델에만 적용 — 아래 참고 사항 확인.
top_logprobs
integer
위치당 반환할 최고 확률 토큰 수 (logprobs: true 필요). 범위: 0–20. OpenAI 계열 모델에만 적용 — 아래 참고 사항 확인.
response_format
object
구조화된 JSON 출력 강제. 구조화된 출력 섹션 참조
structured_outputs
boolean
지원하는 제공자에서 엄격한 JSON 스키마 준수 출력을 요청. 그대로 전달
reasoning
object
제공자별 reasoning/thinking 설정. 그대로 전달
reasoning_effort
string
OpenAI o-시리즈 스타일 reasoning 강도: "low", "medium", 또는 "high". 그대로 전달
include_reasoning
boolean
true이면 message.reasoning(스트리밍에서는 delta.reasoning)에 생각 내용을 반환하고, false이면 기본으로 생각하는 모델의 생각을 끕니다(추론 섹션 참조). 따라서 생각 비용이 청구되지 않습니다. reasoning_effort, reasoning, thinking 중 아무것도 보내지 않으면 그 모델들만 기본으로 생각하고 반환하며, 다른 모델은 요청했을 때만 반환합니다
stop
string | string[]
중지 시퀀스 — 만나면 생성 중단
tools
Tool[]
모델이 호출할 수 있는 도구(함수) 목록
tool_choice
string | object
도구 사용 제어: "auto", "none", 또는 특정 도구
parallel_tool_calls
boolean
도구 제공 시 병렬 함수 호출 활성화. 기본값: true. OpenAI 계열 모델에만 적용 — 아래 참고 사항 확인.

크레딧

현재 크레딧 잔액과 누적 API 사용량 조회.

GET/v1/credits
Auth
Bearer token (표준 API 키 sk-bl-...) 필요.

예제 요청

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

응답

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

오류: 401 (키 누락/무효), 403 (정지된 사용자).

생성 세부정보

응답 id 또는 x-request-id 헤더의 불투명한 BazaarLink 요청 ID로 GET /v1/generation을 호출하세요. 비스트리밍 응답에도 같은 ID가 x-generation-id로 포함됩니다. 통계가 표시되기까지 몇 초 걸릴 수 있으므로 404는 잠시 재시도하세요.

GET/v1/generation?id=<generation-id>
Auth
Bearer token (표준 API 키) 필요. 필수 query 파라미터: id.

예제 요청

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

응답

{
  "data": {
    "id": "85e6f35c71a31f19-SJC",
    "model": "openai/gpt-4o",
    "provider": "bazaarlink",
    "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 키의 rate limit 계층과 집계 사용량 카운터 조회 (응답 형식은 업계 표준 키 정보 API와 호환).

GET/v1/key
Auth
Bearer token (표준 API 키) 필요.

응답

{
  "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일~말일. 키에 개별 사용 한도가 설정된 경우(키 생성/수정 시 limit 파라미터), limit / limit_remaining / limit_reset은 해당 한도와 그 기간의 사용량을 반영합니다. 설정되지 않은 경우 limit은 null이며 limit_remaining은 계정 크레딧 잔액으로 대체됩니다. expires_at은 키의 만료 시각(없으면 null)입니다. is_management_key와 is_provisioning_key는 동일한 개념의 별칭으로, 관리 키인 경우 둘 다 true입니다.
BYOK
BazaarLink는 BYOK(자체 키 지참) 프로그램을 제공하지 않으므로 이 엔드포인트는 byok_usage 관련 필드를 반환하지 않습니다.

오류: 401 (auth), 404 (사용자 없음 — 드물게).

오류 코드

오류 응답 형식

오류 envelope는 엔드포인트마다 다릅니다. HTTP 상태와 존재하는 경우 error.type을 사용하세요. error.code는 문자열 또는 숫자이며 생략될 수 있습니다. error.message는 표시용입니다.

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

HTTP 상태 및 오류.코드

오류 envelope는 엔드포인트마다 다릅니다. HTTP 상태와 존재하는 경우 error.type을 사용하세요. error.code는 문자열 또는 숫자이며 생략될 수 있습니다. error.message는 표시용입니다.

코드
이름
설명
424종속성 실패직접 설정한 BYOK 키가 업스트림 제공자에 의해 거부되었습니다. BYOK 설정에서 확인하거나 교체하세요. strict 모드에서만 발생합니다
400잘못된 요청잘못된 요청, 빈 messages 배열, 또는 필수 필드 누락
401승인되지 않음API 키가 누락, 잘못됨, 또는 비활성화됨
402결제 필요계정 크레딧 부족, 키별 지출 한도 도달, 또는 월간/주간 예산 상한 초과
403금지됨계정이 정지되었거나 권한이 없음
404찾을 수 없음Requested model, generation, key, or other resource does not exist
409충돌Resource is not in the required state, such as an incomplete video job
410사라Requested model has been retired and must be replaced
413페이로드가 너무 큼요청 바디가 10 MB 초과; 콘텐츠 크기를 줄이거나 요청을 분할하세요
416범위가 만족스럽지 않음Requested byte range is invalid for generated video content
429요청이 너무 많습니다속도 제한 초과; 재시도 전 Retry-After 헤더를 확인하세요
432무료 한도 소진Tavily 호환 엔드포인트(/v1/search, /v1/extract, /v1/crawl, /v1/map): 무료 검색 한도를 모두 사용했거나 잔액이 0 이하입니다. 크레딧을 충전한 뒤 계속하세요. 응답 본문은 Tavily 형식입니다: {"detail":{"error":"..."}}
500서버 오류BazaarLink 내부 오류
502잘못된 게이트웨이모든 업스트림 소스가 요청을 처리하지 못했습니다. 요청에 오류가 반환됩니다.
503서비스를 이용할 수 없습니다이 모델에 구성된 업스트림 공급자 없음; 관리자에게 문의하세요
504게이트웨이 시간 초과Upstream connection or stream stalled and timed out

기계 판독 가능한 청구 코드

A 402 can represent different controls. Use these stable codes to choose the correct action.

코드
설명
byok_key_invalid직접 설정한 BYOK 키가 업스트림 제공자에 의해 거부되었습니다. BYOK 설정에서 확인하거나 교체하세요. strict 모드에서만 발생합니다.
budget_cap_reachedA weekly or monthly budget cap was reached; raise or reset the cap.
credit_limit_exceededA monthly-billing organization's credit line was exhausted; contact billing.
insufficient_creditsThe prepaid balance is insufficient; add credits.
spend_limit_exceededThe API key reached its daily, weekly, or monthly spend limit.
capacity_unavailableThis model is temporarily at capacity. Retry shortly; the Retry-After header says how long to wait.

Stable error.code catalog

These string codes are emitted by public inference and media paths. Branch on the string code when present; the HTTP status remains the broad failure class.

모델 및 엔드포인트
모델 조회, 수명 주기, 가격 책정, 양식 및 엔드포인트 호환성 오류입니다.
코드
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
이미지 생성 및 편집
이미지 입력, 멀티파트 편집, 출력 및 이미지 파이프라인 오류입니다.
코드
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
capacity_unavailable429
upstream_unavailable502/503
byok_key_invalid424

콘텐츠 검토

모든 요청은 모델로 전달되기 전에 자동 콘텐츠 검토를 거칩니다. 이용 정책을 위반하는 요청은 모델에 전달되지 않고 거부되며 403 오류가 반환됩니다.

차단되는 콘텐츠 카테고리

검토는 당사의 이용 정책(Acceptable Use Policy)에 따라 이루어지며, 주로 다음 카테고리의 콘텐츠를 차단합니다:

  • 성적 착취 콘텐츠
  • 폭력적 위협
  • 불법 행위 실행 안내
  • 생물학적 위해 관련 콘텐츠

403 응답 형식

검토에 의해 차단된 요청은 다음 형식의 오류를 반환합니다:

{
  "error": {
    "message": "Your prompt was blocked by content moderation.",
    "type": "invalid_request_error",
    "code": "content_filter"
  }
}

차단된 요청은 과금되지 않습니다——거부된 요청에 대한 비용은 청구되지 않습니다.

오탐 이의 제기

요청이 잘못 차단되었다고 생각되면 요청 시각과 (가능하다면) request id를 첨부하여 지원팀에 문의해 주세요. 검토해 드리겠습니다.

개인정보 보호

모든 요청은 자동으로 콘텐츠 검토를 거칩니다.

위반으로 판정된 요청은 컴플라이언스 증빙 목적으로 해당 내용을 보관합니다.

그 외 요청은 전체 프롬프트 내용을 보관하지 않습니다.

속도 제한, 예산 및 비상 브레이크

These controls can reject an otherwise valid request and require different recovery actions.

제어
HTTP 상태
식별 방법
요청 속도 제한429문자열 코드 또는 숫자 코드 429입니다. Retry-After와 X-RateLimit-* 헤더를 사용하세요.
속도 제한 페널티 블록429숫자 코드 429 및 임시 제한 메시지; 재시도 후를 사용하십시오.
글로벌 소비 비상 브레이크503숫자 코드 503, 글로벌 지출 한도 메시지 및 30초 또는 300초 후 재시도.
Scoped spend brake429Numeric code 429 and a spend circuit-breaker message naming the scope.
청구 및 예산 관리402위에 나열된 안정적인 청구 문자열 코드를 사용하세요.

오류 envelope는 엔드포인트마다 다릅니다. HTTP 상태와 존재하는 경우 error.type을 사용하세요. error.code는 문자열 또는 숫자이며 생략될 수 있습니다. error.message는 표시용입니다.

비디오 및 미디어 리소스 상태

Video validation commonly returns numeric code 400. Missing jobs return 404, retired models 410, unfinished video content 409, and invalid video byte ranges 416.

재시도 정책

Retry only failures that may recover without changing the request. Honor Retry-After or use exponential backoff with jitter. Do not stack SDK and manual retries.

백오프로 재시도
429, 502, 503, and 504. Check the original generation job before creating another after an ambiguous network failure.
재시도하기 전에 수정하세요
400, 401, 402, 403, 404, 409, 410, 413, and 416. Fix the request, credentials, balance, permissions, resource state, or Range header first.

오류 처리

import random
import time
from openai import OpenAI, APIStatusError

client = OpenAI(
    base_url="https://api.bazaarlink.ai/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-4o",
            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)

스트리밍 오류 형식

토큰 스트리밍 전에 발생한 오류는 JSON 바디와 함께 표준 HTTP 오류 응답을 반환합니다.

스트림이 시작되면 HTTP 응답은 이미 200입니다. 각 SSE 데이터 프레임을 파싱하고, 최상위 error 또는 choices[0].finish_reason === "error"가 나타나면 실패한 불완전 응답으로 처리하세요.

스트림이 시작된 후 실패하면 BazaarLink가 최상위 error 객체가 담긴 마지막 SSE 이벤트를 보내고 이어서 data: [DONE]을 보낼 수 있습니다. 응답을 불완전한 것으로 처리하고, 부분 출력을 완료된 결과로 사용하지 마세요.

data: {"error":{"message":"The request could not be completed.","type":"upstream_error","code":502}}

data: [DONE]

// Branch on error.code; error.type can vary by failure path.

버전 관리

BazaarLink는 단일 안정 API 경로인 /api/v1을 제공합니다 — 관리해야 할 날짜 고정 버전이나 버전 헤더가 없습니다. API는 번호가 매겨진 릴리스가 아니라 지속적으로 발전합니다.

비파괴적 변경

다음은 사전 공지 없이 배포됩니다:

  • 새 엔드포인트
  • 카탈로그에 새 모델 추가
  • 새로운 선택적 요청 매개변수
  • 새로운 응답 필드
  • 선택적 속성을 가진 새 스키마
  • 추가 응답 상태/오류 코드
방어적으로 클라이언트를 작성하세요
인식하지 못하는 응답 필드는 무시하고, enum 형태 필드의 알 수 없는 값에서 실패하지 않도록 하세요 — 카탈로그와 기능이 늘어나면서 새 값이 추가됩니다.

파괴적 변경

이는 드물게 발생하며, 다음을 포함합니다:

  • 엔드포인트, 매개변수, 응답 필드를 제거하거나 이름을 바꾸는 것
  • 필드 타입을 변경하는 것
  • 선택적 매개변수를 필수로 만드는 것

발생하더라도 파괴적 변경은 전체 /v1 표면이 아니라 특정 엔드포인트에만 적용됩니다 — 모든 연동을 한 번에 깨뜨릴 수 있는 단일 버전 업그레이드는 없습니다. 아직 Breaking 태그가 있는 공식 changelog는 게시하지 않습니다(아래 "최신 정보 확인" 참고) — 연동에 중요한 부분이라면, 문서화되지 않은 동작에 의존하기 전에 Support에 문의하세요.

지원 종료 정책

예상해야 할 유일한 정기적인 "파괴적" 이벤트: 업스트림 공급자가 지원을 종료함에 따라 개별 모델이 폐지됩니다. GET /v1/models로 모델의 현재 상태를 조회하세요.

GET https://api.bazaarlink.ai/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 피드는 게시하지 않습니다. 지금은 이 페이지를 직접 확인하거나, GET /v1/models로 모델 상태를 확인하거나, 중요한 연동에 사전 통지가 필요하면 Support에 문의하세요.

Support
Support
Hi! How can we help you?
Send a message and we'll get back to you soon.
API 레퍼런스 | 채팅, 임베딩 및 모델 라우팅