Defapi(api.defapi.org)CHAT + 產圖串接指南
Defapi 是統一 AI 模型閘道(BYOK):一支 key 同時打 OpenAI / Google 等多家模型,適合不想對每家 API 開戶的情境。
本 skill 用於:新專案接入 Defapi 的 chat 或產圖時、debug Defapi 呼叫問題、確認參數 / 模型名稱 / 費用。
最後驗證日期:chat 模型 2026-06-02 / 其餘 2026-05-28(模型清單、價格、size 規則都會變,過期請以官方為準) 官方文件:https://defapi.org/en/user/api
1. 認證
- 所有 endpoint 共用一支 key
- Header:
Authorization: Bearer <DEFAPI_API_KEY> - key 從 https://defapi.org 後台拿,通常
dk-開頭
2. 兩條路線一覽
| 用途 | Endpoint | 同步 / 異步 | 計費單位 |
|---|---|---|---|
| 對話補全(文字 + 多模態看圖) | POST /api/v1/chat/completions |
同步(可選 stream) | per token |
| 產圖 — GPT Image 2 | POST /api/gpt-image/gen → poll |
異步 | per image($0.02) |
| 產圖 — Google Nano Banana 系列 | POST /api/image/gen → poll |
異步 | per image($0.04 / $0.05) |
| 任務輪詢(產圖共用) | GET /api/task/query?task_id=... |
— | — |
⚠️ 注意 endpoint 前綴不一致:chat 是
/api/v1/(OpenAI-compatible)、產圖是/api/(沒有 v1)。
3. CHAT(對話補全)
完全 OpenAI-compatible —— request / response shape 跟 OpenAI 一模一樣。最快的接法是直接用 OpenAI SDK,只改 baseURL。
3.1 模型清單(chat 部分 2026-06-02 重驗)
model 字串 |
對應 | 備註 |
|---|---|---|
openai/gpt-5-nano |
OpenAI gpt-5-nano | GPT-5 最省;回應約 10–15s |
openai/gpt-5-mini |
OpenAI gpt-5-mini | GPT-5 中階 |
openai/gpt-5 |
OpenAI gpt-5 | 旗艦,$0.875 / $7 per 1M tokens |
⚠️ 2026-06-02 實測:
openai/gpt-4o-mini、openai/gpt-4o已下架(回{"code":1404,"message":"model not found"});gpt-4.1 / o4-mini 也不存在。chat 目前只剩上面 3 個 gpt-5 模型。openai/前綴加不加都通。 沒有GET /api/v1/models端點(回 404)—— 要確認可用模型只能逐一 curl 探測。 其他模型(Claude / Gemini / DeepSeek 等)我沒實測 —— 用前到 Defapi 後台 model 頁確認。
3.2 用法 A — OpenAI SDK(推薦,最少改動)
import OpenAI from 'openai'
const client = new OpenAI({
apiKey: process.env.DEFAPI_API_KEY,
baseURL: 'https://api.defapi.org/api/v1',
// 瀏覽器端要加(BYOK SaaS 場景);Node.js 不需要
// dangerouslyAllowBrowser: true,
})
const resp = await client.chat.completions.create({
model: 'openai/gpt-4o',
messages: [
{ role: 'system', content: 'You are a helpful assistant.' },
{ role: 'user', content: 'Hello' },
],
temperature: 0.7,
})
console.log(resp.choices[0].message.content)
console.log(resp.usage) // { prompt_tokens, completion_tokens, total_tokens }
3.3 用法 B — Raw fetch(無依賴)
const resp = await fetch('https://api.defapi.org/api/v1/chat/completions', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.DEFAPI_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
model: 'openai/gpt-4o',
messages: [{ role: 'user', content: 'Hello' }],
temperature: 0.7,
}),
})
if (!resp.ok) throw new Error(`Defapi ${resp.status}: ${await resp.text()}`)
const json = await resp.json()
console.log(json.choices[0].message.content)
3.4 多模態(看圖)
content 改成陣列,每個元素 {type, ...}:
await client.chat.completions.create({
model: 'openai/gpt-4o',
messages: [{
role: 'user',
content: [
{ type: 'text', text: 'What is in this image?' },
{ type: 'image_url', image_url: { url: 'https://example.com/cat.jpg' } },
// 或用 data URI:
// { type: 'image_url', image_url: { url: 'data:image/png;base64,iVBOR...' } },
],
}],
})
3.5 Streaming
const stream = await client.chat.completions.create({
model: 'openai/gpt-4o',
messages: [{ role: 'user', content: 'Write a haiku' }],
stream: true,
})
for await (const chunk of stream) {
process.stdout.write(chunk.choices[0]?.delta?.content ?? '')
}
SSE 原始格式:data: {chunk JSON}\n\n 一行一行送,結尾 data: [DONE]。
3.6 參數
| 欄位 | 範圍 | 預設 |
|---|---|---|
model |
上表 5 個 | 必填 |
messages |
至少 1 條 | 必填 |
temperature |
0–2 | 1.0 |
top_p |
0–1 | 1.0 |
frequency_penalty |
-2 ~ 2 | 0 |
presence_penalty |
-2 ~ 2 | 0 |
stream |
boolean | false |
❓ 以下「沒測過」,用前自己驗:
tools/tool_choice(function calling)、response_format: { type: 'json_object' }(JSON mode)
3.7 錯誤
| HTTP | 意思 |
|---|---|
| 400 | 參數錯(看 detail) |
| 401 | key 無效 / 沒帶 / Invalid API key |
| 500 | server 端錯,可重試 |
回應 body:{ code, message, detail }。
4. 產圖(GPT Image 2 + Google Nano Banana)
共通模式:submit → 拿 task_id → 輪詢 → 拿 output URL。每張圖都這樣跑,沒有同步版本。
4.1 模型清單(2026-05-28)
model 字串 |
Endpoint | 價格/張 | 特性 |
|---|---|---|---|
openai/gpt-image-2 |
/api/gpt-image/gen |
$0.02 | OpenAI · 精準文字渲染 |
google/nano-banana-2 |
/api/image/gen |
$0.04 | Google · 4K · 多語言文字 |
google/nano-banana-pro |
/api/image/gen |
$0.05 | Google · 角色一致 · 電商主圖最強 |
⚠️ Midjourney 系列我在實際專案測過、極不穩(Blend
prompt_is_required不在 spec 但實際強制、Imagine proxy fetch 常失敗、submit→poll 索引延遲產生 404 假陽性)。不推薦接入。
4.2 GPT Image 2
Endpoint: POST https://api.defapi.org/api/gpt-image/gen
const submitResp = await fetch('https://api.defapi.org/api/gpt-image/gen', {
method: 'POST',
headers: {
'Authorization': `Bearer ${KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
model: 'openai/gpt-image-2',
prompt: 'A red coffee mug on white background, product photo',
size: '1024x1024', // 像素字串,規則見下
quality: 'auto', // auto | low | medium | high
images: [ // 選填,圖生圖 / 編輯用,data URI 陣列
'data:image/jpeg;base64,/9j/...',
],
}),
})
const { data: { task_id } } = await submitResp.json()
// 接下去用 4.4 的 pollTask(task_id)
GPT Image 2 — size 4 條硬規則(2026-05-20 實測)
⚠️ 任一條沒滿足 → 立刻 HTTP 400 拒絕。寫程式時送出前先檢查:
- 寬、高都是 16 的倍數
- 長邊 / 短邊 ≤ 3:1(
4:1/1:4不可能) - 任一邊 ≤ 3840px
- 總像素 655,360 ~ 8,294,400(下限約 640×1024,上限 = 3840×2160 = 4K 全幅)
推薦 preset(實測通過,各比例最大解析):
| 比例 | size |
|---|---|
| 1:3 | 1280x3840 |
| 1:2 | 1920x3840 |
| 1:1 | 2880x2880(也可 1024x1024 ~ 2880x2880) |
| 2:1 | 3840x1920 |
| 3:1 | 3840x1280 |
4.3 Google Nano Banana 2 / Pro
Endpoint: POST https://api.defapi.org/api/image/gen(2 / Pro 共用,靠 model 區分)
await fetch('https://api.defapi.org/api/image/gen', {
method: 'POST',
headers: { 'Authorization': `Bearer ${KEY}`, 'Content-Type': 'application/json' },
body: JSON.stringify({
model: 'google/nano-banana-pro',
prompt: 'A red coffee mug on white background',
aspect_ratio: '1:1', // 11 enum,見下
image_size: '2k', // 1k | 2k | 4k(僅 nano-banana 系列吃)
images: [ // 選填,上限 14 張 data URI
'data:image/jpeg;base64,/9j/...',
],
}),
})
aspect_ratio 11 個 enum:auto / 1:1 / 3:2 / 4:3 / 5:4 / 16:9 / 21:9 / 2:3 / 3:4 / 4:5 / 9:16
4.4 輪詢任務(產圖共用)
Endpoint: GET https://api.defapi.org/api/task/query?task_id={id}
Status enum:pending / submitted / in_progress / success / failed
async function pollTask(taskId: string, apiKey: string, opts: {
timeoutMs?: number, intervalMs?: number, signal?: AbortSignal
} = {}): Promise<{ result: Array<{ image: string }> }> {
const timeoutMs = opts.timeoutMs ?? 5 * 60_000
const intervalMs = opts.intervalMs ?? 2000
const MAX_404 = 10 // submit 後索引延遲,前 10 次 404 容忍
let notFoundCount = 0
const startedAt = Date.now()
while (Date.now() - startedAt < timeoutMs) {
if (opts.signal?.aborted) throw new Error('aborted')
await new Promise(r => setTimeout(r, intervalMs))
const resp = await fetch(
`https://api.defapi.org/api/task/query?task_id=${encodeURIComponent(taskId)}`,
{ headers: { 'Authorization': `Bearer ${apiKey}` } },
)
if (resp.status === 404 && notFoundCount < MAX_404) {
notFoundCount++
continue // ⚠️ 重要:不要直接拋,索引延遲
}
if (!resp.ok) throw new Error(`poll ${resp.status}: ${await resp.text()}`)
const json = await resp.json()
if (json.code !== 0) throw new Error(`code=${json.code}: ${json.message}`)
const status = String(json.data?.status ?? '').toLowerCase()
if (status === 'success') return json.data
if (status === 'failed') {
throw new Error(`task failed: ${JSON.stringify(json.data.status_reason)}`)
}
// pending / submitted / in_progress → 繼續輪詢
}
throw new Error(`task ${taskId} timeout`)
}
4.5 輸出格式
{
"code": 0,
"data": {
"status": "success",
"consumed": "0.02000000",
"result": [
{ "image": "https://aisaas.nots.top/tmp/.../output-0.png" }
// 或 data URI:"data:image/png;base64,..."
]
}
}
⚠️ result[].image URL 約 1 小時失效。production code 應立刻下載轉成 blob 或 data URI 存自家 storage。範例:
async function downloadOutput(ref: string): Promise<Blob> {
if (ref.startsWith('data:')) {
// 本來就是 data URI,parse 出來
const resp = await fetch(ref)
return resp.blob()
}
// http URL → fetch 下載
const resp = await fetch(ref, { mode: 'cors' })
if (!resp.ok) throw new Error(`download ${resp.status}`)
return resp.blob()
}
CORS 注意:第三方 CDN(google.datas.systems、aisaas.nots.top 等)CORS header 不一定友善。瀏覽器端 fetch 可能 opaque,建議走後端代理或 server-side 下載。
4.6 多張變體 / n>1
API 沒有原生 n 參數。要產 N 張變體就平行送 N 個任務:
const tasks = Array.from({ length: n }, () => submitOneTask(input))
const taskIds = await Promise.all(tasks)
const results = await Promise.all(taskIds.map(id => pollTask(id, KEY)))
4.7 輸入圖片(image-to-image / 編輯)
- 三家共用
images陣列(GPT Image 2)或一樣是images(Google) - 吃 data URI,格式
data:image/jpeg;base64,/9j/...或data:image/png;base64,... - 送出前壓縮(實測:OpenAI / Google 後端對「proxy fetch 大圖」常失敗,跳「Failed to fetch image data via proxy service」)。建議:長邊 ≤ 1024px、JPEG quality 0.85
- 上限:Google 14 張;GPT Image 2 多張可行但沒實測上限
4.8 產圖錯誤碼
| HTTP | 場景 |
|---|---|
| 400 | size / aspect_ratio 不符規則(errors 欄位會講明原因) |
| 401 | key 錯 |
| 500 | server 端,可重試 |
submit response 的 code !== 0(即使 HTTP 200)也算失敗,看 message。
5. 常見坑(實戰累積)
| 坑 | 解法 |
|---|---|
| submit 200 但 query 立刻 404 | 索引延遲,前 10 次 404 當「還沒準備好」繼續輪詢(已寫進 §4.4) |
| 輸出 URL 過幾天就掛 | 收到後立刻下載,別存 URL |
大張原圖丟進 images → proxy fetch 失敗 |
送前壓到長邊 ≤ 1024、JPEG 0.85 |
| GPT Image 2 隨意 size → 400 | 嚴格遵守 §4.2 的 4 條規則,送前先檢查 |
| n>1 變體 | 平行送 N 個任務,沒有 n 參數 |
| CORS:瀏覽器 fetch 輸出 CDN | 走後端代理 / Edge Function 中轉 |
| 同步等結果 vs 異步輪詢 | Defapi 產圖只有異步,別期待同步;Vercel hobby 10 秒 timeout 也走不完 |
| price drift | 用前去後台確認,別寫死 |
6. 快速驗證 key
第一次拿到 key,跑這個確認能通:
export DEFAPI_API_KEY=dk-xxxxx
node ~/.claude/skills/defapi/scripts/test-key.mjs # 只測 chat(免費)
node ~/.claude/skills/defapi/scripts/test-key.mjs --image # 也測產圖($0.02)
腳本:見 scripts/test-key.mjs
7. 不確定 / 沒實測的部分
⚠️ 用前自己驗,別讓 Claude 猜:
- chat 的
tools/tool_choice(function calling) - chat 的
response_format: { type: 'json_object' }(JSON mode) - chat 多模態下的 streaming
- embeddings — 2026-06-03 實測:
POST /api/v1/embeddings回 404 Route not found,DefAPI 沒有 embeddings 端點。 要算向量得直接打 OpenAI/Google 的 embedding API 或用本地模型,無法走 DefAPI。 - TTS / STT / moderation endpoints — 沒見過
- Claude / Gemini / DeepSeek / Qwen 等非 OpenAI 模型 — 後台可能有,沒測過
- 是否有獨立 image edit endpoint(我都用
/gen+images達成) - Rate limit 規則 / quota tier
- 最新模型目錄與定價(2026-05-28 之後可能變)
8. 更新此 SKILL
每次 Defapi 改 API 或加新模型,更新流程:
- 到 https://defapi.org/en/user/api 看 model 列表
- 對照本 SKILL §3.1 / §4.1,有差異就更新
- 更新檔頭「最後驗證日期」
scripts/test-key.mjs跑一次確認還通