开发者接入 · v1

API 文档

API 专供有持续、批量任务需求的商家与合作者使用,不面向任务量很少的个人使用者。量大优惠更大,个人使用者请勿申请。

合作商家请联系管理员洽谈价格与接入方式;开通后,由管理员手动私信发送密钥。

私信管理员开通 TG:@xubeifeng

接口地址
https://guoti1.shanjierenyi3.com/wp-json/site-api/v1

流程总览

  1. GET /account 读取当前可用功能、价格、余额和今日剩余额度(可选)。
  2. POST /tasks 提交任务:请求头携带密钥和 Idempotency-Key;成功返回 HTTP 202 和 task_code,此时已扣款。
  3. GET /tasks/{task_code} 每 5–10 秒轮询,直到 statussucceededfailedcancelled
  4. statussucceeded 时下载 result_url(10 分钟有效,过期后重新查询获取新地址)。failed / cancelled 均已自动退款。

所有接口只接受服务器端调用;响应均为 JSON(下载地址除外),请求和响应均使用 UTF-8。同一账号内请串行提交创建请求:一个创建请求正在处理时,同账号的另一个创建请求会返回 409 account_busy,稍后按原编号重试即可。

密钥与鉴权

所有业务请求使用 HTTPS,并携带以下请求头。一个账号只有一个有效密钥;更换密钥请联系管理员,旧密钥在重置后失效。

Authorization: Bearer <管理员提供的密钥>

密钥格式为 sapi_ 加 64 位十六进制字符。请把密钥保存在服务器的环境变量中,供后端调用。不要放进网页 JavaScript、URL、公开代码或日志。账号停用、封禁后无法继续调用。

功能列表

API 只开放下表中的功能,每个 type 与站内同名页面使用同一套处理流程和默认价格。提交未开放或不存在的 type 会收到 400 unsupported_type(message 列出当前站点可用类型),不会扣款。

功能type必填素材prompt结果
文生图text_to_image必填图片
人脸融合(文生图)text_to_image_faceimage必填图片
单图编辑image_editimage必填图片
双图编辑multi_image_editimageimage2必填图片
一键脱衣image_undressimage不需要图片
换衣clothing_changeimage不需要图片
图片换脸image_face_swapimage:人物照片(提供人脸);image2:目标图片(被替换人脸)不需要图片
视频换脸(自定义视频)video_face_swapimage:人物照片(提供人脸);video:目标视频不需要MP4 视频
视频换脸(站内模板)video_face_swap_templateimage:人物照片;template:站内模板 key(见 GET /account 的 options)不需要MP4 视频
文生视频text_to_video必填MP4 视频
人脸融合(文生视频)text_to_video_faceimage必填MP4 视频
图生视频(自定义提示词)image_to_videoimage(或 source_task_code:本人文生图作品)必填MP4 视频
图生视频模板image_to_video_templateimage(或 source_task_code:本人文生图作品)不需要MP4 视频
图生长视频long_videoimage(或 source_task_code:本人文生图作品)不需要MP4 视频
视频脱衣video_undressvideo:已剪到 1–10 秒、不超过 20 MB 的视频不需要MP4 视频

创建任务

POST /tasks · 有文件时使用 multipart/form-data;无文件任务可使用 application/json。所有参数放在请求体中,URL 上不能带查询参数。

请求头

请求头说明
Authorization必填,Bearer <密钥>
Idempotency-Key必填,8–128 位,仅允许字母、数字和 . _ : -,建议使用 UUID。每个新任务生成一个新编号;超时或网络错误后,使用相同编号、相同参数和相同文件重试,服务端会返回已创建的同一任务且不再扣款。同一编号搭配不同参数会返回 409 idempotency_conflict
Content-Typemultipart/form-dataapplication/json

请求体字段

