Node.js · API Virtual Try-On
API Virtual Try-On di Node.js
Belum ada paket @photta/node — dan Anda tidak membutuhkannya. Node 18+ menyertakan `fetch` secara bawaan, dan helper 20 baris bisa membawa Anda ke gambar model pertama dalam waktu sekitar lima menit.
Dalam satu kalimat
Set `PHOTTA_API_KEY` di env, tulis helper `phottaFetch()` kecil yang memanggil `https://ai.photta.app/api/v1` dengan `Authorization: Bearer photta_live_xxx`, POST ke `/tryon/apparel` dengan URL gambar produk, mannequin ID dan pose ID, lalu poll `/tryon/apparel/:id` setiap 3 detik hingga `status === 'completed'` — biasanya dalam 1.5–4 menit.
Diperbarui · 2026-04-19
Request pertama Anda
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);Apa yang diharapkan
Typical completion
1–3min
2K / 4K credits
4 / 6
Styles
2
Batch-ready
yes
Cara kerja
API Virtual Try-On di Node.js
Lima langkah, sekitar lima menit dari pendaftaran hingga gambar pertama.
- 01
Langkah 1
Daftar dan buat key
Buat akun di ai.photta.app. Buka bagian Developers di dashboard, klik Generate API key, dan ambil key livenya. Dimulai dengan `photta_live_` diikuti 32 karakter hex.
- 02
Langkah 2
Simpan key di env, bukan di kode sumber
Tambahkan `PHOTTA_API_KEY=...` ke `.env` (atau secret store platform Anda) dan muat via `process.env`. Jangan pernah commit key tersebut; jangan pernah impor ke file bertanda `'use client'` — bundler akan membawanya ke browser.
- 03
Langkah 3
Tulis helper fetch kecil
Satu wrapper 20 baris di sekitar `fetch()` menangani base URL, header Authorization, body JSON, dan normalisasi error. Ini adalah satu-satunya abstraksi yang Anda butuhkan sampai SDK resmi dirilis.
- 04
Langkah 4
Kirim try-on dan poll
Kirim POST ke `/tryon/apparel` dengan `product_type`, `product_images`, `mannequin_id`, `pose_id`, `resolution` dan `aspect_ratio`. API mengembalikan ID generasi segera. Poll `/tryon/apparel/:id` setiap 3 detik hingga `status === 'completed'`.
- 05
Langkah 5
Simpan hasilnya
Payload yang selesai menyertakan `output_url` dan `thumbnail_url`. Ambil byte-nya sekali dan simpan di penyimpanan objek Anda sendiri — URL-nya stabil tetapi produk Anda sebaiknya tidak bergantung pada CDN Photta untuk rendering.
Kode, ujung ke ujung
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;
}Mengapa pola ini
Mengapa helper lebih baik daripada library klien — untuk saat ini
- 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
Apa yang tidak bisa dilakukan
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
Pertanyaan pengembang lainnya
Questions other developers ask
Apakah ada SDK Node.js resmi Photta?+
Belum ada. Dokumentasi Photta merencanakan SDK setelah ambang batas adopsi tercapai: Python setelah sepuluh pengguna API, Node.js pada dua puluh. Hingga saat itu, jalur yang didokumentasikan adalah REST murni via cURL, fetch bawaan Node, atau library requests Python. Helper 20 baris di halaman ini setara dengan klien untuk endpoint yang paling sering Anda gunakan.
Versi Node.js apa saja yang didukung?+
Apa pun yang mendukung `fetch` bawaan — yang berarti Node 18 dan versi lebih baru. Pada Node 16, Anda perlu polyfill dengan `node-fetch` atau upgrade. Sisa kodenya adalah ECMAScript 2020 standar (async/await, template literals, dynamic imports) sehingga tidak ada persyaratan runtime lain.
Bagaimana cara autentikasi dari Node?+
Kirim `Authorization: Bearer photta_live_xxx` pada setiap request. Key dimulai dengan `photta_live_` di produksi, `photta_test_` saat sandbox dirilis. Simpan di variabel lingkungan dan muat melalui `process.env.PHOTTA_API_KEY`. API belum mendukung OAuth client credentials atau auth berbasis sesi.
Bagaimana cara menangani jendela generasi 1.5–4 menit?+
Endpoint try-on sepenuhnya asinkron. POST mengembalikan ID generasi segera dengan `status: 'processing'`. Poll `GET /tryon/apparel/:id` setiap 3–5 detik hingga `status` berubah menjadi `completed` atau `failed`. Berikan batas maksimal percobaan agar job yang macet tidak menggantung request Anda selamanya — 120 percobaan dalam 3 detik mencakup jendela waktu yang didokumentasikan dengan margin yang cukup.
Bisakah saya memanggil API di dalam Next.js?+
Ya — dari route handler (`app/**/route.ts`), server action (`'use server'`), atau middleware. Simpan API key di server; jangan pernah impor helper dari file `'use client'`. Untuk job yang berjalan lama melebihi timeout fungsi Vercel, tunda polling ke antrean (Inngest, Trigger.dev, BullMQ) dan kembalikan ID generasi ke browser agar bisa melakukan polling ke webhook atau endpoint status Anda sendiri.
Bagaimana API memberi sinyal error?+
Respons non-2xx membawa body JSON dengan objek `error`: `type`, `code`, `message` dan ID request untuk dukungan. Kasus umum: 400 invalid_request_error dengan `param` menunjuk ke field yang salah; 402 insufficient_credits dengan jumlah `required` dan `available`; 429 rate_limit_exceeded dengan `retry_after` dalam detik dan header Retry-After yang sesuai. Error 5xx aman untuk dicoba kembali dengan exponential backoff.
Node.js · API Virtual Try-On
Buat akun dan dapatkan API key
Set `PHOTTA_API_KEY` di env, tulis helper `phottaFetch()` kecil yang memanggil `https://ai.photta.app/api/v1` dengan `Authorization: Bearer photta_live_xxx`, POST ke `/tryon/apparel` dengan URL gambar produk, mannequin ID dan pose ID, lalu poll `/tryon/apparel/:id` setiap 3 detik hingga `status === 'completed'` — biasanya dalam 1.5–4 menit.