Python · 幽灵模特 API
幽灵模特 API 在 Python 中
一句话总结
安装 requests,从环境变量读取 PHOTTA_API_KEY,编写一个发送 Bearer Key 并在非 2xx 响应时抛出类型化 PhottaError 的 photta() 包装函数,随后 POST 请求至 /api/v1/ghost-mannequin,并每隔 3 秒轮询一次 /api/v1/ghost-mannequin/{id} 直至 status 为 completed。
- 常规耗时: 1.5–4 min
- Credits: 2K 分辨率 4 credits · 4K 分辨率 5 credits
- 处理方式: 异步,轮询
- 限制: 600 次请求/分钟
- 身份验证: Bearer key
本页所有数据均来自 Photta API 文档 · 已验证
RESPONSE=$(curl -s -X POST https://api.photta.app/api/v1/ghost-mannequin \
-H "Authorization: Bearer $PHOTTA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"product_image": "https://cdn.yourstore.com/products/jacket-front.jpg",
"back_image": "https://cdn.yourstore.com/products/jacket-back.jpg",
"image_side": "front",
"angle": "side",
"style": "3d",
"background_color": "white",
"resolution": "2K",
"aspect_ratio": "3:4",
"user_instruction": "closed front, cream interior lining",
"brand_label_id": "7cc9f988-068b-44cd-8004-22f486b10e67"
}')
ID=$(echo "$RESPONSE" | jq -r '.data.id')
# $ID is data.id from the POST response. Poll every 3 seconds until status is "completed" or "failed".
for i in $(seq 1 120); do
RESULT=$(curl -s "https://api.photta.app/api/v1/ghost-mannequin/$ID" -H "Authorization: Bearer $PHOTTA_API_KEY")
STATUS=$(echo "$RESULT" | jq -r '.data.status')
[ "$STATUS" = "completed" ] && break
[ "$STATUS" = "failed" ] && echo "generation failed" && exit 1
sleep 3
done
echo "$RESULT" | jq -r '.data.output_url'const res = await fetch("https://api.photta.app/api/v1/ghost-mannequin", {
method: "POST",
headers: { Authorization: `Bearer ${process.env.PHOTTA_API_KEY}`, "Content-Type": "application/json" },
body: JSON.stringify({
"product_image": "https://cdn.yourstore.com/products/jacket-front.jpg",
"back_image": "https://cdn.yourstore.com/products/jacket-back.jpg",
"image_side": "front",
"angle": "side",
"style": "3d",
"background_color": "white",
"resolution": "2K",
"aspect_ratio": "3:4",
"user_instruction": "closed front, cream interior lining",
"brand_label_id": "7cc9f988-068b-44cd-8004-22f486b10e67"
}),
});
const { data } = await res.json(); // data.id, data.status
async function waitFor(id) {
for (let attempt = 0; attempt < 120; attempt++) {
const res = await fetch(`https://api.photta.app/api/v1/ghost-mannequin/${id}`, { headers: { Authorization: `Bearer ${process.env.PHOTTA_API_KEY}` } });
const { data } = await res.json();
if (data.status === "completed") return data.output_url;
if (data.status === "failed") throw new Error(data.error_message ?? "generation failed");
await new Promise((r) => setTimeout(r, 3000));
}
throw new Error("timed out after 6 minutes");
}import os, requests
res = requests.post(
"https://api.photta.app/api/v1/ghost-mannequin",
headers={"Authorization": f"Bearer {os.environ['PHOTTA_API_KEY']}"},
json={
"product_image": "https://cdn.yourstore.com/products/jacket-front.jpg",
"back_image": "https://cdn.yourstore.com/products/jacket-back.jpg",
"image_side": "front",
"angle": "side",
"style": "3d",
"background_color": "white",
"resolution": "2K",
"aspect_ratio": "3:4",
"user_instruction": "closed front, cream interior lining",
"brand_label_id": "7cc9f988-068b-44cd-8004-22f486b10e67"
},
)
data = res.json()["data"] # data["id"], data["status"]
import time
def wait_for(job_id):
for _ in range(120):
res = requests.get(f"https://api.photta.app/api/v1/ghost-mannequin/{job_id}", headers={"Authorization": f"Bearer {os.environ['PHOTTA_API_KEY']}"})
data = res.json()["data"]
if data["status"] == "completed":
return data["output_url"]
if data["status"] == "failed":
raise RuntimeError(data.get("error_message", "generation failed"))
time.sleep(3)
raise TimeoutError("timed out after 6 minutes")概览
概览
- 端点
- POST /api/v1/ghost-mannequin
- 身份验证
- Bearer API 密钥
- 处理方式
- 异步 — 轮询状态端点
- 常规耗时
- 1.5–4 min
- Credits
- 2K 分辨率 4 credits · 4K 分辨率 5 credits
- 宽高比
- 3:4 · 1:1 · 4:3 · 9:16 · 16:9
- 输入限制
- 单张图片最大 10 MB;支持 JPEG, PNG, WebP
- 幂等性
- 否
工作原理
仅需五步,零 Photta 专属依赖——requests 即可搞定一切。
步骤 1
注册并生成密钥
与其他语言路径一致:ai.photta.app → Developers → Generate API key。密钥以 `photta_live_` 开头,通用于 Photta 的所有功能特性。
步骤 2
从环境变量加载密钥
在环境中设置 `PHOTTA_API_KEY` 并通过 `os.environ` 读取。在 FastAPI 或 Django 中,系统启动时将其加载到 settings 模块中即可。切勿将密钥硬编码在源码中或提交至公开的 Git 历史。
python3 -m pip install requests export PHOTTA_API_KEY="photta_live_xxxxx"步骤 3
编写 requests 包装函数
一个三十行的 `photta_request()` 函数即可搞定 base URL、Authorization 请求头、JSON 序列化以及错误转换。在 Python SDK 正式发布前,这就是你唯一需要的抽象层。
# photta.py — one helper for every endpoint import os, requests BASE = "https://api.photta.app/api/v1" class PhottaError(Exception): def __init__(self, status, error, retry_after=None): super().__init__(error.get("message", "request failed")) self.status, self.type, self.retry_after = status, error.get("type"), retry_after def photta(method, path, **kwargs): res = requests.request(method, BASE + path, headers={"Authorization": f"Bearer {os.environ['PHOTTA_API_KEY']}"}, timeout=30, **kwargs) body = res.json() if not res.ok: raise PhottaError(res.status_code, body.get("error", {}), res.headers.get("Retry-After")) return body步骤 4
提交并轮询
向 `/api/v1/ghost-mannequin` 发起 POST 请求获取生成任务 ID,随后按 3 秒间隔轮询 `/api/v1/ghost-mannequin/{id}`。在 Celery 或 RQ 中,请将轮询循环拆分到多个任务中,避免耗时数分钟的任务长时间占用 worker。
import os, requests res = requests.post( "https://api.photta.app/api/v1/ghost-mannequin", headers={"Authorization": f"Bearer {os.environ['PHOTTA_API_KEY']}"}, json={ "product_image": "https://cdn.yourstore.com/products/jacket-front.jpg", "back_image": "https://cdn.yourstore.com/products/jacket-back.jpg", "image_side": "front", "angle": "side", "style": "3d", "background_color": "white", "resolution": "2K", "aspect_ratio": "3:4", "user_instruction": "closed front, cream interior lining", "brand_label_id": "7cc9f988-068b-44cd-8004-22f486b10e67" }, ) data = res.json()["data"] # data["id"], data["status"] import time def wait_for(job_id): for _ in range(120): res = requests.get(f"https://api.photta.app/api/v1/ghost-mannequin/{job_id}", headers={"Authorization": f"Bearer {os.environ['PHOTTA_API_KEY']}"}) data = res.json()["data"] if data["status"] == "completed": return data["output_url"] if data["status"] == "failed": raise RuntimeError(data.get("error_message", "generation failed")) time.sleep(3) raise TimeoutError("timed out after 6 minutes")步骤 5
持久化存储结果
任务完成的 payload 包含 `output_url` 和 `thumbnail_url`。将二进制数据下载并存入你自己的对象存储(S3、GCS、Cloudflare R2)中,避免长期展示依赖 Photta 的 CDN。
错误
- 400
invalid_request_error - The request is malformed or contains invalid parameters.
- 401
authentication_error - The API key is missing, invalid, or expired.
- 402
insufficient_credits_error - Your account does not have enough credits.
- 404
not_found_error - The requested resource does not exist.
- 409
conflict_error - The request conflicts with current state — e.g. your concurrent-batch cap is reached.
- 429
rate_limit_error - Too many requests. Slow down and retry.Retry-After: 30
- 500
api_error - An internal server error occurred. Retry later.
try:
photta("POST", "/ghost-mannequin", json={
"product_image": "https://cdn.yourstore.com/products/jacket-front.jpg",
"back_image": "https://cdn.yourstore.com/products/jacket-back.jpg",
"image_side": "front",
"angle": "side",
"style": "3d",
"background_color": "white",
"resolution": "2K",
"aspect_ratio": "3:4",
"user_instruction": "closed front, cream interior lining",
"brand_label_id": "7cc9f988-068b-44cd-8004-22f486b10e67"
})
except PhottaError as e:
if e.status == 402:
print("insufficient_credits_error: top up before retrying")
elif e.status == 429:
time.sleep(int(e.retry_after or 30))
else:
raise限制
- 每个 API 密钥每分钟 600 次请求 (固定窗口;各套餐限制相同)
- 429 响应包含 Retry-After: 30 秒
- 单张图片最大 10 MB
- 格式:: JPEG, PNG, WebP
- 各套餐并发批处理数:: Free 1 · Hobby 2 · Seller 3 · Brand 4 · Studio 6
- 仅支持轮询 — API 不发送 Webhook。
为什么 requests 是当下的理想之选
- 无 Photta 专有依赖——绝大多数 Python 项目已内置 requests
- 支持所有运行 Python 的环境:Django、FastAPI、Flask、Celery worker、Lambda、脚本
- 客户端封装仅约三十行代码——直接粘贴至 photta.py 即可使用
- 需要并行提交时,可通过 httpx 与 asyncio 无缝搭配
不支持的特性
- 暂无官方 Photta Python 包——目前文档规范的集成模式是基于 requests 的 REST 调用
- 轮询是获取完成状态的唯一方式;API 不发送 webhook
- 仅支持 Bearer key;不支持 OAuth 客户端凭证(client-credentials)流程
开发者常见问题
Photta 是否提供官方 Python SDK?
暂未提供。官方推荐的集成路径是 requests 库(同步)或 httpx(异步)——两者只需一层极简封装即可使用,本页提供的封装代码适用于所有 capability。
支持哪些 Python 版本?
Python 3.9 及更高版本。封装代码使用了类型注解、f-strings 以及 `str | None` 语法,这些在 3.10+ 环境下原生支持。在 3.9 环境下请将 `str | None` 替换为 `Optional[str]`。requests 本身官方支持 3.8+,但 3.9+ 是现代 Photta 项目切合实际的最低版本要求。
我应该选择 requests 还是 httpx?
如果是少数顺序调用,选 requests——更简单且几乎存在于所有代码库中。如果需要异步并发(并行提交、批量回填)或 HTTP/2 支持,选 httpx。无论选哪个,封装都非常轻量;将 `requests.request` 替换为 `httpx.Client().request`,其余代码完全通用。
可以在 Django 中调用吗?
可以。将封装代码放在 `services/photta.py` 中,在 view 或 Celery 任务中导入即可。对于耗时较长的任务,切勿在同步请求处理函数中调用 API——应在 view 中提交任务、返回生成任务 ID,然后在后台任务或 Channels consumer 中进行轮询。
如何在 Celery worker 中进行轮询?
在一个任务中提交作业,然后调度后续任务(通过 `apply_async(countdown=3)`)单次轮询;若未完成则重新调度自身,直到作业完成或达到最大重试次数上限。这样可以保持 worker 处于空闲状态,避免因长时运行任务干扰弹性伸缩(autoscaler)。
API 如何返回错误?
非 2xx 响应会返回一个包含 `error` 对象的 JSON body:包括 `type`、`code`、`message`,以及 400 状态码下的 `param` 和 429 状态码下的 `retry_after`。本页的封装代码会抛出一个携带上述全部字段的 `PhottaError`,方便调用方根据状态码直接处理逻辑,无需自行解析 body。
相关页面
Node.js
在 Node.js 中使用 幽灵模特 API
在 Node.js 后端中使用原生 fetch 调用 Photta 的 幽灵模特 API。无需 SDK:存储你的 key、提交任务、轮询获取结果即可。
阅读cURL
通过 cURL 调用 幽灵模特 API
直接在终端中使用 cURL 调用 Photta 的 幽灵模特 API。提交、轮询、下载——每个代码片段均可搭配 jq 用于自动化流水线脚本。
阅读功能特性
幽灵模特 API 适用于镂空模特商品图
AI 幽灵模特 endpoint。从服装照片中移除模特,完整保留内部细节。支持 3D 或平铺效果,支持批量处理,2K 分辨率 4 credits。
阅读构建
为您的商品目录实现隐形模特自动提取
每晚目录自动化配方:拉取昨天的商品更新,批量提交至 Photta 的隐形模特 API,轮询父批次,持久化存储到您的数据库。
阅读快速开始
5 分钟内生成第一张 Photta 图像。
注册、生成 API 密钥、运行第一个 cURL 调用、轮询直至完成、持久化保存结果。共五个步骤,端到端完整记录。
阅读参考
Photta API 定价
Photta API 各个 endpoint 在 2K 和 4K 分辨率下的 credits 成本、扣费与退款机制,以及哪些 endpoint 是免费的。没有按单张图片收取的货币价格。
阅读
本页所有数据均来自 Photta API 文档 · 已验证
五分钟内上手试用 API
生成 Photta API key,粘贴上方的 cURL 代码片段,咖啡还没煮好,你的第一张模特实穿图就已经生成完毕。
- 1.5–4 min
- 2K 分辨率 4 credits · 4K 分辨率 5 credits
- 异步,轮询
- 600 次请求/分钟
- Bearer key