字段说明
type必填,见功能列表。
prompt文生图、人脸融合文生图、单图/双图编辑、文生视频、人脸融合文生视频、自定义图生视频必填,最多 6000 个 UTF-8 字节。脱衣、换衣、换脸、模板、长视频、视频脱衣请勿依赖此字段。提示词原样传给生成流程,与页面输入框等效。
negative_prompt可选,反向提示词,最多 3000 个 UTF-8 字节。
size仅文生视频、人脸融合文生视频、自定义图生视频、长视频:480x832(默认)或 704x1280。其他类型请勿传。
image / image2文件字段,随创建请求上传。JPG、PNG、WebP;每张最多 18 MB,单边 32–8192 像素,最多 1200 万像素。服务端会重新编码为 JPEG 并剥离元数据。
video文件字段。视频换脸:MP4 或 WebM,最多 50 MB、250 秒、1080p(长边不超过 1920)、60 FPS,只能包含一个视频轨。视频脱衣:请先剪到 1–10 秒、不超过 20 MB,最短边不低于 360 像素;服务端不代剪。
source_task_code自定义图生视频、图生视频模板、长视频可用本人已完成的文生图作品作为源图,替代 image。传该作品的 19 位任务 code(字符串),不能与 image 同时使用。作品需在 30 天内且未删除。
style一键脱衣必填:xiaonai / zhongnai / danai。换衣必填:chiheidiaorujiaokunbang 等,完整列表见 GET /accountoptions
hair / breast / outfit可选。脱衣的阴毛、换衣的身材/阴毛/服装、视频脱衣的奶子大小与阴毛;取值以 options 为准。视频脱衣未传时默认 breast=zhongnaihair=shaomao
template图生视频模板、站内视频换脸模板必填;长视频可与 segments 二选一。必须使用 GET /account 返回的 key,未知模板拒绝。
segments长视频自定义段:JSON 数组(multipart 时传 JSON 字符串),2–4 段,每段 {"template_key":"s01_1","duration":4}。只用页面别名(s01_1 / s02 等),不要传内部工作流名。与 template 不能同时传。
keep_shoes / keep_hands / keep_stockings / fullbody仅视频脱衣,可选,取值 01。默认保留鞋子、不保留手和丝袜、非全身。

整个请求最多 70 MB。不接受上表之外的字段和文件名(会返回 400 invalid_parameter)。文件数量、名称必须与功能列表一致,否则返回 400 invalid_uploads。请先调用 GET /account 读取 options 再提交模板或选项,不要猜测内部 workflow。

受理成功:HTTP 202

{
  "task_code": "2026091209301234567",
  "replayed": false,
  "status_url": "https://guoti1.shanjierenyi3.com/wp-json/site-api/v1/tasks/2026091209301234567"
}

task_code 与站内任务 code 一致,为 19 位字符串,请勿转成数字,以免丢失精度。replayed: true 表示返回了同一 Idempotency-Key 已创建的任务,没有再次扣款。幂等记录长期保留,不要复用旧编号发起新任务。

受理即扣款;扣款金额可在随后的查询响应 price 字段中看到。金币不足(402)或额度不足(429)时不会创建任务。

请求示例

示例中 $SITE_API_KEY 为管理员提供的密钥,$TASK_REQUEST_ID 为本次任务的唯一编号(请保存下来供重试使用)。

cURL:文生图(JSON)

curl --request POST "https://guoti1.shanjierenyi3.com/wp-json/site-api/v1/tasks" \
  --header "Authorization: Bearer $SITE_API_KEY" \
  --header "Idempotency-Key: $TASK_REQUEST_ID" \
  --header "Content-Type: application/json" \
  --data '{"type":"text_to_image","prompt":"雨后山间的木屋,柔和晨光","negative_prompt":"模糊,低画质"}'

cURL:文生视频(JSON,指定尺寸)

curl --request POST "https://guoti1.shanjierenyi3.com/wp-json/site-api/v1/tasks" \
  --header "Authorization: Bearer $SITE_API_KEY" \
  --header "Idempotency-Key: $TASK_REQUEST_ID" \
  --header "Content-Type: application/json" \
  --data '{"type":"text_to_video","prompt":"海边日出,镜头缓慢推进","size":"704x1280"}'

cURL:单图编辑(multipart 上传图片)

curl --request POST "https://guoti1.shanjierenyi3.com/wp-json/site-api/v1/tasks" \
  --header "Authorization: Bearer $SITE_API_KEY" \
  --header "Idempotency-Key: $TASK_REQUEST_ID" \
  --form "type=image_edit" \
  --form "prompt=把背景换成黄昏的海边" \
  --form "image=@input.jpg;type=image/jpeg"

cURL:图片换脸(两张图片)

curl --request POST "https://guoti1.shanjierenyi3.com/wp-json/site-api/v1/tasks" \
  --header "Authorization: Bearer $SITE_API_KEY" \
  --header "Idempotency-Key: $TASK_REQUEST_ID" \
  --form "type=image_face_swap" \
  --form "image=@face.jpg;type=image/jpeg" \
  --form "image2=@target.jpg;type=image/jpeg"

cURL:视频换脸(图片 + 视频)

curl --request POST "https://guoti1.shanjierenyi3.com/wp-json/site-api/v1/tasks" \
  --header "Authorization: Bearer $SITE_API_KEY" \
  --header "Idempotency-Key: $TASK_REQUEST_ID" \
  --form "type=video_face_swap" \
  --form "image=@face.jpg;type=image/jpeg" \
  --form "video=@target.mp4;type=video/mp4"

