Build · Virtual Try-On
Bouw een virtual try-on-feature voor je app
In één zin
Accepteer de productfoto in je backend, POST deze naar /api/v1/tryon/apparel met een mannequin ID, poll het geretourneerde generation ID vanuit een background worker (nooit de HTTP-request-thread) totdat status naar completed springt, sla output_url vervolgens op in je eigen object storage en render deze in de UI.
- Credits: 5 credits bij 2K · 6 credits bij 4K
- Typische duur: 1.5–4 min
- Verwerking: async, polling
Elk getal op deze pagina is afkomstig uit de Photta-API-documentatie · gecontroleerd
Een recept klaar voor productie: de klant uploadt een productfoto, je backend zet een Photta try-on-taak in de wachtrij, een worker pollt tot deze klaar is, en de frontend toont het resultaat op een model. Geen blokkerende requests, geen gelekte API-keys, geen nep-SDK.
RESPONSE=$(curl -s -X POST https://api.photta.app/api/v1/tryon/apparel \
-H "Authorization: Bearer $PHOTTA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"product_type": "top",
"product_images": [
"https://cdn.yourstore.com/products/shirt-front.jpg"
],
"product_back_image": "https://cdn.yourstore.com/products/shirt-back.jpg",
"product_category": "t_shirt",
"mannequin_id": "mnk_f3a9b1",
"pose_id": "pose_c2d4e5",
"background": "https://cdn.yourstore.com/backgrounds/studio-loft.jpg",
"lock_background": true,
"resolution": "2K",
"aspect_ratio": "3:4",
"body_size": "M",
"expression": "neutral",
"user_instruction": "Keep the collar pattern crisp and centered."
}')
ID=$(echo "$RESPONSE" | jq -r '.data.id')const res = await fetch("https://api.photta.app/api/v1/tryon/apparel", {
method: "POST",
headers: { Authorization: `Bearer ${process.env.PHOTTA_API_KEY}`, "Content-Type": "application/json" },
body: JSON.stringify({
"product_type": "top",
"product_images": [
"https://cdn.yourstore.com/products/shirt-front.jpg"
],
"product_back_image": "https://cdn.yourstore.com/products/shirt-back.jpg",
"product_category": "t_shirt",
"mannequin_id": "mnk_f3a9b1",
"pose_id": "pose_c2d4e5",
"background": "https://cdn.yourstore.com/backgrounds/studio-loft.jpg",
"lock_background": true,
"resolution": "2K",
"aspect_ratio": "3:4",
"body_size": "M",
"expression": "neutral",
"user_instruction": "Keep the collar pattern crisp and centered."
}),
});
const { data } = await res.json(); // data.id, data.statusimport os, requests
res = requests.post(
"https://api.photta.app/api/v1/tryon/apparel",
headers={"Authorization": f"Bearer {os.environ['PHOTTA_API_KEY']}"},
json={
"product_type": "top",
"product_images": [
"https://cdn.yourstore.com/products/shirt-front.jpg"
],
"product_back_image": "https://cdn.yourstore.com/products/shirt-back.jpg",
"product_category": "t_shirt",
"mannequin_id": "mnk_f3a9b1",
"pose_id": "pose_c2d4e5",
"background": "https://cdn.yourstore.com/backgrounds/studio-loft.jpg",
"lock_background": True,
"resolution": "2K",
"aspect_ratio": "3:4",
"body_size": "M",
"expression": "neutral",
"user_instruction": "Keep the collar pattern crisp and centered."
},
)
data = res.json()["data"] # data["id"], data["status"]Hoe het werkt
Van upload tot on-model afbeelding
Zes concrete stappen. Reken de eerste keer op tien tot vijftien minuten integratiewerk.
Stap 1
Schets de datastroom
Device van klant → jouw backend (upload) → Photta API (submit) → Photta API (poll) → jouw database (status-mirror) → device van klant (render). Teken dit op papier voordat je de eerste regel code schrijft — de grens tussen jouw backend en die van Photta is het enige wat telt.
Stap 2
Genereer en bewaar een API-key
Live-keys beginnen met photta_live_. Sla deze op in een environment-variabele. Stuur deze nooit naar de browser. Eén key dekt elke Photta-functionaliteit, dus je hebt geen aparte keys nodig voor try-on, jewelry of ghost mannequin.
Stap 3
Koppel het upload-endpoint aan
Sla de productfoto van de klant eerst op in object storage. Photta een publieke URL geven is simpeler dan base64 en levert een audit trail op voor elk request.
Stap 4
Submit de taak vanaf de server
POST /api/v1/tryon/apparel met de product-URL, mannequin_id, resolution en aspect_ratio. De API retourneert 202 Accepted + een generation ID. Sla het ID op in je database zodat je client je eigen endpoint kan pollen, niet dat van Photta.
Stap 5
Poll vanuit een background worker
Poll niet binnen het HTTP-request — de taak duurt 1.5 tot 4 minuten, wat de meeste serverless timeouts overschrijdt. Gebruik Trigger.dev, Inngest, BullMQ, Vercel Cron of je eigen queue om elke 3 seconden opnieuw een poll in te plannen totdat de taak is voltooid.
Stap 6
Render het resultaat
Wanneer status verandert in completed, kopieer je data.output_url naar je database en verstuur je een realtime-event (websocket, SSE of long-polling) naar het device van de klant. De UI vervangt het laadskelet door de afbeelding. Klaar.
Drie codevoorbeelden, end-to-end
Upload-handler, job-dispatcher, poller aan de worker-zijde — elk onderdeel dat je nodig hebt om de feature uit te rollen.
// POST /app/try-on → your backend upload handler
import { put } from "@vercel/blob";
export async function uploadProduct(file: File) {
const { url } = await put(`products/${crypto.randomUUID()}.jpg`, file, {
access: "public",
});
return url;
}const res = await fetch("https://api.photta.app/api/v1/tryon/apparel", {
method: "POST",
headers: { Authorization: `Bearer ${process.env.PHOTTA_API_KEY}`, "Content-Type": "application/json" },
body: JSON.stringify({
"product_type": "top",
"product_images": [
"https://cdn.yourstore.com/products/shirt-front.jpg"
],
"product_back_image": "https://cdn.yourstore.com/products/shirt-back.jpg",
"product_category": "t_shirt",
"mannequin_id": "mnk_f3a9b1",
"pose_id": "pose_c2d4e5",
"background": "https://cdn.yourstore.com/backgrounds/studio-loft.jpg",
"lock_background": true,
"resolution": "2K",
"aspect_ratio": "3:4",
"body_size": "M",
"expression": "neutral",
"user_instruction": "Keep the collar pattern crisp and centered."
}),
});
const { data } = await res.json(); // data.id, data.status// Trigger.dev / Inngest / BullMQ task
const BASE = "https://api.photta.app/api/v1";
export const pollTryOnTask = task({
id: "poll-try-on",
run: async ({ generationId, attempt = 0 }) => {
const res = await fetch(`${BASE}/tryon/apparel/${generationId}`, {
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);
if (attempt >= 120) throw new Error("try-on timed out");
// Re-schedule this same task after 3 seconds.
return ctx.retry.after(3000, { generationId, attempt: attempt + 1 });
},
});Veelgestelde vragen van developers
Vragen vóórdat je uitrolt
Kan ik dit zonder backend doen?
Nee. Je Photta API-sleutel moet server-side blijven. Zelfs een eenvoudige Next.js route handler of een Cloudflare Worker telt hiervoor al als backend — de sleutel moet simpelweg op een plek staan waar een user-agent er niet bij kan.
Hoe voorkom ik dat HTTP-requests blijven hangen?
Voer nooit polling uit binnen een request handler. Dien de job synchroon in, stuur het generation ID terug naar de client en poll vanuit een background worker. De client pollt JOUW status endpoint, niet dat van Photta — op die manier zijn rate limits jouw verantwoordelijkheid en niet die van elke gebruiker afzonderlijk.
Wat gebeurt er als een job halverwege mislukt?
Photta vergoedt de credits automatisch bij een storing, en de response bevat data.error_code + data.error_message. Toon een duidelijke melding aan de gebruiker en bied een retry-knop aan die een nieuwe job start.
Kan ik echte voortgang tonen?
Photta geeft geen tussentijdse voortgang door — de status is processing, completed of failed. Wat goed werkt, is een progress bar met een timer afgestemd op de periode van 1.5–4 minuten, of een simpele skeleton loader. Verzin geen percentages.
Is de resultaat-URL permanent?
De CDN-URL is stabiel, maar je product moet hier voor langdurige weergave niet van afhangen. Download de bytes eenmalig en sla ze op in je eigen S3/GCS/R2-bucket — zo blijft je PDP werken, zelfs als de CDN van Photta verandert.
Gerelateerde pagina's
Referentie
Mogelijkheden
Virtual try-on API voor kleding
REST API die kleding op AI-mannequins plaatst. Asynchroon, generatie in 1.5–4 minuten, 5 credits bij 2K, 6 bij 4K. Voorbeelden in cURL, Node.js en Python.
LezenSnelstartgids
Eerste Photta-afbeelding in minder dan vijf minuten.
Registreer je, genereer een API-sleutel, voer je eerste cURL-call uit, poll totdat deze is voltooid, sla het resultaat op. Vijf stappen, end-to-end gedocumenteerd.
LezenTalen
Node.js walkthrough
LezenTalen
Python walkthrough
Lezen
Elk getal op deze pagina is afkomstig uit de Photta-API-documentatie · gecontroleerd
Lanceer virtuele try-on in een namiddag
Elk codevoorbeeld op deze pagina komt overeen met de officiële Photta-documentatie. Vraag een API-sleutel aan en je hebt een werkend prototype klaar voordat de koffie is doorgelopen.