Node.js · Virtual Try-On API
Virtual Try-On API in Node.js
Es gibt noch kein @photta/node Paket — und Sie brauchen auch keines. Node 18+ unterstützt `fetch` nativ, und ein 20-Zeilen-Helper bringt Sie in etwa fünf Minuten zu Ihrem ersten On-Model-Bild.
Kurz zusammengefasst
Setzen Sie `PHOTTA_API_KEY` in env, schreiben Sie einen kleinen `phottaFetch()` Helper, der `https://ai.photta.app/api/v1` mit `Authorization: Bearer photta_live_xxx` aufruft, POST an `/tryon/apparel` mit Produkt-URL, Mannequin-ID und Pose-ID, dann pollen Sie `/tryon/apparel/:id` alle 3 Sekunden bis `status === 'completed'` — typischerweise innerhalb von 1.5–4 Minuten.
Aktualisiert · 2026-04-19
Ihr erster Request
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);Was Sie erwartet
Typical completion
1–3min
2K / 4K credits
4 / 6
Styles
2
Batch-ready
yes
Funktionsweise
Virtual Try-On API in Node.js
Fünf Schritte, etwa fünf Minuten vom Signup zum ersten Bild.
- 01
Schritt 1
Registrieren und Key generieren
Erstellen Sie einen Account auf ai.photta.app. Öffnen Sie den Developers-Bereich, klicken Sie auf Generate API key und kopieren Sie den Live-Key. Er beginnt mit `photta_live_`, gefolgt von 32 Hex-Zeichen.
- 02
Schritt 2
Key in env speichern, nicht im Quellcode
Fügen Sie `PHOTTA_API_KEY=...` zur `.env` (oder dem Secret-Store Ihrer Plattform) hinzu und laden Sie ihn via `process.env`. Committen Sie den Key niemals; importieren Sie ihn niemals in Dateien mit `'use client'`, da der Bundler ihn sonst in den Browser zieht.
- 03
Schritt 3
Einen kleinen Fetch-Helper schreiben
Ein 20-zeiliger Wrapper um `fetch()` regelt die Base-URL, den Authorization-Header, den JSON-Body und die Fehlernormalisierung. Dies ist die einzige Abstraktion, die Sie benötigen, bis ein offizielles SDK erscheint.
- 04
Schritt 4
Try-On senden und pollen
POST an `/tryon/apparel` mit `product_type`, `product_images`, `mannequin_id`, `pose_id`, `resolution` und `aspect_ratio`. Die API liefert sofort eine Generations-ID. Pollen Sie `/tryon/apparel/:id` alle 3 Sekunden bis `status === 'completed'`.
- 05
Schritt 5
Ergebnis persistieren
Die fertige Payload enthält `output_url` und `thumbnail_url`. Laden Sie die Daten einmal herunter und speichern Sie sie in Ihrem eigenen Object-Storage — die URLs sind stabil, aber Ihr Produkt sollte für das Rendering nicht vom Photta-CDN abhängen.
Code, End-to-End
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;
}Warum diese Struktur
Warum ein Helper aktuell besser ist als eine Library
- 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
Was es nicht kann
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
Fragen anderer Entwickler
Questions other developers ask
Gibt es ein offizielles Photta Node.js SDK?+
Noch nicht. Die Dokumentation plant SDKs nach Erreichen bestimmter Nutzerzahlen: Python ab zehn API-Kunden, Node.js ab zwanzig. Bis dahin ist der dokumentierte Weg natives REST via cURL, Node fetch oder Python requests. Der 20-Zeilen-Helper auf dieser Seite entspricht funktional einem Client für die meistgenutzten Endpunkte.
Welche Node.js Versionen werden unterstützt?+
Alle Versionen mit nativem `fetch`-Support — also Node 18 und neuer. Bei Node 16 nutzen Sie entweder ein Polyfill wie `node-fetch` oder führen ein Upgrade durch. Der restliche Code ist Standard-ECMAScript 2020 (async/await, Template Literals, Dynamic Imports).
Wie authentifiziere ich mich in Node?+
Senden Sie `Authorization: Bearer photta_live_xxx` bei jedem Request. Der Key beginnt in Produktion mit `photta_live_`, im Sandbox-Modus (sobald verfügbar) mit `photta_test_`. Nutzen Sie Umgebungsvariablen über `process.env.PHOTTA_API_KEY`. OAuth oder Session-basierte Auth werden noch nicht unterstützt.
Wie gehe mit dem 1.5–4 Minuten Zeitfenster um?+
Der Try-On-Endpunkt ist vollständig asynchron. POST liefert sofort eine Generations-ID mit `status: 'processing'`. Pollen Sie `GET /tryon/apparel/:id` alle 3–5 Sekunden, bis der `status` auf `completed` oder `failed` wechselt. Begrenzen Sie die Anzahl der Versuche — 120 Versuche alle 3 Sekunden decken das dokumentierte Fenster mit Puffer ab.
Kann ich die API innerhalb von Next.js aufrufen?+
Ja — aus einem Route Handler (`app/**/route.ts`), einer Server Action (`'use server'`) oder einer Middleware. Halten Sie den API-Key auf dem Server; importieren Sie den Helper niemals in einer `'use client'` Datei. Bei Jobs, die das Vercel-Timeout überschreiten, lagern Sie das Polling in eine Queue aus (Inngest, Trigger.dev, BullMQ) und geben die Generations-ID an den Browser zurück, damit dieser einen Webhook oder Ihren Status-Endpunkt abfragen kann.
Wie signalisiert die API Fehler?+
Nicht-2xx-Antworten enthalten einen JSON-Body mit einem `error`-Objekt: `type`, `code`, `message` und eine Request-ID für den Support. Häufige Fälle: 400 invalid_request_error mit `param` Hinweis; 402 insufficient_credits mit Zähler für `required` und `available`; 429 rate_limit_exceeded mit `retry_after` Angabe. 5xx-Fehler können mit Exponential Backoff erneut versucht werden.
Node.js · Virtual Try-On API
Account erstellen und API-Key erhalten
Setzen Sie `PHOTTA_API_KEY` in env, schreiben Sie einen kleinen `phottaFetch()` Helper, der `https://ai.photta.app/api/v1` mit `Authorization: Bearer photta_live_xxx` aufruft, POST an `/tryon/apparel` mit Produkt-URL, Mannequin-ID und Pose-ID, dann pollen Sie `/tryon/apparel/:id` alle 3 Sekunden bis `status === 'completed'` — typischerweise innerhalb von 1.5–4 Minuten.