cURL:一键脱衣

curl --request POST "https://guoti1.shanjierenyi3.com/wp-json/site-api/v1/tasks" \
  --header "Authorization: Bearer $SITE_API_KEY" \
  --header "Idempotency-Key: $TASK_REQUEST_ID" \
  --form "type=image_undress" \
  --form "style=zhongnai" \
  --form "hair=moren" \
  --form "image=@input.jpg;type=image/jpeg"

cURL:换衣

curl --request POST "https://guoti1.shanjierenyi3.com/wp-json/site-api/v1/tasks" \
  --header "Authorization: Bearer $SITE_API_KEY" \
  --header "Idempotency-Key: $TASK_REQUEST_ID" \
  --form "type=clothing_change" \
  --form "style=chiheidiao" \
  --form "breast=zhongnai" \
  --form "image=@input.jpg;type=image/jpeg"

cURL:站内视频换脸模板

curl --request POST "https://guoti1.shanjierenyi3.com/wp-json/site-api/v1/tasks" \
  --header "Authorization: Bearer $SITE_API_KEY" \
  --header "Idempotency-Key: $TASK_REQUEST_ID" \
  --form "type=video_face_swap_template" \
  --form "template=YOUR_TEMPLATE_KEY" \
  --form "image=@face.jpg;type=image/jpeg"

cURL:视频脱衣(请先剪到 1–10 秒、不超过 20MB)

curl --request POST "https://guoti1.shanjierenyi3.com/wp-json/site-api/v1/tasks" \
  --header "Authorization: Bearer $SITE_API_KEY" \
  --header "Idempotency-Key: $TASK_REQUEST_ID" \
  --form "type=video_undress" \
  --form "breast=zhongnai" \
  --form "hair=shaomao" \
  --form "keep_shoes=1" \
  --form "video=@clip.mp4;type=video/mp4"

cURL:图生视频(使用本人文生图作品)

curl --request POST "https://guoti1.shanjierenyi3.com/wp-json/site-api/v1/tasks" \
  --header "Authorization: Bearer $SITE_API_KEY" \
  --header "Idempotency-Key: $TASK_REQUEST_ID" \
  --header "Content-Type: application/json" \
  --data '{"type":"image_to_video","prompt":"云朵缓慢移动,镜头平稳推进","source_task_code":"2026091209301234567"}'

cURL:图生视频模板

curl --request POST "https://guoti1.shanjierenyi3.com/wp-json/site-api/v1/tasks" \
  --header "Authorization: Bearer $SITE_API_KEY" \
  --header "Idempotency-Key: $TASK_REQUEST_ID" \
  --header "Content-Type: application/json" \
  --data '{"type":"image_to_video_template","template":"xianyilouru","source_task_code":"2026091209301234567"}'

cURL:长视频(预设或自定义段)

curl --request POST "https://guoti1.shanjierenyi3.com/wp-json/site-api/v1/tasks" \
  --header "Authorization: Bearer $SITE_API_KEY" \
  --header "Idempotency-Key: $TASK_REQUEST_ID" \
  --header "Content-Type: application/json" \
  --data '{"type":"long_video","template":"classic_three","source_task_code":"2026091209301234567"}'

Python:创建、轮询、下载完整流程

import os
import time
import uuid
import requests

BASE = "https://guoti1.shanjierenyi3.com/wp-json/site-api/v1"
HEADERS = {"Authorization": "Bearer " + os.environ["SITE_API_KEY"]}


def create_task(fields, files=None, request_id=None):
    """request_id 每个业务任务生成一次;重试时必须复用同一个。"""
    request_id = request_id or str(uuid.uuid4())
    headers = dict(HEADERS, **{"Idempotency-Key": request_id})
    for attempt in range(5):
        try:
            if files:
                r = requests.post(BASE + "/tasks", headers=headers, data=fields, files=files, timeout=120)
            else:
                r = requests.post(BASE + "/tasks", headers=headers, json=fields, timeout=60)
        except requests.RequestException:
            time.sleep(2 ** attempt)
            continue
        if r.status_code == 202:
            return r.json()["task_code"]
        if r.status_code in (409, 429, 503):
            time.sleep(int(r.headers.get("Retry-After", 2 ** attempt)))
            continue
        raise RuntimeError(r.status_code, r.json())
    raise RuntimeError("创建任务重试次数用尽,请稍后用同一 request_id 重试")


