图片幂等提交与原请求恢复
图片原响应保留 10 小时;提交响应丢失后,可通过只读查询恢复原任务或结果,避免重复生成。
图片幂等提交与原请求恢复
第一次提交就携带 Idempotency-Key,并在发送前保存它。 无法给先前未携带 key 的请求补加幂等保护。提交响应丢失后,使用同一个 key 做认证 GET 查询,不要创建替代生成。
覆盖范围
按接口接入,不维护模型白名单:当前和未来使用以下接口的图片模型自动获得保护,包括 Gemini、GPT Image、Seedream、Grok 和 Midjourney。幂等保护不会让原本不支持的模型/接口组合变成可用。
POST /v1/images/generations、/v1/images/generations/async。POST /v1/images/edits、/v1/images/edits/async、/v1/edits、/v1/images/variations。/v1/midjourney/generations及其/imagine别名、旧版/mj/submit/*路径。- 为覆盖多模态出图,带 key 的
POST /v1/chat/completions、/v1/responses,以及/v1/models/{model}:generateContent原生 Gemini 路径也采用相同规则,包括:predict、:streamGenerateContent。这些接口的纯文本请求携带 key 时同样生效。流式输出会缓冲后持久化再返回,不再逐段推送,建议使用非流式请求。
不携带该请求头时保留原有行为。Seedance 使用独立的视频幂等契约。
请求头、作用域与冲突
Authorization: Bearer YOUR_API_KEY
Idempotency-Key: image-order-123-attempt-1
Content-Type: application/json
key 为 8–128 个可见 ASCII 字符,不含空格。作用域是提交账户,覆盖全部受保护接口。同账户另一把有效 API key 可以找回回执和原响应;仍检查账户状态、密钥吊销/过期与 IP 限制。额度耗尽的 key 仍能恢复原请求,首次执行仍须通过正常额度检查。APIMaster 与其他服务的账户、key 和回执相互独立,跨服务不会去重。
同 key、同请求并发或重发只允许一次原执行,不会再次生成和计费。已有成功响应且尚未过期时原样回放并带 Idempotency-Replayed: true;成功响应已过期时返回 HTTP 410 submission_response_expired 与原回执,不重新执行;处理中或结果不明时返回 HTTP 202 与原回执。
同 key 改变接口路径、模型、正文、有效分组或显式固定渠道,返回 HTTP 409、error.code = idempotency_conflict。JSON 正文按字节精确比较,包括空白、字段顺序、数字写法和省略/显式字段;请保留首次正文。GET 恢复不需要正文。
multipart 允许 boundary 和文件名变化;表单值、上传字段名、文件字节、同字段的文件顺序必须一致。重复的普通字段会被拒绝。不得修改参考图后复用原 key。
原响应正文自保存起保留 10 小时,之后自动清理;此规则同样适用于历史响应。回执、请求指纹、执行及账务状态继续保留,不自动复用 key。正文到期不会授权重新执行。原响应中的图片 URL 有独立有效期,请及时下载。
取回接口保留原 HTTP 状态码和完整响应内容(包括 Base64 图片字段),无需处理额外的存储链接。若暂时返回 HTTP 503 submission_storage_unavailable,请重试同一只读查询,不要因此新建生成请求;保留期到期仍返回 HTTP 410。
平台先持久化账户/key 占位,再进入生成和计费。带 key 的请求关闭自动换渠道重试和慢任务并发补发;结果不明时不会内部创建替代生成。这是可选能力:不携带 Idempotency-Key 的请求保留原有 fallback 行为,不具备本页的原提交恢复保证。
不再 POST,直接找回原任务或结果
# 只读查询原提交回执
curl --fail-with-body 'https://apimaster.ai/v1/image-submissions/by-key' \
-H 'Authorization: Bearer YOUR_API_KEY' \
-H 'Idempotency-Key: image-order-123-attempt-1'
# 取回已保存的原 HTTP 正文和状态码
curl --fail-with-body 'https://apimaster.ai/v1/image-submissions/by-key/response' \
-H 'Authorization: Bearer YOUR_API_KEY' \
-H 'Idempotency-Key: image-order-123-attempt-1'
两种 GET 都要求认证,且只读:不创建任务、不生成、不轮询上游、不结算或退款、不重新提交。返回 Cache-Control: no-store、X-Image-Submission-Id 和 X-Original-Request-Id。
回执位于 data。/response 在可用时返回原响应正文和原 HTTP 状态码,尚未就绪时返回 202 与回执;已过期则返回 HTTP 410、error.code = submission_response_expired,并附带原回执。response_available 表示正文当前可读取,response_expired 和 response_expires_at 表示过期状态及时间。过期不代表未执行或可安全重发。原响应可能是 data[0].task_id、同步图片 data[].url / b64_json、Midjourney 批次或原生多模态结果。得到原任务 ID 后使用该模型原有的任务 GET 接口和原模型 ID 继续查询。恢复接口不转换结果格式,也不延长原图片链接有效期。
什么情况下可以创建新尝试
data.status |
含义 | 是否允许替代生成 |
|---|---|---|
pending、submitting |
原请求仍在执行 | 不允许,继续查询原回执 |
accepted |
已保存原成功响应;异步任务可能仍在运行 | 不允许,取回原响应并查询原任务 |
acceptance_unknown |
尚无法确认上游是否受理 | 不允许,等待最终重试决定或联系支持 |
not_accepted |
在进入生成、业务和计费逻辑之前已拒绝 | 安全重试字段成立后,修正原因并使用新 key |
closed_retry_allowed |
平台已确认无预扣或完成退款,关闭这笔受理不明的图片请求 | 允许使用新 key;原请求最终净扣费为零 |
创建新尝试前,必须同时确认 new_submission_safe = true、retry_safe = true、billing_final = true、net_charge = 0。not_accepted 同时返回 acceptance_final = true、billing_status = final_zero。closed_retry_allowed 则返回 acceptance_final = false、upstream_acceptance = unknown,其 billing_status 为 refunded 或 final_zero。允许重试是平台的账务承诺,不代表上游确定没有执行原请求。关闭后即使上游产生费用,也由 APIMaster 承担,不再向客户追扣原请求费用。
该关闭机制覆盖图片生成、编辑、变体及 Midjourney 接口上的所有模型;混合文字/图片入口根据已配置的图片定价、明确的图片输出模态或图片生成工具识别,纯文字请求不适用。首次提交必须携带 Idempotency-Key,才能建立持久回执。
对于原响应已保存、没有已知任务 ID的受理不明图片请求,默认核实窗口为原响应保存后 10 分钟,后台约每分钟检查一次。后台根据可取得的上游账务证据与挂账状态核实,完成必要退款,并在有持久化零净扣费证据后关闭回执。这不是“10 分钟必定结束”的时限:数据库或退款失败、缺少账务证据时,仍保持 retry_safe = false。缺少账务证据的历史记录、未保存完整响应的中断执行,以及已有异步任务 ID 的请求,不会仅因时间过去就允许重试;已有任务请继续查询原任务。
{
"data": {
"status": "closed_retry_allowed",
"acceptance_final": false,
"upstream_acceptance": "unknown",
"retry_safe": true,
"new_submission_safe": true,
"billing_status": "refunded",
"billing_final": true,
"net_charge": 0,
"next_action": "retry_with_new_key"
}
}
待处理或受理不明状态仍返回 billing_status = unverified、billing_final = false、net_charge = null。正数 retry_after_seconds 表示初始核实窗口的剩余秒数,归零不代表退款或关闭必定完成。
旧 key 永久关联旧回执。 用旧 key 重发相同请求只返回 HTTP 202 和已关闭回执,不再次生成或扣费。下一次生成使用新 key。/response 在 10 小时保留期内返回原 HTTP 正文与状态码,因此可能返回原来的 500 或 524;到期后返回 410 submission_response_expired;当前是否允许重试以 /by-key 回执为准。两个 GET 接口都不会触发生成、对账或退款。
查不到回执仍返回 404、error.code = submission_not_found、error.retry_safe = false,不等于 not_accepted,也不授权重试。请使用同一服务、原提交账号,并在 Idempotency-Key 请求头中传入完全一致的原 key,不要仅放在查询参数中。同账号的另一把有效 API key 也可查询;持续 404 时请保留原 request ID 联系支持。
结构化错误
invalid_idempotency_key:key 格式不合法;不说明另一笔原提交的结果。idempotency_conflict:key 对应的请求不同,恢复原请求,不要覆盖。submission_not_found:暂未查到回执,不授权重发。submission_storage_unavailable、submission_claim_unavailable:临时存储或执行占位故障,继续 GET 查询原 key。submission_response_expired:原响应已超过 10 小时保留期,正文不再提供;原执行及账务状态仍可查询,同 key 不会重新执行。submission_response_too_large:原响应超过 64 MiB 恢复缓冲上限,使用已知原任务 ID 或联系支持,不重新生成。- 适用适配器中的
do_request_failed、read_response_body_failed、image_generation_timeout:传输、读取或等待故障,不能证明未接受。 get_channel_failed:渠道选择失败;也可能发生在前一渠道尝试之后的 fallback 选择阶段,不能仅凭此代码保证此前未提交。model_not_found且消息含no non-exclusive channel available:筛选时没有路由同时满足模型、请求能力和用户渠道偏好,不一定是模型 ID 不存在;代码本身不证明最终受理或账务状态。image_channels_exhausted:至少尝试过一个图片渠道后,可用渠道已耗尽;原始上游错误保留在使用日志中,不能认定请求从未到达上游。
HTTP 408/429/5xx 或上游特有错误均不是统一的安全重试信号。响应丢失后,保留原 key、正文、UTC 时间、模型、接口及已收到的 request ID;不要向支持人员发送 API key。
错误日志中的 quota: 0 只描述该日志行,不证明上游未创建任务,也不证明所有预扣和结算已最终完成。上游 HTTP 500 或 524 没有返回任务 ID 时,不能仅据此改成 not_accepted。回执查询即使返回 HTTP 200,正文状态仍可能为 acceptance_unknown。
登录后的图片体验页代理
/api/playground/image 会透传调用方提供的 Idempotency-Key 和原回执标识。携带同一个请求头访问 GET /api/playground/image 可查回执;增加 ?submission_response=1 可取原响应正文。带 task_id 的 GET 仍按原任务查询处理。此代理要求登录,不会给未携带 key 的请求自动补建 key。
