Node.js · Ghost-Mannequin-API
Ghost-Mannequin-API in Node.js
In aller Kürze
Setzen Sie PHOTTA_API_KEY im Env, schreiben Sie einen kleinen fetch-Helper für https://api.photta.app/api/v1 mit einem Bearer-Key, senden Sie einen POST an /api/v1/ghost-mannequin und pollen Sie /api/v1/ghost-mannequin/{id} alle 3 Sekunden, bis der Status completed ist.
- Typische Dauer: 1.5–4 min
- Credits: 4 Credits bei 2K · 5 Credits bei 4K
- Verarbeitung: asynchron, Polling
- Limits: 600 Anfragen/Min.
- Authentifizierung: Bearer-Key
Jeder Zahlenwert auf dieser Seite stammt aus der Photta-API-Dokumentation · geprüft
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")Auf einen Blick
Auf einen Blick
- Endpoint
- POST /api/v1/ghost-mannequin
- Authentifizierung
- Bearer-API-Schlüssel
- Verarbeitung
- Asynchron — Polling über den Status-Endpoint
- Typische Dauer
- 1.5–4 min
- Credits
- 4 Credits bei 2K · 5 Credits bei 4K
- Seitenverhältnisse
- 3:4 · 1:1 · 4:3 · 9:16 · 16:9
- Eingabelimits
- Bis zu 10 MB pro Bild; JPEG, PNG, WebP
- Idempotent
- Nein
Funktionsweise
Fünf Schritte, etwa fünf Minuten von der Registrierung bis zum ersten Bild.
Schritt 1
Registrieren und Key generieren
Erstellen Sie einen Account unter ai.photta.app. Öffnen Sie den Entwicklerbereich im Dashboard, klicken Sie auf API-Key generieren und kopieren Sie den Live-Key. Er beginnt mit `photta_live_`, gefolgt von 32 Hexadezimalzeichen.
Schritt 2
Key im Env speichern, nicht im Sourcecode
Fügen Sie `PHOTTA_API_KEY=...` zu `.env` (oder dem Secret-Store Ihrer Plattform) hinzu und laden Sie ihn über `process.env`. Den Key niemals committen; niemals in eine Datei mit der Kennzeichnung `'use client'` importieren — der Bundler bindet ihn sonst im Browser ein.
node --version # 18 or later ships fetch echo "PHOTTA_API_KEY=photta_live_xxxxx" >> .envSchritt 3
Schreiben Sie einen winzigen fetch-Helper
Ein 20-zeiliger Wrapper um `fetch()` verarbeitet die Basis-URL, den Authorization-Header, den JSON-Body und die Fehlernormalisierung. Dies ist die einzige Abstraktion, die Sie benötigen, bis ein offizielles SDK veröffentlicht wird.
// 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; }Schritt 4
Einen Try-on absenden und pollen
Senden Sie einen POST-Request an `/api/v1/ghost-mannequin` mit dem dokumentierten Beispiel-Body — der folgende Code enthält jedes Feld. Die API liefert sofort eine Generation-ID zurück. Pollen Sie `/api/v1/ghost-mannequin/{id}` alle 3 Sekunden, bis `status === 'completed'` gilt.
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"); }Schritt 5
Das Ergebnis persistieren
Die abgeschlossene Payload enthält `output_url` und `thumbnail_url`. Rufen Sie die Bytes einmal ab und speichern Sie sie in Ihrem eigenen Objektspeicher — die URLs sind stabil, aber Ihr Produkt sollte für das Rendering nicht vom CDN von Photta abhängen.
Fehler
- 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;
}Limits
- 600 Anfragen pro Minute pro API-Schlüssel (Festes Zeitfenster; das Limit ist in jedem Tarif identisch)
- Ein 429 enthält Retry-After: 30 Sekunden
- Bis zu 10 MB pro Bild
- Formate: JPEG, PNG, WebP
- Gleichzeitige Batches pro Tarif: Free 1 · Hobby 2 · Seller 3 · Brand 4 · Studio 6
- Nur Polling — die API sendet keine Webhooks.
Warum ein Helper besser ist als eine Client-Bibliothek — vorerst
- Node 18+ bringt natives fetch mit — keine Laufzeit-Abhängigkeiten
- Derselbe Helper funktioniert innerhalb von Next.js Route Handlers, Server Actions und jedem Worker
- Behalten Sie den API-Key in env; importieren Sie den Helper niemals aus einem 'use client'-Modul, da der Bundler ihn sonst leakt
- Funktioniert mit jeder Queue oder jedem Cron: BullMQ, Inngest, Trigger.dev, Vercel Cron, Cloudflare Queues
Was es nicht tut
- Noch kein offizielles @photta/node-Paket — REST ist derzeit der einzige Weg
- Polling ist das einzige Signal für den Abschluss; die API sendet keine Webhooks
- Nur Bearer-Keys; es gibt keinen OAuth-Client-Credentials-Flow
Häufige Fragen von Entwicklern
Gibt es ein offizielles Photta Node.js-SDK?
Noch nicht. Der dokumentierte Weg ist reines REST über das native fetch von Node — der Helper auf dieser Seite deckt die gesamte Integrationsfläche ab und funktioniert für jede Capability identisch.
Welche Node.js-Versionen werden unterstützt?
Alles, was natives `fetch` unterstützt — also Node 18 und neuer. Unter Node 16 verwenden Sie entweder einen Polyfill mit `node-fetch` oder führen ein Upgrade durch. Der restliche Code ist reines ECMAScript 2020 (async/await, Template-Literale, dynamische Importe), es gibt also keine weiteren Laufzeit-Anforderungen.
Wie authentifiziere ich mich aus Node?
Senden Sie `Authorization: Bearer photta_live_xxx` bei jedem Request. Hinterlegen Sie den Key in einer Umgebungsvariable und laden Sie ihn über `process.env`; importieren Sie ihn niemals aus einer Datei, die im Browser ausgeführt wird.
Wie gehe ich mit dem Generierungsfenster um?
Der Generierungs-Endpoint ist vollständig asynchron. POST gibt sofort eine Generation-ID mit `status: 'processing'` zurück. Pollen Sie `GET /api/v1/ghost-mannequin/{id}` alle 3–5 Sekunden, bis der `status` auf `completed` oder `failed` wechselt, und begrenzen Sie die Versuche, damit ein hängengebliebener Job keinen Request blockiert.
Kann ich die API innerhalb von Next.js aufrufen?
Ja — über einen Route Handler (`app/**/route.ts`), eine Server Action (`'use server'`) oder Middleware. Halten Sie den API-Key auf dem Server; importieren Sie den Helper niemals aus einer `'use client'`-Datei. Bei lang laufenden Jobs, die das Funktions-Timeout von Vercel überschreiten, lagern Sie das Polling in eine Queue aus (Inngest, Trigger.dev, BullMQ) und geben die Generation-ID an den Browser zurück, damit dieser Ihren eigenen Status-Endpoint pollen 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`, das auf das fehlerhafte Feld verweist; 402 insufficient_credits mit Zählerständen für `required` und `available`; 429 rate_limit_exceeded mit `retry_after` in Sekunden und einem passenden Retry-After-Header. 5xx-Fehler können sicher mit exponentiellem Backoff wiederholt werden.
Verwandte Seiten
Python
Ghost-Mannequin-API in Python
Rufen Sie Phottas ghost-Mannequin-API in Python mit der requests-Bibliothek auf. Dreißigzeiliger Wrapper, async-kompatibel über httpx, funktioniert in Django, FastAPI und Celery.
LesencURL
Ghost-Mannequin-API mit cURL
Rufen Sie Phottas ghost-Mannequin-API direkt über die Shell mit cURL auf. Übermitteln, pollen, herunterladen — jedes Snippet lässt sich für skriptbasierte Pipelines mit jq kombinieren.
LesenFunktionen
Ghost-Mannequin-API für Hollow-Man-Produktfotos
KI-Ghost-Mannequin-Endpoint. Entfernt die Puppe aus einem Kleidungsfoto und bewahrt Innendetails. 3D oder Flat-Lay, Batch-Verarbeitung, 4 Credits bei 2K.
LesenBuild
Automatisieren Sie die Ghost-Mannequin-Freistellung für Ihren Katalog
Rezept für die nächtliche Katalog-Automatisierung: Ziehen Sie die Produkt-Updates von gestern, senden Sie sie als Batch an Phottas Ghost-Mannequin-API, pollen Sie den übergeordneten Batch und speichern Sie die Daten in Ihrer Datenbank.
LesenSchnellstart
Erstes Photta-Bild in unter 5 Minuten.
Registrieren, API-Key generieren, ersten cURL-Aufruf ausführen, pollen bis zum Abschluss, Ergebnis persistieren. 5 Schritte, durchgängig dokumentiert.
LesenReferenz
Photta-API-Preise
Was jeder Photta API-Endpoint in Credits bei 2K und 4K kostet, wie Abrechnung und Erstattungen funktionieren und welche Endpoints kostenlos sind. Kein Geldpreis pro Bild.
Lesen
Jeder Zahlenwert auf dieser Seite stammt aus der Photta-API-Dokumentation · geprüft
Testen Sie die API in fünf Minuten
Generieren Sie einen Photta-API-Schlüssel, fügen Sie das obige cURL-Snippet ein, und Sie erhalten Ihr erstes Bild am Model, noch bevor der Kaffee fertig gebrüht ist.
- 1.5–4 min
- 4 Credits bei 2K · 5 Credits bei 4K
- asynchron, Polling
- 600 Anfragen/Min.
- Bearer-Key