def wait_result(task_code):
    while True:
        r = requests.get(BASE + "/tasks/" + task_code, headers=HEADERS, timeout=30)
        if r.status_code == 429:
            time.sleep(int(r.headers.get("Retry-After", 60)))
            continue
        r.raise_for_status()
        data = r.json()
        if data["status"] == "succeeded":
            return data
        if data["status"] in ("failed", "cancelled"):
            raise RuntimeError(data["message"])
        time.sleep(8)


def download(data, path):
    if not data.get("result_url"):
        raise RuntimeError("结果已过期或已删除")
    with requests.get(data["result_url"], stream=True, timeout=300) as r:
        r.raise_for_status()
        with open(path, "wb") as f:
            for chunk in r.iter_content(1024 * 1024):
                f.write(chunk)


task_code = create_task({"type": "text_to_image", "prompt": "雨后山间的木屋,柔和晨光"})
result = wait_result(task_code)
download(result, task_code + ".jpg")

上传文件时把 files 传给 create_task,例如:create_task({"type": "image_edit", "prompt": "..."}, files={"image": ("input.jpg", open("input.jpg", "rb"), "image/jpeg")})

查询任务与下载结果

GET /tasks/{task_code},携带 API 密钥。建议每 5–10 秒查询一次,收到 429 后按 Retry-After 退避。查询不收费。只能查询本账号通过 API 创建的任务。

{
  "task_code": "2026091209301234567",
  "status": "succeeded",
  "price": 10,
  "charged_amount": 10,
  "refund_status": "none",
  "message": "",
  "result_url": "<短期有效下载地址>",
  "result_expires_in": 600,
  "result_retention_days": 30,
  "created_at": "2026-09-12T01:30:12+00:00"
}
status含义处理
queued已受理、排队中。继续轮询。
processing执行中,或失败后自动重试、退款核对中(此时 refund_status 可能为 pending)。继续轮询。
succeeded成功。下载 result_url
failed最终失败,金币已按创建时价格退回(charged_amount 为 0,refund_statusrefunded)。终态;如需重做请用新的 Idempotency-Key 创建。
cancelled任务在排队阶段被账号本人在站内“我的作品”取消,金币已退回。终态。

result_url 有效期 10 分钟(result_expires_in 秒),过期后重新查询即可获得新地址。下载结果地址时不要附带 API 密钥。结果为图片时通常是 PNG/JPG,视频为 MP4;请以下载响应的 Content-Type 或文件扩展名为准。

结果从受理时间起保留 30 天(result_retention_days),请及时下载;过期或已删除的结果 result_urlnull。已结束任务的输入素材在 7 天后清理;仍在执行或重试的任务保留素材。

查询账户

GET /account,携带 API 密钥。返回余额、当前开放的功能与价格、网站时区与日期、每日消费上限、今日已消费和剩余额度。查询不收费。

{
  "balance": 1000,
  "currency": "金币",
  "date": "YYYY-MM-DD",
  "timezone": "<网站时区>",
  "daily_limit": 500,
  "today_spent": 100,
  "daily_remaining": 400,
  "types": ["text_to_image", "text_to_image_face", "image_edit", "multi_image_edit", "image_undress", "clothing_change", "image_face_swap", "video_face_swap", "video_face_swap_template", "text_to_video", "text_to_video_face", "image_to_video", "image_to_video_template", "long_video", "video_undress"],
  "prices": {"text_to_image:default": 10, "image_undress:default": 8, "text_to_video:480x832": 15},
  "pricing_notes": {"video_face_swap": "按视频时长阶梯计价……", "long_video": "按段计价……"},
  "options": {"image_undress": {"style": ["xiaonai", "zhongnai", "danai"]}, "image_to_video_template": [{"template": "xianyilouru", "label": "掀衣露乳"}]}
}

prices 的键为 type:size,图片类功能的 size 固定为 default。按时长/段数/模板文件计价的类型只出现在 pricing_notesoptions 给出当前站点可用的 style / template / 长视频预设与段别名。以上金额仅为示例,实际价格以此接口及下表为准。账户接口不返回个人联系方式等资料。

价格与退款

具体价格请商家与管理员协商,量大优惠更大。下表为当前基础报价,与站内页面同功能的价格一致;合作价格与计费方式请在开通前确认。

