Node.js · Virtuaalinen try-on API
Virtuaalinen try-on API Node.js:ssä
Yhdellä lauseella
Aseta PHOTTA_API_KEY ympäristömuuttujiin, kirjoita pieni fetch-apufunktio osoitteelle https://api.photta.app/api/v1 Bearer-avaimella, tee POST osoitteeseen /api/v1/tryon/apparel, ja pollaa sitten osoitetta /api/v1/tryon/apparel/{id} 3 sekunnin välein, kunnes tila on completed.
- Tyypillinen kesto: 1.5–4 min
- Credits: 5 credits resoluutiolla 2K · 6 credits resoluutiolla 4K
- Käsittely: asynkroninen, polling
- Rajoitukset: 600 pyyntöä/min
- Autentikointi: Bearer-avain
Jokainen luku tällä sivulla on peräisin Photta-rajapinnan dokumentaatiosta · tarkistettu
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')
# $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/tryon/apparel/$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/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
async function waitFor(id) {
for (let attempt = 0; attempt < 120; attempt++) {
const res = await fetch(`https://api.photta.app/api/v1/tryon/apparel/${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/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"]
import time
def wait_for(job_id):
for _ in range(120):
res = requests.get(f"https://api.photta.app/api/v1/tryon/apparel/{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")Lyhyesti
Lyhyesti
- Endpoint
- POST /api/v1/tryon/apparel
- Autentikointi
- Bearer-API-avain
- Käsittely
- Asynkroninen — tee polling-kyselyitä status-endpointiin
- Tyypillinen kesto
- 1.5–4 min
- Credits
- 5 credits resoluutiolla 2K · 6 credits resoluutiolla 4K
- Kuvasuhteet
- 3:4 · 1:1 · 4:3 · 9:16 · 16:9
- Syöterajoitukset
- Enintään 10 MB per kuva; JPEG, PNG, WebP
- Idempotentti
- Ei
Miten se toimii
Viisi vaihetta, noin viisi minuuttia rekisteröitymisestä ensimmäiseen kuvaan.
Vaihe 1
Rekisteröidy ja luo avain
Luo tili osoitteessa ai.photta.app. Avaa hallintapaneelin Developers-osio, napsauta Generate API key ja kopioi live-avain. Se alkaa merkkijonolla `photta_live_`, jota seuraa 32 heksadesimaalimerkkiä.
Vaihe 2
Tallenna avain ympäristömuuttujiin, älä lähdekoodiin
Lisää `PHOTTA_API_KEY=...` tiedostoon `.env` (tai alustasi salaisuuksien hallintaan) ja lataa se muuttujan `process.env` kautta. Älä koskaan commitoi avainta; älä koskaan tuo sitä tiedostoon, jossa on merkintä `'use client'` — paketointityökalu vie sen selaimeen.
node --version # 18 or later ships fetch echo "PHOTTA_API_KEY=photta_live_xxxxx" >> .envVaihe 3
Kirjoita pieni fetch-apufunktio
Yksi 20 rivin kääre `fetch()`-funktion ympärille hoitaa perus-URL:n, Authorization-otsakkeen, JSON-rungon ja virheiden normalisoinnin. Tämä on ainoa tarvitsemasi abstraktio, kunnes virallinen SDK julkaistaan.
// 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; }Vaihe 4
Lähetä try-on ja tee pollingia
Tee POST-pyyntö kohteeseen `/api/v1/tryon/apparel` dokumentoidulla esimerkki-payloadilla — alla oleva koodi sisältää jokaisen kentän. API palauttaa generointitunnisteen välittömästi. Pollaa `/api/v1/tryon/apparel/{id}` 3 sekunnin välein, kunnes `status === 'completed'`.
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 async function waitFor(id) { for (let attempt = 0; attempt < 120; attempt++) { const res = await fetch(`https://api.photta.app/api/v1/tryon/apparel/${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"); }Vaihe 5
Tallenna tulos pysyvästi
Valmis payload sisältää kentät `output_url` ja `thumbnail_url`. Nouda tavut kerran ja tallenna ne omaan objektitallennustilaasi — URL-osoitteet ovat pysyviä, mutta tuotteesi ei pitäisi riippua Phottan CDN:stä renderöintiä varten.
Virheet
- 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("/tryon/apparel", { method: "POST", 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."
}) });
} 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;
}Rajoitukset
- 600 pyyntöä minuutissa per API-avain (Kiinteä aikaikkuna; rajoitus on sama kaikissa tilauksissa)
- Vastaus 429 sisältää otsakkeen Retry-After: 30 sekuntia
- Enintään 10 MB per kuva
- Formaatit: JPEG, PNG, WebP
- Rinnakkaiset eräajot per tilaus: Free 1 · Hobby 2 · Seller 3 · Brand 4 · Studio 6
- Vain polling — API ei lähetä webhookeja.
Miksi apufunktio voittaa asiakaskirjaston — toistaiseksi
- Node 18+ sisältää natiivin fetchin — ei ajonaikaisia riippuvuuksia
- Sama apufunktio toimii Next.js-reittikäsittelijöissä, server actioneissa ja missä tahansa workerissa
- Pidä API-avain ympäristömuuttujissa; älä koskaan tuo apufunktiota 'use client' -moduuliin, jotta paketointityökalu ei vuoda sitä
- Toimii minkä tahansa jonon tai cronin kanssa: BullMQ, Inngest, Trigger.dev, Vercel Cron, Cloudflare Queues
Mitä se ei tee
- Ei vielä virallista @photta/node-pakettia — REST on ainoa tapa tällä hetkellä
- Polling on ainoa valmistumissignaali; API ei lähetä webhookeja
- Vain Bearer-avain; OAuth client-credentials -kulkua ei ole
Kehittäjien usein kysymää
Onko olemassa virallista Photta Node.js SDK:ta?
Ei vielä. Dokumentoitu tapa on suora REST Noden natiivin fetchin kautta — tällä sivulla oleva apufunktio on koko integraatiopinta, ja se toimii samalla tavalla jokaiselle kyvykkyydelle.
Mitä Node.js-versioita tuetaan?
Kaikkia, jotka tukevat natiivia `fetch`-funktiota — eli Node 18 ja uudemmat. Node 16 -versiossa joko käytät polyfilliä `node-fetch`-paketilla tai päivität uudempaan. Muu koodi on pelkkää ECMAScript 2020:tä (async/await, mallimerkkijonot, dynaamiset tuonnit), joten muita ajonaikaisia vaatimuksia ei ole.
Miten autentikoidun Nodesta?
Lähetä `Authorization: Bearer photta_live_xxx` jokaisessa pyynnössä. Aseta avain ympäristömuuttujaan ja lue se `process.env`-kautta; älä koskaan tuo sitä tiedostosta, jota ajetaan selaimessa.
Miten käsittelen generointi-ikkunan?
Generointi-endpoint on täysin asynkroninen. POST palauttaa generointitunnisteen välittömästi tilalla `status: 'processing'`. Pollaa `GET /api/v1/tryon/apparel/{id}` 3–5 sekunnin välein, kunnes `status` muuttuu arvoon `completed` tai `failed`, ja aseta yrityksille yläraja, jotta jumiutunut työ ei jätä pyyntöä roikkumaan.
Voinko kutsua APIa Next.js:n sisällä?
Kyllä — reittikäsittelijästä (`app/**/route.ts`), server actionista (`'use server'`) tai middlewaresta. Pidä API-avain palvelimella; älä koskaan tuo apufunktiota `'use client'` -tiedostosta. Jos kyseessä on pitkäkestoinen työ, joka ylittää Vercelin funktion aikakatkaisun, siirrä polling jonoon (Inngest, Trigger.dev, BullMQ) ja palauta generointitunniste selaimelle, jotta se voi pollata omaa status-endpointiasi.
Miten API ilmoittaa virheistä?
Muut kuin 2xx-vastaukset sisältävät JSON-rungon, jossa on `error`-objekti: `type`, `code`, `message` sekä pyyntötunniste tukea varten. Yleisiä tapauksia: 400 invalid_request_error, jossa `param` osoittaa virheelliseen kenttään; 402 insufficient_credits, jossa on `required`- ja `available`-määrät; 429 rate_limit_exceeded, jossa on `retry_after` sekunteina ja vastaava Retry-After-otsake. 5xx-virheitä voi turvallisesti yrittää uudelleen eksponentiaalisella peruutuksella.
Liittyvät sivut
Python
Virtuaalinen try-on API Pythonissa
Kutsu Phottan virtuaalinen try-on API -ominaisuutta Pythonissa requests-kirjaston avulla. Kolmenkymmenen rivin kääre, async-yhteensopiva httpx:n kautta, toimii Djangossa, FastAPIssa ja Celeryssä.
LuecURL
Virtuaalinen try-on API cURLillä
Kutsu Phottan virtuaalinen try-on API-rajapintaa suoraan komentoriviltä cURLin avulla. Lähetä, pollaa, lataa — jokainen koodinpätkä toimii yhdessä jq:n kanssa skriptatuissa putkissa.
LueOminaisuudet
Virtuaalinen try-on API vaatteille
REST API, joka asettaa vaatteet tekoälymallinukkejen päälle. Asynkroninen, 1.5–4 minuutin generointi, 5 credits resoluutiolla 2K, 6 resoluutiolla 4K. cURL-, Node.js- ja Python-esimerkit.
LueRakenna
Rakenna virtuaalinen try-on -ominaisuus sovellukseesi
Kattava toteutusmalli virtuaalisen try-on -ominaisuuden julkaisemiseen Photta APIlla: lataus, lähetys, polling workerista ja lopputuloksen renderöinti. TypeScript + vain palvelimella ajettavat mallit.
LueRakenna
Lisää virtuaalinen try-on iOS- tai Android-sovellukseen
Kuinka lisätä tekoälypohjainen virtuaalinen try-on natiiviin iOS- tai Android-sovellukseen Photta API:lla: älä koskaan toimita avainta laitteeseen, käytä proxyna taustajärjestelmääsi, peilaa työn tila.
LuePikaopas
Ensimmäinen Photta-kuva alle viidessä minuutissa.
Rekisteröidy, luo API-avain, suorita ensimmäinen cURL-kutsusi, tee pollingia valmistumiseen asti ja tallenna tulos. Viisi vaihetta, dokumentoitu alusta loppuun.
LueReferenssi
Photta API:n hinnoittelu
Mitä kukin Photta API -endpoint maksaa creditseinä resoluutioilla 2K ja 4K, miten veloitus ja palautukset toimivat ja mitkä endpointit ovat ilmaisia. Ei kuvakohtaista rahahintaa.
Lue
Jokainen luku tällä sivulla on peräisin Photta-rajapinnan dokumentaatiosta · tarkistettu
Kokeile APIa viidessä minuutissa
Luo Photta-API-avain, liitä yllä oleva cURL-koodinpätkä, ja sinulla on ensimmäinen mallikuva ennen kuin kahvi ehtii tippua.
- 1.5–4 min
- 5 credits resoluutiolla 2K · 6 credits resoluutiolla 4K
- asynkroninen, polling
- 600 pyyntöä/min
- Bearer-avain