Node.js · 首饰试穿 API
首饰试穿 API Node.js 环境
一句话总结
在环境变量中设置 PHOTTA_API_KEY,为 https://api.photta.app/api/v1 编写一个带有 Bearer 认证的简易 fetch 辅助函数,POST 到 /api/v1/tryon/jewelry,随后每 3 秒轮询一次 /api/v1/tryon/jewelry/{id} 直到状态变为 completed。
- 常规耗时: 1.5–4 min
- Credits: 2K 分辨率 5 credits · 4K 分辨率 6 credits
- 处理方式: 异步,轮询
- 限制: 600 次请求/分钟
- 身份验证: Bearer key
本页所有数据均来自 Photta API 文档 · 已验证
RESPONSE=$(curl -s -X POST https://api.photta.app/api/v1/tryon/jewelry \
-H "Authorization: Bearer $PHOTTA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"jewelry_image": "https://cdn.yourstore.com/products/gold-necklace.jpg",
"jewelry_type": "necklace",
"mannequin_id": "mnk_j9k1l2",
"background": "soft window light on dark velvet",
"resolution": "2K",
"aspect_ratio": "3:4",
"user_instruction": "Make the pendant 10% smaller."
}')
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/tryon/jewelry/$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/tryon/jewelry", {
method: "POST",
headers: { Authorization: `Bearer ${process.env.PHOTTA_API_KEY}`, "Content-Type": "application/json" },
body: JSON.stringify({
"jewelry_image": "https://cdn.yourstore.com/products/gold-necklace.jpg",
"jewelry_type": "necklace",
"mannequin_id": "mnk_j9k1l2",
"background": "soft window light on dark velvet",
"resolution": "2K",
"aspect_ratio": "3:4",
"user_instruction": "Make the pendant 10% smaller."
}),
});
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/tryon/jewelry/${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/tryon/jewelry",
headers={"Authorization": f"Bearer {os.environ['PHOTTA_API_KEY']}"},
json={
"jewelry_image": "https://cdn.yourstore.com/products/gold-necklace.jpg",
"jewelry_type": "necklace",
"mannequin_id": "mnk_j9k1l2",
"background": "soft window light on dark velvet",
"resolution": "2K",
"aspect_ratio": "3:4",
"user_instruction": "Make the pendant 10% smaller."
},
)
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/tryon/jewelry/{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/tryon/jewelry
- 身份验证
- Bearer API 密钥
- 处理方式
- 异步 — 轮询状态端点
- 常规耗时
- 1.5–4 min
- Credits
- 2K 分辨率 5 credits · 4K 分辨率 6 credits
- 宽高比
- 3:4 · 1:1 · 4:3 · 9:16 · 16:9
- 输入限制
- 单张图片最大 10 MB;支持 JPEG, PNG, WebP
- 幂等性
- 否
工作原理
从注册到输出第一张图片,只需五步,大约五分钟。
步骤 1
注册并生成 key
在 ai.photta.app 创建账号。打开控制台的 Developers 区域,点击 Generate API key,获取正式环境 key。它以 `photta_live_` 开头,后接 32 位十六进制字符。
步骤 2
将 key 存入环境变量,切勿写入源码
将 `PHOTTA_API_KEY=...` 添加到 `.env`(或你平台的密钥管理服务中),并通过 `process.env` 读取。切勿将 key 提交到版本库;切勿将其导入带有 `'use client'` 标记的文件——打包工具会将其暴露到浏览器端。
node --version # 18 or later ships fetch echo "PHOTTA_API_KEY=photta_live_xxxxx" >> .env步骤 3
编写一个微型 fetch 辅助函数
一个 20 行左右的 `fetch()` 包装函数即可处理 Base URL、Authorization 请求头、JSON 请求体和错误规范化。在官方 SDK 发布之前,这是你唯一需要的抽象层。
// photta.js — one helper for every endpoint const BASE = "https://api.photta.app/api/v1"; export async function photta(path, init = {}) { const res = await fetch(BASE + path, { ...init, headers: { Authorization: `Bearer ${process.env.PHOTTA_API_KEY}`, "Content-Type": "application/json", ...(init.headers ?? {}) } }); const body = await res.json(); if (!res.ok) throw Object.assign(new Error(body.error?.message ?? res.statusText), { status: res.status, retryAfter: res.headers.get("Retry-After"), body }); return body; }步骤 4
提交 try-on 任务并轮询
使用文档示例中的请求体向 `/api/v1/tryon/jewelry` 发送 POST 请求——下方的代码包含了所有字段。API 会立即返回一个生成 ID。每隔 3 秒轮询一次 `/api/v1/tryon/jewelry/{id}`,直到 `status === 'completed'`。
const res = await fetch("https://api.photta.app/api/v1/tryon/jewelry", { method: "POST", headers: { Authorization: `Bearer ${process.env.PHOTTA_API_KEY}`, "Content-Type": "application/json" }, body: JSON.stringify({ "jewelry_image": "https://cdn.yourstore.com/products/gold-necklace.jpg", "jewelry_type": "necklace", "mannequin_id": "mnk_j9k1l2", "background": "soft window light on dark velvet", "resolution": "2K", "aspect_ratio": "3:4", "user_instruction": "Make the pendant 10% smaller." }), }); 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/tryon/jewelry/${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"); }步骤 5
持久化存储结果
完成状态的 payload 包含 `output_url` 和 `thumbnail_url`。拉取一次字节流并存入你自己的对象存储中——这些 URL 虽是长期有效的,但你的产品不应依赖 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 {
await photta("/tryon/jewelry", { method: "POST", body: JSON.stringify({
"jewelry_image": "https://cdn.yourstore.com/products/gold-necklace.jpg",
"jewelry_type": "necklace",
"mannequin_id": "mnk_j9k1l2",
"background": "soft window light on dark velvet",
"resolution": "2K",
"aspect_ratio": "3:4",
"user_instruction": "Make the pendant 10% smaller."
}) });
} catch (err) {
if (err.status === 402) console.error("insufficient_credits_error: top up before retrying");
else if (err.status === 429) await new Promise((r) => setTimeout(r, Number(err.retryAfter ?? 30) * 1000));
else throw err;
}限制
- 每个 API 密钥每分钟 600 次请求 (固定窗口;各套餐限制相同)
- 429 响应包含 Retry-After: 30 秒
- 单张图片最大 10 MB
- 格式:: JPEG, PNG, WebP
- 各套餐并发批处理数:: Free 1 · Hobby 2 · Seller 3 · Brand 4 · Studio 6
- 仅支持轮询 — API 不发送 Webhook。
为什么辅助函数目前优于客户端 SDK
- Node 18+ 内置原生 fetch——零运行时依赖
- 同一个辅助函数可在 Next.js 路由处理程序、Server Actions 以及任何 Worker 中直接运行
- 将 API Key 保留在环境变量中;切勿在 'use client' 模块中导入该辅助函数,否则打包器会将其泄露
- 兼容任何队列系统或定时任务:BullMQ、Inngest、Trigger.dev、Vercel Cron、Cloudflare Queues
暂不支持的功能
- 尚无官方 @photta/node 包——目前 REST 是唯一的接入方式
- 轮询是唯一的完成信号;API 不发送 Webhook
- 仅支持 Bearer Key;没有 OAuth 客户端凭据流程
开发者常见问题
是否有官方的 Photta Node.js SDK?
暂无。文档推荐的做法是通过 Node 原生 fetch 调用底层 REST API——本页提供的辅助函数就是完整的集成实现,且适用于所有功能特性。
支持哪些 Node.js 版本?
任何支持原生 `fetch` 的版本——即 Node 18 及更高版本。在 Node 16 上,你需要使用 `node-fetch` 打 polyfill 或直接升级环境。其余代码均为纯 ECMAScript 2020(async/await、模板字符串、动态导入),无其他运行时要求。
如何从 Node 进行身份验证?
在每个请求中携带 `Authorization: Bearer photta_live_xxx`。将密钥存入环境变量并通过 `process.env` 读取;切勿在浏览器端运行的文件中导入它。
如何处理生成等待窗口?
生成 endpoint 完全采用异步设计。POST 请求会立即返回一个带有 `status: 'processing'` 的生成 ID。每隔 3–5 秒轮询一次 `GET /api/v1/tryon/jewelry/{id}`,直到 `status` 变为 `completed` 或 `failed`,并设置最大重试次数以防卡住的任务导致请求无限挂起。
我可以在 Next.js 内部调用此 API 吗?
可以——在路由处理程序(`app/**/route.ts`)、Server Action(`'use server'`)或中间件中调用。务必将 API Key 保留在服务端;切勿在 `'use client'` 文件中导入该辅助函数。对于执行时间超过 Vercel 函数超时的长任务,可将轮询交由队列系统(Inngest、Trigger.dev、BullMQ)处理,并将生成 ID 返回给浏览器,让前端轮询你自己的状态 endpoint。
API 如何返回错误信号?
非 2xx 响应会返回一个包含 `error` 对象的 JSON 请求体:`type`、`code`、`message` 以及用于支持排查的请求 ID。常见情况:400 invalid_request_error,附带指向错误字段的 `param`;402 insufficient_credits,附带 `required` 和 `available` 计数;429 rate_limit_exceeded,附带以秒为单位的 `retry_after` 及对应的 Retry-After 标头。5xx 错误可安全使用指数退避策略重试。
相关页面
Python
Python 中的 首饰试穿 API
在 Python 中使用 requests 库调用 Photta 的 首饰试穿 API。三十行包装函数,通过 httpx 具备异步亲和性,可在 Django、FastAPI 和 Celery 中开箱即用。
阅读cURL
通过 cURL 调用 首饰试穿 API
直接在终端中使用 cURL 调用 Photta 的 首饰试穿 API。提交、轮询、下载——每个代码片段均可搭配 jq 用于自动化流水线脚本。
阅读功能特性
首饰试穿 API 适用于项链、戒指、手链和耳环
通过 REST 将项链、戒指、手链和耳环穿戴至 AI 模特身上。2K 规格单次 5 credits,内置特写模特,具备 Photta 文档所述的反光感知渲染能力。
阅读构建
构建 AI 商品摄影服务
创始人将 Photta 虚拟 try-on API 作为白标 SaaS 转售的实战指南:租户 key、批量扇出、按 credit 计费以及 SLA 现实考量。
阅读快速开始
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 分辨率 5 credits · 4K 分辨率 6 credits
- 异步,轮询
- 600 次请求/分钟
- Bearer key