功能尺寸基础报价
文生图默认10 金币 / 次
人脸融合(文生图)默认15 金币 / 次
单图编辑默认8 金币 / 次
双图编辑默认10 金币 / 次
一键脱衣默认8 金币 / 次
换衣默认10 金币 / 次
图片换脸默认8 金币 / 次
文生视频480x83215 金币 / 次
文生视频704x128020 金币 / 次
人脸融合(文生视频)480x83217 金币 / 次
人脸融合(文生视频)704x128022 金币 / 次
图生视频(自定义提示词)480x83226 金币 / 次
图生视频(自定义提示词)704x128028 金币 / 次
图生视频模板默认27 金币 / 次
视频换脸(自定义视频)按时长按视频时长阶梯计价:前 60 秒每秒 0.6 金币,60–180 秒每秒 0.5 金币,180–250 秒每秒 0.38 金币,向上取整,最低 15 金币。例:30 秒 18 金币,60 秒 36 金币,120 秒 66 金币,250 秒 123 金币。时长由服务器读取。
视频换脸(站内模板)按模板按站内模板发布时写入的价格扣费;未知模板直接拒绝,不会回退到默认价
图生长视频按段按段计价:首段 27 金币,每多一段 +15;704x1280 每段再 +5;单段超过 4 秒后每多 1 秒 +1。段数 2–4,单段 3–10 秒。例:2 段各 4 秒 480x832 为 42 金币。
视频脱衣按时长按视频时长计价:每秒 5 金币,按 0.1 秒精度四舍五入,最短 1 秒、最长 10 秒。例:1 秒 5 金币,5.9 秒 30 金币,10 秒 50 金币。时长由服务器读取。

使用本站金币余额。任务受理时扣款,排队和执行中的任务计入当日 API 消费;查询任务与账户不收取金币。

最终失败或取消的任务按创建时的价格退回金币,并回退原扣款日的 API 消费额度。重试中的任务等待最终结果后结算。价格变动不影响已经受理的任务。

每日消费上限按网站时区自然日统计,只累计 API 消费;超出时创建请求返回 429 daily_limit_exceeded,次日自动恢复,需要调整请联系管理员。

请求限制

安全策略与自动停用

密钥仅用于本文档列出的三个接口和文档中的字段。服务端会对每个密钥的异常请求进行识别,出现以下情况时密钥会被立即自动停用并通知管理员,后续请求返回 403 api_disabled;恢复需要联系管理员核实:

正常接入不会触发以上规则:请只提交文档列出的字段,只查询本账号通过 API 创建的 task_code,联调时先用少量请求验证参数,再批量提交。遇到 400 错误时请先修正参数,不要用同一错误请求反复重试。任何安全测试请先与管理员沟通并使用管理员指定的测试账号。

错误处理

错误响应为 JSON,code 为稳定的机器可读错误码,message 为说明文字(可能调整,请勿用于程序判断)。

{"code":"invalid_api_key","message":"请提供有效 API 密钥","data":{"status":401}}
HTTPcode含义与处理
400unsupported_typetype 不存在或本站未开放;message 中列出可用类型。
400invalid_parameter包含不支持的字段、URL 带查询参数或参数类型错误。
400invalid_prompt / invalid_size / invalid_source提示词、尺寸或 source_task_code 不符合要求。
400invalid_uploads / invalid_upload / invalid_image / invalid_video文件数量或字段名不对、上传失败、图片或视频格式/尺寸/时长不合规。
400upload_not_allowed当前站点禁止上传外部素材,请改用本人文生图 source_task_code
400idempotency_required / invalid_body缺少合法的 Idempotency-Key,或请求体为空(常见于超过服务器上传限制)。
401invalid_api_key密钥缺失或错误;确认是否已被管理员重置。
402insufficient_balance金币不足,请充值后用同一 Idempotency-Key 重试。
403api_disabled / https_required / invalid_download授权已停用、账号不可用或因异常请求被自动停用(见安全策略,需联系管理员);未使用 HTTPS;下载链接无效或过期。
404task_not_found / source_not_found / result_unavailable任务、源作品或结果不存在、不属于当前账号,或已过期删除。
409account_busy同账号另一个请求正在处理,稍后用原 Idempotency-Key 重试。
409idempotency_conflict同一编号对应的参数或文件发生了变化;为新任务换一个编号。
409account_deleting账号正在注销,不能创建任务。
413request_too_large / file_too_large / image_too_large请求或文件过大,请压缩后重试。
415unsupported_media_typeContent-Type 不是 multipart/form-data 或 application/json。
429rate_limited请求过于频繁,按 Retry-After 退避。
429daily_limit_exceeded今日 API 消费额度不足,等待新的一天或联系管理员调整上限。
503service_unavailable / storage_unavailable / storage_error服务暂时不可用。创建请求保留原 Idempotency-Key 重试,不会重复扣款;持续异常时联系管理员。

网络超时时无法确定请求是否已受理:请始终用同一 Idempotency-Key 重试创建,服务端会返回已存在的任务(replayed: true)或继续创建。