Node.js · 虚拟试穿 API
Node.js 虚拟试穿 API
目前还没有 @photta/node 包 —— 您也不需要它。Node 18+ 原生内置了 `fetch`,只需 20 行辅助代码,大约五分钟即可生成您的第一张模特图。
一句话介绍
在环境变量中设置 `PHOTTA_API_KEY`,编写一个简单的 `phottaFetch()` 辅助函数调用 `https://ai.photta.app/api/v1` 并携带 `Authorization: Bearer photta_live_xxx`,向 `/tryon/apparel` 发送 POST(包含产品图 URL、模特 ID 和姿势 ID),然后每 3 秒轮询一次 `/tryon/apparel/:id` 直至 `status === 'completed'` —— 通常在 1.5–4 分钟内完成。
已更新 · 2026-04-19
发起首次请求
import { phottaFetch } from "./photta.js";
// 1. Submit the job — returns a generation ID immediately.
const created = await phottaFetch("/tryon/apparel", {
method: "POST",
body: JSON.stringify({
product_type: "dress",
product_images: ["https://example.com/dress.jpg"],
mannequin_id: "mnq_athena_ts",
pose_id: "pose_standing_front",
resolution: "2K",
aspect_ratio: "3:4",
}),
});
const generationId = created.data.id;
// 2. Poll every 3 seconds until processing completes. Typical
// completion is 1.5–4 minutes; put an upper bound so a stuck
// job can't hang your request forever.
const pollInterval = 3000;
const maxAttempts = 120; // 120 × 3s = 6 minutes
let result;
for (let i = 0; i < maxAttempts; i++) {
result = await phottaFetch(`/tryon/apparel/${generationId}`);
if (result.data.status === "completed") break;
if (result.data.status === "failed") {
throw new Error(result.data.error_message);
}
await new Promise((r) => setTimeout(r, pollInterval));
}
console.log("Result:", result.data.output_url);预期效果
Typical completion
1.5–4min
2K / 4K credits
5 / 7
Jewelry types
4
Close-up mannequins
built-in
工作原理
Node.js 虚拟试穿 API
五个步骤,从注册到生成首张图片约五分钟。
- 01
步骤 1
注册并生成密钥
在 ai.photta.app 创建账户。打开仪表盘的 Developers 部分,点击 Generate API key 获取 live 密钥。它以 `photta_live_` 开头,后跟 32 位十六进制字符。
- 02
步骤 2
将密钥存入 env,而非源码
将 `PHOTTA_API_KEY=...` 添加到 `.env`(或您平台的密钥库)中,并通过 `process.env` 加载。切勿提交密钥;切勿在标有 `'use client'` 的文件中导入它 —— 否则打包工具会将其暴露到浏览器端。
- 03
步骤 3
编写简单的 fetch 辅助函数
一个 20 行左右的 `fetch()` 封装即可处理基础 URL、Authorization 请求头、JSON 请求体和错误规范化。在官方 SDK 发布前,这是您唯一需要的抽象。
- 04
步骤 4
提交试穿任务并轮询
向 `/tryon/apparel` 发送 POST,包含 `product_type`、`product_images`、`mannequin_id`、`pose_id`、`resolution` 和 `aspect_ratio`。API 会立即返回任务 ID。每 3 秒轮询一次 `/tryon/apparel/:id` 直至 `status === 'completed'`。
- 05
步骤 5
持久化结果
完成后的数据包含 `output_url` 和 `thumbnail_url`。请获取字节流并存入您自己的对象存储 —— URL 是稳定的,但您的产品不应依赖 Photta 的 CDN 进行渲染。
端到端代码
Copy, paste, done.
Four snippets — install prerequisites, wrap the REST call, submit + poll, then handle the errors that actually happen in production.
# Node 18+ ships fetch natively. No install step needed.
node --version # ensure v18 or later
# Optional: keep your API key out of source control
echo "PHOTTA_API_KEY=photta_live_xxxxx" >> .env// photta.js — a 20-line wrapper you can reuse across your app.
const PHOTTA_BASE_URL = "https://ai.photta.app/api/v1";
export async function phottaFetch(path, init = {}) {
const res = await fetch(`${PHOTTA_BASE_URL}${path}`, {
...init,
headers: {
"Authorization": `Bearer ${process.env.PHOTTA_API_KEY}`,
"Content-Type": "application/json",
...init.headers,
},
});
const body = await res.json();
if (!res.ok) {
const err = new Error(body?.error?.message ?? res.statusText);
err.status = res.status;
err.code = body?.error?.code;
throw err;
}
return body;
}import { phottaFetch } from "./photta.js";
// 1. Submit the job — returns a generation ID immediately.
const created = await phottaFetch("/tryon/apparel", {
method: "POST",
body: JSON.stringify({
product_type: "dress",
product_images: ["https://example.com/dress.jpg"],
mannequin_id: "mnq_athena_ts",
pose_id: "pose_standing_front",
resolution: "2K",
aspect_ratio: "3:4",
}),
});
const generationId = created.data.id;
// 2. Poll every 3 seconds until processing completes. Typical
// completion is 1.5–4 minutes; put an upper bound so a stuck
// job can't hang your request forever.
const pollInterval = 3000;
const maxAttempts = 120; // 120 × 3s = 6 minutes
let result;
for (let i = 0; i < maxAttempts; i++) {
result = await phottaFetch(`/tryon/apparel/${generationId}`);
if (result.data.status === "completed") break;
if (result.data.status === "failed") {
throw new Error(result.data.error_message);
}
await new Promise((r) => setTimeout(r, pollInterval));
}
console.log("Result:", result.data.output_url);try {
await phottaFetch("/tryon/apparel", {
method: "POST",
body: JSON.stringify({ /* … */ }),
});
} catch (err) {
if (err.status === 402) {
// Out of credits — surface a top-up CTA to the user.
// err.code === "insufficient_credits"
} else if (err.status === 429) {
// Rate-limited. Honour the Retry-After header.
const retryAfter = err.retryAfter ?? 30;
await new Promise((r) => setTimeout(r, retryAfter * 1000));
// Then retry…
} else if (err.status >= 500) {
// Server-side issue — backoff + retry.
}
throw err;
}设计初衷
为什么现阶段辅助函数优于客户端库
- Node 18+ ships native fetch — no runtime deps required
- Same helper works inside Next.js route handlers, API routes, server actions and edge functions
- Keep API keys in env; never import the helper from a 'use client' module or the bundler will leak them
- Works with any queue/cron: BullMQ, Inngest, Trigger.dev, Vercel Cron, Cloudflare Queues
功能边界
Honest caveats
- No official @photta/node SDK yet — REST is the only path today
- No built-in webhook delivery; polling is the documented pattern (3–5s interval)
- Bearer token lives in env; the API doesn't support OAuth client credentials yet
开发者常见问题
Questions other developers ask
有官方的 Photta Node.js SDK 吗?+
目前还没有。Photta 文档明确计划在达到用户阈值后发布 SDK:Python 需 10 个 API 用户,Node.js 需 20 个。在此之前,推荐路径是直接使用 cURL、Node 原生 fetch 或 Python requests。本页面的 20 行辅助函数功能上等同于您最常用端点的客户端。
支持哪些 Node.js 版本?+
任何支持原生 `fetch` 的版本 —— 即 Node 18 及更高版本。在 Node 16 上,您需要使用 `node-fetch` 进行 polyfill 或升级环境。其余代码为标准的 ECMAScript 2020(async/await, 模板字符串, 动态导入),无其他运行时要求。
如何在 Node 中进行认证?+
在每个请求中发送 `Authorization: Bearer photta_live_xxx`。生产环境密钥以 `photta_live_` 开头,沙盒模式上线后将使用 `photta_test_`。将其存入环境变量并加载。API 目前暂不支持 OAuth 客户端凭据或基于 session 的认证。
如何处理 1.5–4 分钟的生成窗口?+
试穿端点是完全异步的。POST 请求会立即返回任务 ID 且 `status: 'processing'`。每 3–5 秒轮询一次 `GET /tryon/apparel/:id` 直至 `status` 变为 `completed` 或 `failed`。请务必设置尝试次数上限(如 3 秒一次,共 120 次),防止脚本无限挂起。
我可以在 Next.js 中调用 API 吗?+
可以 —— 在 route handler (`app/**/route.ts`)、server action (`'use server'`) 或中间件中调用。请务必在服务器端保留 API 密钥;严禁在 `'use client'` 文件中导入辅助函数。对于超过 Vercel 函数超时的任务,建议将轮询交给队列(Inngest, Trigger.dev, BullMQ),并将任务 ID 返回给浏览器,由前端查询您的状态端点。
API 如何返回错误?+
非 2xx 响应包含一个 JSON 请求体,其中包含 `error` 对象:`type`、`code`、`message` 以及用于技术支持的请求 ID。常见情况:400 invalid_request_error 会在 `param` 中指出错误字段;402 insufficient_credits 包含 `required` 和 `available` 计数;429 rate_limit_exceeded 包含 `retry_after` 秒数。5xx 错误可以尝试指数退避重试。
Node.js · 虚拟试穿 API
创建账户并获取 API 密钥
在环境变量中设置 `PHOTTA_API_KEY`,编写一个简单的 `phottaFetch()` 辅助函数调用 `https://ai.photta.app/api/v1` 并携带 `Authorization: Bearer photta_live_xxx`,向 `/tryon/apparel` 发送 POST(包含产品图 URL、模特 ID 和姿势 ID),然后每 3 秒轮询一次 `/tryon/apparel/:id` 直至 `status === 'completed'` —— 通常在 1.5–4 分钟内完成。