Node.js · Ghost mannequin API
Ghost mannequin API di Node.js
Ringkasan singkat
Set PHOTTA_API_KEY di env, tulis helper fetch kecil untuk https://api.photta.app/api/v1 dengan kunci Bearer, POST ke /api/v1/ghost-mannequin, lalu lakukan polling ke /api/v1/ghost-mannequin/{id} setiap 3 detik hingga status completed.
- Waktu umum: 1.5–4 min
- Credits: 4 credits pada 2K · 5 credits pada 4K
- Pemrosesan: async, polling
- Batasan: 600 requests/min
- Autentikasi: Bearer key
Setiap angka di halaman ini bersumber dari dokumentasi API Photta · diperiksa
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")Sekilas
Sekilas
- Endpoint
- POST /api/v1/ghost-mannequin
- Autentikasi
- API key Bearer
- Pemrosesan
- Asinkron — lakukan polling ke endpoint status
- Waktu umum
- 1.5–4 min
- Credits
- 4 credits pada 2K · 5 credits pada 4K
- Rasio aspek
- 3:4 · 1:1 · 4:3 · 9:16 · 16:9
- Batas input
- Hingga 10 MB per gambar; JPEG, PNG, WebP
- Idempoten
- Tidak
Cara kerja
Lima langkah, sekitar lima menit dari pendaftaran hingga gambar pertama.
Langkah 1
Daftar dan buat kunci
Buat akun di ai.photta.app. Buka bagian Developers di dashboard, klik Generate API key, dan ambil live key tersebut. Kunci ini dimulai dengan `photta_live_` diikuti oleh 32 karakter heksadesimal.
Langkah 2
Simpan kunci di env, bukan di source code
Tambahkan `PHOTTA_API_KEY=...` ke `.env` (atau secret store platform Anda) dan muat melalui `process.env`. Jangan pernah commit kunci tersebut; jangan pernah mengimpornya ke dalam file yang ditandai `'use client'` — bundler akan memasukkannya ke browser.
node --version # 18 or later ships fetch echo "PHOTTA_API_KEY=photta_live_xxxxx" >> .envLangkah 3
Tulis helper fetch ringkas
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 hingga SDK resmi dirilis.
// 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; }Langkah 4
Kirim try-on dan lakukan polling
Kirim POST ke `/api/v1/ghost-mannequin` dengan contoh body yang terdokumentasi — kode di bawah mencakup setiap field. API langsung mengembalikan ID generasi. Lakukan polling ke `/api/v1/ghost-mannequin/{id}` setiap 3 detik hingga `status === 'completed'`.
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"); }Langkah 5
Simpan hasilnya
Payload yang selesai mencakup `output_url` dan `thumbnail_url`. Ambil byte-nya sekali dan simpan di object storage Anda sendiri — URL-nya stabil, tetapi produk Anda sebaiknya tidak bergantung pada CDN Photta untuk rendering.
Error
- 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("/ghost-mannequin", { method: "POST", 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"
}) });
} 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;
}Batasan
- 600 request per menit per API key (Fixed window; batasannya sama di setiap paket)
- Respons 429 menyertakan Retry-After: 30 detik
- Hingga 10 MB per gambar
- Format: JPEG, PNG, WebP
- Batch konkuren per paket: Free 1 · Hobby 2 · Seller 3 · Brand 4 · Studio 6
- Hanya polling — API tidak mengirim webhook.
Mengapa helper lebih baik daripada client library — untuk saat ini
- Node 18+ menyediakan native fetch — tanpa dependensi runtime
- Helper yang sama bekerja di dalam route handler Next.js, server action, dan worker apa pun
- Simpan API key di env; jangan pernah mengimpor helper dari modul 'use client' atau bundler akan membocorkannya
- Bekerja dengan antrean atau cron apa pun: BullMQ, Inngest, Trigger.dev, Vercel Cron, Cloudflare Queues
Yang tidak dilakukannya
- Belum ada paket resmi @photta/node — REST adalah satu-satunya jalur saat ini
- Polling adalah satu-satunya sinyal penyelesaian; API tidak mengirimkan webhook
- Hanya Bearer key; tidak ada alur client-credentials OAuth
Pertanyaan umum developer
Apakah ada SDK Node.js resmi dari Photta?
Belum ada. Jalur yang terdokumentasi adalah REST mentah via native fetch bawaan Node — helper di halaman ini mencakup seluruh integrasi, dan bekerja sama persis untuk setiap kapabilitas.
Versi Node.js apa saja yang didukung?
Versi apa pun yang mendukung native `fetch` — artinya Node 18 dan yang lebih baru. Pada Node 16, Anda dapat melakukan polyfill dengan `node-fetch` atau melakukan upgrade. Kode lainnya adalah ECMAScript 2020 standar (async/await, template literals, dynamic imports) sehingga tidak ada persyaratan runtime lainnya.
Bagaimana cara mengautentikasi dari Node?
Kirimkan `Authorization: Bearer photta_live_xxx` pada setiap request. Simpan key di environment variable dan muat via `process.env`; jangan pernah mengimpornya dari file yang berjalan di browser.
Bagaimana cara menangani jendela generasi?
Endpoint generasi sepenuhnya asinkron. POST langsung mengembalikan ID generasi dengan `status: 'processing'`. Lakukan polling `GET /api/v1/ghost-mannequin/{id}` setiap 3–5 detik hingga `status` berubah menjadi `completed` atau `failed`, dan batasi jumlah percobaan agar job yang macet tidak menggantung request.
Bisakah saya memanggil API di dalam Next.js?
Bisa — dari route handler (`app/**/route.ts`), server action (`'use server'`), atau middleware. Simpan API key di sisi server; jangan pernah mengimpor helper dari file `'use client'`. Untuk job berdurasi panjang yang melebihi batas function timeout Vercel, alihkan polling ke antrean (Inngest, Trigger.dev, BullMQ) dan kembalikan ID generasi ke browser agar browser dapat melakukan polling ke endpoint status Anda sendiri.
Bagaimana cara API menandai error?
Respons non-2xx memuat body JSON dengan objek `error`: `type`, `code`, `message`, dan request ID untuk bantuan teknis. Kasus umum: 400 invalid_request_error dengan `param` mengarah ke field yang bermasalah; 402 insufficient_credits dengan jumlah `required` dan `available`; 429 rate_limit_exceeded dengan `retry_after` dalam detik beserta header Retry-After yang sesuai. Error 5xx aman untuk di-retry dengan exponential backoff.
Halaman terkait
Python
Ghost mannequin API di Python
Panggil ghost mannequin API Photta di Python dengan library requests. Wrapper tiga puluh baris, ramah asinkron via httpx, bekerja di Django, FastAPI, dan Celery.
BacacURL
Ghost mannequin API dengan cURL
Panggil ghost mannequin API Photta langsung dari shell menggunakan cURL. Kirim, lakukan polling, unduh — setiap cuplikan kode dapat dipadukan dengan jq untuk pipeline berbasis skrip.
BacaKapabilitas
Ghost mannequin API untuk foto produk hollow-man
Endpoint AI ghost mannequin. Hapus manekin dari foto pakaian dan pertahankan detail bagian dalam. 3D atau flat-lay, pemrosesan batch, 4 credits pada 2K.
BacaBangun
Otomatiskan ekstraksi ghost mannequin untuk katalog Anda
Resep otomatisasi katalog harian: ambil pembaruan produk kemarin, kirim secara batch ke API ghost-mannequin Photta, lakukan polling pada parent batch, simpan ke database Anda.
BacaQuickstart
Gambar Photta pertama dalam waktu kurang dari lima menit.
Daftar, buat API key, jalankan pemanggilan cURL pertama Anda, lakukan polling hingga selesai, simpan hasilnya. Lima langkah, terdokumentasi end-to-end.
BacaReferensi
Harga Photta API
Biaya setiap endpoint Photta API dalam credits pada 2K dan 4K, cara kerja pemotongan dan pengembalian dana, serta endpoint mana saja yang gratis. Tidak ada harga uang per gambar.
Baca
Setiap angka di halaman ini bersumber dari dokumentasi API Photta · diperiksa
Coba API dalam lima menit
Buat Photta API key, tempel cuplikan cURL di atas, dan Anda akan mendapatkan gambar on-model pertama sebelum kopi selesai diseduh.
- 1.5–4 min
- 4 credits pada 2K · 5 credits pada 4K
- async, polling
- 600 requests/min
- Bearer key