Node.js · API try-on trang sức
API try-on trang sức trong Node.js
Tóm tắt trong một câu
Thiết lập PHOTTA_API_KEY trong env, viết một helper fetch ngắn cho https://api.photta.app/api/v1 kèm key Bearer, POST tới /api/v1/tryon/jewelry, sau đó poll /api/v1/tryon/jewelry/{id} mỗi 3 giây cho đến khi status là completed.
- Thời gian điển hình: 1.5–4 min
- Credits: 5 credits ở 2K · 6 credits ở 4K
- Xử lý: async, polling
- Giới hạn: 600 requests/min
- Xác thực: Bearer key
Mọi số liệu trên trang này đều lấy từ tài liệu Photta API · đã kiểm tra
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")Tổng quan nhanh
Tổng quan nhanh
- Endpoint
- POST /api/v1/tryon/jewelry
- Xác thực
- Bearer API key
- Xử lý
- Bất đồng bộ — polling status endpoint
- Thời gian điển hình
- 1.5–4 min
- Credits
- 5 credits ở 2K · 6 credits ở 4K
- Tỷ lệ khung hình
- 3:4 · 1:1 · 4:3 · 9:16 · 16:9
- Giới hạn đầu vào
- Tối đa 10 MB mỗi ảnh; JPEG, PNG, WebP
- Idempotent
- Không
Cơ chế hoạt động
Năm bước, mất khoảng năm phút từ khi đăng ký đến bức ảnh đầu tiên.
Bước 1
Đăng ký và tạo key
Tạo tài khoản tại ai.photta.app. Mở mục Developers trong dashboard, nhấp vào Generate API key và lấy live key. Key bắt đầu bằng `photta_live_` theo sau là 32 ký tự hex.
Bước 2
Lưu key trong env, không để trong source code
Thêm `PHOTTA_API_KEY=...` vào file `.env` (hoặc kho lưu trữ secret trên nền tảng của bạn) và nạp qua `process.env`. Tuyệt đối không commit key; không import key vào file có đánh dấu `'use client'` — trình đóng gói sẽ kéo nó ra phía browser.
node --version # 18 or later ships fetch echo "PHOTTA_API_KEY=photta_live_xxxxx" >> .envBước 3
Viết một helper fetch nhỏ gọn
Một wrapper 20 dòng bọc quanh `fetch()` xử lý URL gốc, header Authorization, body JSON và chuẩn hóa lỗi. Đây là lớp trừu tượng duy nhất bạn cần cho đến khi SDK chính thức được phát hành.
// 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; }Bước 4
Gửi yêu cầu try-on và poll
POST tới `/api/v1/tryon/jewelry` với body mẫu theo tài liệu — mã nguồn bên dưới chứa đầy đủ mọi trường. API trả về ID tạo ảnh ngay lập tức. Poll `/api/v1/tryon/jewelry/{id}` mỗi 3 giây cho đến khi `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"); }Bước 5
Lưu trữ kết quả
Payload hoàn thành bao gồm `output_url` và `thumbnail_url`. Fetch dữ liệu một lần và lưu vào object storage của riêng bạn — các URL này ổn định nhưng sản phẩm của bạn không nên phụ thuộc vào CDN của Photta để hiển thị.
Lỗi
- 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;
}Giới hạn
- 600 request mỗi phút trên mỗi API key (Fixed window; giới hạn như nhau trên mọi gói)
- Mã 429 kèm header Retry-After: 30 giây
- Tối đa 10 MB mỗi ảnh
- Định dạng: JPEG, PNG, WebP
- Batch đồng thời theo từng gói: Free 1 · Hobby 2 · Seller 3 · Brand 4 · Studio 6
- Chỉ hỗ trợ polling — API không gửi webhook.
Vì sao dùng helper tốt hơn thư viện client — vào lúc này
- Node 18+ tích hợp sẵn fetch gốc — không phụ thuộc runtime
- Cùng một helper hoạt động tốt trong Next.js route handlers, server actions và bất kỳ worker nào
- Lưu API key trong env; không bao giờ import helper từ module 'use client' nếu không bundler sẽ làm lộ key
- Tương thích với mọi queue hoặc cron: BullMQ, Inngest, Trigger.dev, Vercel Cron, Cloudflare Queues
Những gì API không hỗ trợ
- Chưa có package @photta/node chính thức — hiện tại REST là cách duy nhất
- Polling là tín hiệu hoàn thành duy nhất; API không gửi webhook
- Chỉ dùng khóa Bearer; không có luồng OAuth client-credentials
Câu hỏi thường gặp từ developer
Có SDK Photta chính thức cho Node.js không?
Chưa có. Cách thức theo tài liệu là REST thuần qua fetch gốc của Node — helper trên trang này là toàn bộ phạm vi tích hợp, và hoạt động tương tự cho mọi capability.
Những phiên bản Node.js nào được hỗ trợ?
Bất kỳ phiên bản nào hỗ trợ `fetch` gốc — nghĩa là Node 18 trở lên. Trên Node 16 bạn phải dùng polyfill với `node-fetch` hoặc nâng cấp. Phần mã còn lại là ECMAScript 2020 thuần (async/await, template literals, dynamic imports) nên không có yêu cầu runtime nào khác.
Xác thực từ Node như thế nào?
Gửi `Authorization: Bearer photta_live_xxx` trong mỗi request. Đặt key trong biến môi trường và nạp qua `process.env`; không bao giờ import key từ file chạy trên trình duyệt.
Xử lý khoảng thời gian tạo ảnh thế nào?
Endpoint tạo ảnh hoàn toàn bất đồng bộ. POST trả về ID tạo ảnh ngay lập tức với `status: 'processing'`. Poll `GET /api/v1/tryon/jewelry/{id}` mỗi 3–5 giây cho đến khi `status` chuyển sang `completed` hoặc `failed`, và giới hạn số lần thử để tác vụ bị treo không làm nghẽn request.
Tôi có thể gọi API bên trong Next.js không?
Được — từ route handler (`app/**/route.ts`), server action (`'use server'`), hoặc middleware. Giữ API key trên server; không bao giờ import helper từ file `'use client'`. Đối với các tác vụ chạy lâu vượt quá timeout hàm của Vercel, hãy chuyển việc polling sang một queue (Inngest, Trigger.dev, BullMQ) và trả ID tạo ảnh về trình duyệt để client tự poll endpoint trạng thái của bạn.
API báo lỗi như thế nào?
Các phản hồi non-2xx trả về JSON body kèm object `error`: `type`, `code`, `message` và ID request để hỗ trợ. Các trường hợp thường gặp: 400 invalid_request_error với `param` chỉ ra trường không hợp lệ; 402 insufficient_credits kèm số lượng `required` và `available`; 429 rate_limit_exceeded kèm `retry_after` tính bằng giây và header Retry-After tương ứng. Các lỗi 5xx có thể thử lại an toàn với exponential backoff.
Các trang liên quan
Python
API try-on trang sức trong Python
Gọi aPI try-on trang sức của Photta trong Python với thư viện requests. Wrapper ba mươi dòng, hỗ trợ async qua httpx, hoạt động trong Django, FastAPI và Celery.
ĐọccURL
API try-on trang sức với cURL
Gọi trực tiếp aPI try-on trang sức của Photta từ shell bằng cURL. Gửi request, poll, tải về — mọi snippet đều kết hợp hoàn hảo với jq cho các script pipeline.
ĐọcTính năng
API try-on trang sức dành cho dây chuyền, nhẫn, vòng tay và hoa tai
Đưa dây chuyền, nhẫn, vòng tay và hoa tai lên người mẫu AI qua REST. 5 credits ở độ phân giải 2K, tích hợp sẵn mannequin cận cảnh, render chuẩn phản chiếu theo tài liệu Photta.
ĐọcXây dựng
Xây dựng dịch vụ chụp ảnh sản phẩm bằng AI
Sổ tay chiến lược dành cho founder để bán lại virtual try-on API của Photta dưới dạng SaaS white-label: khóa cho từng tenant, xử lý phân nhánh hàng loạt, thanh toán theo credit, thực tế về SLA.
ĐọcBắt đầu nhanh
Tạo ảnh Photta đầu tiên trong vòng chưa đầy năm phút.
Đăng ký, tạo API key, chạy lệnh cURL đầu tiên, polling cho đến khi hoàn thành, lưu trữ kết quả. Năm bước, có tài liệu hướng dẫn trọn gói từ đầu đến cuối.
ĐọcTài liệu tham khảo
Bảng giá Photta API
Chi phí tính bằng credits cho từng endpoint của Photta API ở độ phân giải 2K và 4K, cơ chế trừ phí và hoàn tiền, cùng các endpoint miễn phí. Không tính giá tiền trực tiếp trên từng ảnh.
Đọc
Mọi số liệu trên trang này đều lấy từ tài liệu Photta API · đã kiểm tra
Thử nghiệm API trong năm phút
Tạo một Photta API key, dán đoạn mã cURL ở trên, và bạn sẽ nhận được bức ảnh mẫu mặc đồ đầu tiên trước khi pha xong ly cà phê.
- 1.5–4 min
- 5 credits ở 2K · 6 credits ở 4K
- async, polling
- 600 requests/min
- Bearer key