任务与计费单位说明
1 个批量任务 task = 客户上传 1 张参考图 + 提交多段提示词 + 系统生成多张图片。
计费单位不是 task,而是 image / item,也就是单张成功生成的图片。
例如:1 张参考图 + 8 段提示词 = 1 个 task,里面包含 8 个 image item。成功 8 张扣 8 张图片额度;如果成功 6 张、失败 2 张,则只扣 6 张图片额度,失败 2 张会退回额度。
{
"task_unit": "batch_task",
"image_unit": "image",
"billing_unit": "successful_image",
"max_images_per_task": 8,
"example": "1 reference image + 8 prompts = 1 task with 8 generated images"
}
目录
任务与计费单位说明 基础信息 鉴权方式 提交生成任务 查询任务状态 任务状态说明 轮询频率限制 失败重试 计费与退款 额度查询 客户端示例 错误处理1. 基础信息
| 项目 | 说明 |
|---|---|
| 接口域名 | https://vip.hebokuajing.xyz |
| 数据格式 | 请求和响应均使用 JSON |
| 鉴权方式 | HTTP Header 中传入 Authorization: Bearer YOUR_API_KEY |
| 任务模式 | 异步任务。提交后返回 task_id,客户端轮询查询结果。 |
| 计费规则 | 成功生成才扣费。最终失败会退回预占额度。 |
说明:提交任务后不会立即返回图片,而是返回任务 ID。客户端需要通过查询接口获取任务进度和最终图片。
2. 鉴权方式
所有接口都需要在请求头中携带 API Key:
Authorization: Bearer YOUR_API_KEY
Content-Type: application/json
请妥善保管 API Key,不要暴露在网页前端源码中。桌面客户端或服务端程序可直接调用;浏览器前端建议通过自己的后端转发请求。
3. 提交图片生成任务
接口地址
POST /v1/ecom/batch
完整地址
https://vip.hebokuajing.xyz/v1/ecom/batch
请求参数
| 字段 | 类型 | 是否必填 | 说明 |
|---|---|---|---|
| image_url | string | 是 | 产品图片 URL,必须是公网可访问地址。 |
| model | string | 否 | 模型名称,默认可使用 gpt-image-2-1k。 |
| size | string | 否 | 请求尺寸,例如 1024x1024。 |
| aspect_ratio | string | 否 | 图片比例,例如 1:1、3:4、4:3。 |
| prompts | array<string> | 是 | 提示词数组。每条提示词生成一张图片。 |
比例说明
| aspect_ratio | 实际生成方向 | 说明 |
|---|---|---|
| 1:1 | 方图 | 适合主图、商品展示图。 |
| 3:4 / 2:3 / 9:16 | 竖图 | 适合电商广告图、竖版海报。 |
| 4:3 / 3:2 / 16:9 | 横图 | 适合横版广告、Banner。 |
请求示例
curl -X POST "https://vip.hebokuajing.xyz/v1/ecom/batch" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"image_url": "https://example.com/product.jpg",
"model": "gpt-image-2-1k",
"size": "1024x1024",
"aspect_ratio": "3:4",
"prompts": [
"Use this product image as exact reference. Create a premium ecommerce vertical poster."
]
}'
成功响应示例
{
"success": true,
"task_id": "ecom_1783178612_7256b0ad0b",
"job_id": "ecom_1783178612_7256b0ad0b",
"status": "queued",
"total": 1,
"aspect_ratio": "3:4",
"message": "任务已进入队列",
"poll_url": "/v1/ecom/tasks/ecom_1783178612_7256b0ad0b",
"quota": {
"enabled": true,
"level": "vip1",
"daily_limit / daily_image_limit": 40,
"used_before": 3,
"reserved / reserved_images": 1,
"used_after": 4,
"remaining / remaining_images": 36
}
}
提交成功后,客户端需要保存
task_id,后续通过查询接口获取任务状态。
4. 查询任务状态
接口地址
GET /v1/ecom/tasks/{task_id}
请求示例
curl "https://vip.hebokuajing.xyz/v1/ecom/tasks/ecom_1783178612_7256b0ad0b" \
-H "Authorization: Bearer YOUR_API_KEY"
生成中响应示例
{
"task_id": "ecom_xxx",
"status": "processing",
"success_count": 0,
"failed_count": 0,
"processing_count": 1,
"items": [
{
"task_id": "item_xxx",
"status": "processing",
"retry_count": 0,
"max_retries": 6,
"manual_retry_allowed": false
}
]
}
成功响应示例
{
"task_id": "ecom_xxx",
"status": "completed",
"success_count": 1,
"failed_count": 0,
"results": [
{
"task_id": "item_xxx",
"status": "success",
"image_url": "https://image.example.com/result.png",
"retry_count": 0
}
],
"quota": {
"reserved / reserved_images": 1,
"billable": 1,
"refunded": 0
}
}
失败响应示例
{
"task_id": "ecom_xxx",
"status": "failed",
"success_count": 0,
"failed_count": 1,
"failed_items": [
{
"task_id": "item_xxx",
"status": "failed",
"retry_count": 6,
"max_retries": 6,
"retryable": true,
"manual_retry_allowed": true,
"error_message": "HTTP 500: system error"
}
],
"quota": {
"reserved / reserved_images": 1,
"billable": 0,
"refunded": 1
}
}
5. 任务状态说明
| 状态 | 说明 | 客户端行为 |
|---|---|---|
| queued | 任务已进入队列,等待处理。 | 继续轮询。 |
| processing | 任务正在处理。 | 继续轮询。 |
| retrying | 任务失败后正在自动重试。 | 继续轮询,不要手动重试。 |
| completed | 任务全部成功。 | 停止轮询,展示图片。 |
| failed | 任务最终失败。 | 停止轮询,可显示重试按钮。 |
| partial_failed | 部分成功,部分失败。 | 展示成功图片,并允许重试失败项。 |
6. 轮询频率限制
为避免客户端过于频繁查询任务状态,服务端对轮询做了频率限制。
| 任务创建后时间 | 最小查询间隔 |
|---|---|
| 0 - 30 秒 | 最少 5 秒查一次 |
| 30 - 180 秒 | 最少 10 秒查一次 |
| 180 秒以后 | 最少 20 秒查一次 |
| completed / failed 后 | 客户端应停止轮询。如继续查询,最少 10 秒一次。 |
单个任务最多允许:
- 1 小时内最多查询 200 次。
- 任务超过 1 小时还未结束时,服务端会限制高频查询。
查询太频繁时的响应
HTTP/1.1 429 Too Many Requests
Retry-After: 5
{
"detail": "Polling too frequently",
"task_id": "ecom_xxx",
"status": "processing",
"min_interval": 5,
"retry_after": 5
}
HTTP 429 不是任务失败。客户端收到 429 后,应等待
retry_after 秒,再继续查询同一个 task_id。不要重新提交任务。
7. 失败重试
任务最终失败后,如果失败项里有 manual_retry_allowed: true,客户端可以显示“重新生成”按钮。
重试接口
POST /v1/ecom/tasks/{原始task_id}/retry-items
请求示例
curl -X POST "https://vip.hebokuajing.xyz/v1/ecom/tasks/ecom_xxx/retry-items" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"task_ids": ["item_xxx"]
}'
响应示例
{
"success": true,
"parent_task_id": "ecom_xxx",
"retry_task_id": "ecom_retry_xxx",
"retry_job_id": "ecom_retry_xxx",
"status": "queued",
"total_retry_items": 1
}
重试成功后,客户端应改为轮询新的
retry_task_id,不要继续轮询旧任务等待新结果。
8. 计费与退款规则
| 情况 | 是否扣费 | 说明 |
|---|---|---|
| 任务提交成功 | 预占额度 | 系统会先预占对应图片数量的额度。 |
| 图片生成成功 | 扣费 | 只按成功生成的图片扣费。 |
| 自动重试中 | 不重复扣费 | 自动重试次数不额外扣费。 |
| 最终失败 | 不扣费 | 预占额度会退回。 |
| 手动重试成功 | 扣费 | 重试任务成功后正常扣费。 |
| 手动重试失败 | 不扣费 | 重试任务失败后预占额度退回。 |
客户端可以根据返回的
quota.billable 和 quota.refunded 展示本次任务是否扣费。
9. 额度查询
查询当前额度
GET /v1/ecom/quota
请求示例
curl "https://vip.hebokuajing.xyz/v1/ecom/quota" \
-H "Authorization: Bearer YOUR_API_KEY"
响应示例
{
"user_id": "3",
"quota": {
"enabled": true,
"level": "vip1",
"daily_limit / daily_image_limit": 40,
"used": 4,
"remaining / remaining_images": 36
}
}
10. 客户端 JavaScript 示例
提交任务
async function createImageTask(apiKey, imageUrl, prompt) {
const res = await fetch("https://vip.hebokuajing.xyz/v1/ecom/batch", {
method: "POST",
headers: {
"Authorization": `Bearer ${apiKey}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
image_url: imageUrl,
model: "gpt-image-2-1k",
size: "1024x1024",
aspect_ratio: "3:4",
prompts: [prompt]
})
});
const data = await res.json();
if (!res.ok) {
throw new Error(data.detail || "Create task failed");
}
return data.task_id;
}
轮询任务
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
async function pollTask(apiKey, taskId) {
const start = Date.now();
while (true) {
const res = await fetch(`https://vip.hebokuajing.xyz/v1/ecom/tasks/${taskId}`, {
headers: {
"Authorization": `Bearer ${apiKey}`
}
});
if (res.status === 429) {
let retryAfter = Number(res.headers.get("Retry-After")) || 20;
try {
const data = await res.json();
retryAfter = data.retry_after || retryAfter;
} catch (e) {}
await sleep(retryAfter * 1000);
continue;
}
const data = await res.json();
if (data.status === "completed") {
return {
status: "completed",
images: data.results || [],
task: data
};
}
if (data.status === "failed") {
return {
status: "failed",
failed_items: data.failed_items || [],
task: data
};
}
if (data.status === "partial_failed") {
return {
status: "partial_failed",
success_items: (data.results || []).filter(x => x.status === "success"),
failed_items: data.failed_items || [],
task: data
};
}
const age = (Date.now() - start) / 1000;
let delay = 20000;
if (age <= 30) {
delay = 5000;
} else if (age <= 180) {
delay = 10000;
} else {
delay = 20000;
}
await sleep(delay);
}
}
重试失败项
async function retryFailedItems(apiKey, originalTaskId, failedItems) {
const itemIds = failedItems
.filter(item => item.manual_retry_allowed)
.map(item => item.task_id);
if (itemIds.length === 0) {
throw new Error("No retryable items");
}
const res = await fetch(`https://vip.hebokuajing.xyz/v1/ecom/tasks/${originalTaskId}/retry-items`, {
method: "POST",
headers: {
"Authorization": `Bearer ${apiKey}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
task_ids: itemIds
})
});
const data = await res.json();
if (!res.ok) {
throw new Error(data.detail || "Retry failed");
}
return data.retry_task_id;
}
11. 常见错误处理
| HTTP 状态 | 含义 | 客户端处理方式 |
|---|---|---|
| 200 | 请求成功 | 读取 JSON 中的 status 判断任务状态。 |
| 400 | 请求参数错误 | 检查 image_url、prompts、aspect_ratio 等参数。 |
| 401 / 403 | API Key 无效或无权限 | 检查 Authorization Header。 |
| 429 | 查询太频繁 | 读取 retry_after,等待后继续查询同一个 task_id。 |
| 500 | 服务异常 | 稍后重试请求;不要短时间高频重复提交。 |
任务失败请以查询接口返回的
status=failed 为准,不要把 HTTP 429 当成任务失败。