更新日期:2026-06-23
适用场景
Crazyrouter 对 OpenAI SDK 兼容接口提供统一接入。聊天、Responses API、图片、音频、嵌入和模型列表优先使用官方 OpenAI SDK;视频、Kling、Luma、Suno、Midjourney 等异步或厂商原生接口使用同一个 API Key,通过 fetch 调用 Crazyrouter 原生路径。
默认国际 API 入口:
https://api.crazyrouter.com
OpenAI SDK 需要填写带 /v1 的地址:
https://api.crazyrouter.com/v1
不要把 OpenAI SDK 的 baseURL 写成 https://api.crazyrouter.com,否则 SDK 会少拼 /v1。也不要写成 https://api.crazyrouter.com/v1/chat/completions,否则 SDK 会重复拼路径。
安装 SDK
Node.js 建议使用 18 或更高版本。Node.js 18+ 已内置 fetch、FormData 和 Blob。
配置环境变量
macOS / Linux:
export CRAZYROUTER_API_KEY="sk-your-api-key"
export CRAZYROUTER_BASE_URL="https://api.crazyrouter.com"
Windows PowerShell:
$env:CRAZYROUTER_API_KEY = "sk-your-api-key"
$env:CRAZYROUTER_BASE_URL = "https://api.crazyrouter.com"
创建 SDK Client
import OpenAI from 'openai';
const apiKey = process.env.CRAZYROUTER_API_KEY;
if (!apiKey) {
throw new Error('Missing CRAZYROUTER_API_KEY');
}
const baseURL = process.env.CRAZYROUTER_BASE_URL ?? 'https://api.crazyrouter.com';
export const client = new OpenAI({
apiKey,
baseURL: `${baseURL}/v1`,
timeout: 180_000,
});
Chat Completions
const response = await client.chat.completions.create({
model: 'gpt-5.5',
messages: [
{ role: 'system', content: 'You are concise.' },
{ role: 'user', content: 'Say sdk-ok and nothing else.' },
],
max_tokens: 16,
});
console.log(response.choices[0]?.message?.content);
流式输出
const stream = await client.chat.completions.create({
model: 'gpt-5.5',
messages: [{ role: 'user', content: 'Count from 1 to 3.' }],
max_tokens: 32,
stream: true,
});
for await (const chunk of stream) {
process.stdout.write(chunk.choices[0]?.delta?.content ?? '');
}
模型列表
const models = await client.models.list();
for (const model of models.data.slice(0, 10)) {
console.log(model.id);
}
Embeddings
const embedding = await client.embeddings.create({
model: 'text-embedding-3-small',
input: 'Crazyrouter SDK test',
});
console.log(embedding.data[0].embedding.length);
Responses API
Responses API 适合支持 /v1/responses 的 GPT 系列模型。
const response = await client.responses.create({
model: 'gpt-5.5',
input: 'Return only: responses-ok',
max_output_tokens: 16,
});
console.log(response.output_text);
Claude 模型不要放到 Responses API 路径里测试。Claude 推荐使用 /v1/messages 或 OpenAI-compatible /v1/chat/completions。
图片、音频和转录
OpenAI-compatible 图片和音频接口也使用同一个 SDK client。
const image = await client.images.generate({
model: 'gpt-image-2',
prompt: 'A simple white mug on a clean table',
size: '1024x1024',
output_format: 'png',
});
console.log(image.data[0]?.url);
const speech = await client.audio.speech.create({
model: 'tts-1',
voice: 'alloy',
input: 'Hello from Crazyrouter.',
});
const audio = Buffer.from(await speech.arrayBuffer());
console.log(audio.length);
原生异步任务接口
视频、Kling、Luma、Suno、Midjourney 等异步任务通常不是 OpenAI SDK 方法,而是 Crazyrouter 原生 HTTP 路径。仍然使用同一个 API Key。
async function crazyrouterFetch<T>(
path: string,
options: RequestInit & { json?: Record<string, unknown> } = {},
): Promise<T> {
const response = await fetch(`${baseURL}${path}`, {
...options,
headers: {
Authorization: `Bearer ${apiKey}`,
...(options.json ? { 'Content-Type': 'application/json' } : {}),
...options.headers,
},
body: options.json ? JSON.stringify(options.json) : options.body,
});
const body = await response.json().catch(() => ({}));
if (!response.ok) {
throw new Error(`Crazyrouter API error ${response.status}: ${JSON.stringify(body)}`);
}
return body as T;
}
提交统一视频任务:
const task = await crazyrouterFetch<{
id?: string;
task_id?: string;
data?: { task_id?: string };
}>('/v1/video/create', {
method: 'POST',
json: {
model: 'veo-3.1-fast',
prompt: 'A quiet city street after rain, cinematic lighting',
aspect_ratio: '16:9',
size: '1080P',
},
});
const taskId = task.data?.task_id ?? task.task_id ?? task.id;
console.log(taskId);
查询任务:
const result = await crazyrouterFetch(
`/v1/video/query?task_id=${encodeURIComponent(taskId!)}`,
);
console.log(result);
上传本地图片
需要把本地参考图传给 image-to-video、vision 或图片编辑接口时,先上传到 Crazyrouter 临时存储。
import { readFile } from 'node:fs/promises';
import { basename } from 'node:path';
async function uploadImage(filePath: string) {
const bytes = await readFile(filePath);
const form = new FormData();
form.append(
'file',
new Blob([bytes], { type: 'image/png' }),
basename(filePath),
);
form.append('purpose', 'model_input');
const response = await fetch(`${baseURL}/v1/files/uploads`, {
method: 'POST',
headers: {
Authorization: `Bearer ${apiKey}`,
},
body: form,
});
const body = await response.json();
if (!response.ok) {
throw new Error(`Upload failed: ${JSON.stringify(body)}`);
}
return body as {
id: string;
url: string;
mime_type: string;
size: number;
expires_at: string;
};
}
const uploaded = await uploadImage('./reference.png');
console.log(uploaded.url);
临时上传 URL 默认用于模型输入,不是永久图床。业务长期资产请使用自己的存储。
完整 SDK 测试脚本
保存为 crazyrouter-sdk-smoke.mjs:
import OpenAI from 'openai';
const apiKey = process.env.CRAZYROUTER_API_KEY;
const rootBaseURL = process.env.CRAZYROUTER_BASE_URL ?? 'https://api.crazyrouter.com';
if (!apiKey) {
throw new Error('Set CRAZYROUTER_API_KEY before running this test.');
}
const client = new OpenAI({
apiKey,
baseURL: `${rootBaseURL}/v1`,
timeout: 180_000,
});
const checks = [];
async function check(name, fn) {
const started = Date.now();
try {
const detail = await fn();
checks.push({ name, ok: true, ms: Date.now() - started, detail });
console.log(`ok ${name}: ${detail}`);
} catch (error) {
checks.push({ name, ok: false, ms: Date.now() - started, detail: error.message });
console.error(`fail ${name}: ${error.message}`);
}
}
await check('models.list', async () => {
const models = await client.models.list();
return `${models.data.length} models`;
});
await check('chat.completions.create', async () => {
const response = await client.chat.completions.create({
model: 'gpt-5.5',
messages: [{ role: 'user', content: 'Return exactly sdk-ok' }],
max_tokens: 16,
});
return response.choices[0]?.message?.content?.trim() ?? '(empty)';
});
await check('chat.completions.stream', async () => {
const stream = await client.chat.completions.create({
model: 'gpt-5.5',
messages: [{ role: 'user', content: 'Return exactly stream-ok' }],
max_tokens: 16,
stream: true,
});
let text = '';
for await (const chunk of stream) {
text += chunk.choices[0]?.delta?.content ?? '';
}
return text.trim() || '(empty stream)';
});
await check('embeddings.create', async () => {
const response = await client.embeddings.create({
model: 'text-embedding-3-small',
input: 'Crazyrouter SDK smoke test',
});
return `${response.data[0].embedding.length} dimensions`;
});
await check('raw /v1/video/query route shape', async () => {
const response = await fetch(`${rootBaseURL}/v1/video/query?task_id=doc-smoke-test`, {
method: 'GET',
headers: {
Authorization: `Bearer ${apiKey}`,
},
});
const text = await response.text();
if (response.status === 404 && text.toLowerCase().includes('not found')) {
throw new Error('route returned a path-level 404');
}
return `route reachable, status ${response.status}`;
});
const failed = checks.filter((item) => !item.ok);
console.log(JSON.stringify({ total: checks.length, failed: failed.length, checks }, null, 2));
if (failed.length > 0) {
process.exit(1);
}
运行:
npm install openai
node crazyrouter-sdk-smoke.mjs
测试通过后,你应至少看到:
models.list 返回模型数量
chat.completions.create 返回文本
chat.completions.stream 收到流式文本
embeddings.create 返回向量维度
/v1/video/query 返回任务不存在或其他业务状态,说明原生异步任务查询路由可达
常见错误
| 问题 | 处理方式 |
|---|
401 Unauthorized | 检查 CRAZYROUTER_API_KEY 是否设置,格式是否为 Authorization: Bearer sk-... |
404 或 /v1/v1/... | OpenAI SDK 使用 https://api.crazyrouter.com/v1,原生 HTTP 使用 https://api.crazyrouter.com 加完整路径 |
| Chat 可用但 Responses 不可用 | 检查模型是否支持 /v1/responses,Claude 不要走 Responses API |
| 图片或视频超时 | 提高 SDK timeout,视频类任务优先使用异步任务查询 |
| 403 Forbidden | Token 没有对应模型权限,或模型不在该 token 的可用范围内 |