Node.js · Virtual Try-On API

Virtual Try-On API Node.js-ympäristössä

Virallista @photta/node-pakettia ei vielä ole — etkä tarvitse sellaista. Node 18+ sisältää natiivin `fetch`-tuen, ja 20 rivin apufunktio vie sinut ensimmäiseen mallikuvaan noin viidessä minuutissa.

Yhdellä lauseella

Aseta `PHOTTA_API_KEY` ympäristömuuttujiin, kirjoita pieni `phottaFetch()`-apufunktio osoitteeseen `https://ai.photta.app/api/v1` otsakkeella `Authorization: Bearer photta_live_xxx`, lähetä POST osoitteeseen `/tryon/apparel` ja pollata `/tryon/apparel/:id` 3 sekunnin välein kunnes `status === 'completed'` — yleensä 1.5–4 minuutissa.

Päivitetty · 2026-04-19

Ensimmäinen pyyntösi

Node.jsPythoncURLcURL
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);

Mitä odottaa

Typical completion

1.5–4min

2K / 4K credits

5 / 7

Jewelry types

4

Close-up mannequins

built-in

Miten se toimii

Virtual Try-On API Node.js-ympäristössä

Viisi vaihetta, noin viisi minuuttia rekisteröitymisestä ensimmäiseen kuvaan.

  1. 01

    Vaihe 1

    Rekisteröidy ja generoi avain

    Luo tili osoitteessa ai.photta.app. Avaa Developers-osio, klikkaa Generate API key ja ota live-avain talteen. Se alkaa `photta_live_` -tunnisteella.

  2. 02

    Vaihe 2

    Tallenna avain ympäristömuuttujiin, älä koodiin

    Lisää `PHOTTA_API_KEY=...` `.env`-tiedostoon ja lataa se `process.env`-kautta. Älä koskaan tallenna avainta versionhallintaan tai käytä sitä `'use client'` -tiedostossa — se vuotaa selaimeen.

  3. 03

    Vaihe 3

    Kirjoita pieni fetch-apufunktio

    Yksi 20 rivin kääre `fetch()`-kutsun ympärillä hoitaa perus-URL:n, Authorization-otsakkeen, JSON-rungon ja virheiden käsittelyn. Tämä on ainoa abstraktio, jonka tarvitset ennen virallista SDK:ta.

  4. 04

    Vaihe 4

    Lähetä sovitus ja pollata

    POST osoitteeseen `/tryon/apparel` tiedoilla `product_type`, `product_images`, `mannequin_id`, `pose_id`, `resolution` ja `aspect_ratio`. API palauttaa tunnuksen välittömästi. Pollata `/tryon/apparel/:id` 3 sekunnin välein.

  5. 05

    Vaihe 5

    Tallenna lopputulos

    Vastaus sisältää `output_url` ja `thumbnail_url`. Hae tavut kerran ja tallenna omaan objektitallennustilaasi — osoitteet ovat vakaita, mutta tuotteesi ei pitäisi riippua Phottan CDN:stä renderöinnissä.

Koodi alusta loppuun

Copy, paste, done.

Four snippets — install prerequisites, wrap the REST call, submit + poll, then handle the errors that actually happen in production.

01No SDK required — use native fetch in Node 18+
bash
# 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
02Wrap the REST call in a tiny client helper
javascript
// 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;
}
03Submit a try-on job and poll until it lands
javascript
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);
04Handle 402 credit exhaustion and 429 rate limits
javascript
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;
}

Miksi tämä muoto

Miksi apufunktio voittaa kirjaston — toistaiseksi

  • 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

Mitä se ei tee

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

Muiden kehittäjien kysymyksiä

Questions other developers ask

Onko olemassa virallista Photta Node.js SDK:ta?+

Ei vielä. Tie-kartassa SDK:t tulevat käyttöasteen mukaan: Python 10 asiakkaan jälkeen, Node.js 20:n. Siihen asti suositeltu tapa on natiivi REST, ja tämän sivun 20 rivin funktio vastaa täysin virallista asiakasohjelmaa.

Mitä Node.js-versioita tuetaan?+

Kaikkia, jotka tukevat natiivia `fetch`-funktiota — eli Node 18 ja uudemmat. Node 16:ssa voit käyttää `node-fetch`-polyfillausta. Muu koodi on puhdasta ECMAScript 2020 -standardia (async/await, template literals).

Miten tunnistaudun Node-ympäristöstä?+

Lähetä `Authorization: Bearer photta_live_xxx` jokaisessa pyynnössä. Käytä ympäristömuuttujia `process.env.PHOTTA_API_KEY`. API ei tue vielä OAuth-asiakastunnuksia tai istuntopohjaista tunnistautumista.

Miten käsittelen 1.5–4 minuutin generointiajan?+

Sovitustehtävä on täysin asynkroninen. POST palauttaa tunnuksen ja tilan `processing`. Pollata `GET /tryon/apparel/:id` 3–5 sekunnin välein. Aseta yläraja yrityksille (esim. 120 kertaa), jotta palvelimesi ei jää jumiin ikuisesti.

Voinko kutsua API:a Next.js-sovelluksessa?+

Kyllä — reitinkäsittelijöistä (`app/**/route.ts`), server actioneista tai middlewaresta. Pidä avain palvelimella; älä koskaan tuo apufunktiota `'use client'` -tiedostoon. Jos työ kestää yli Vercel-funktioiden aikarajan, siirrä pollaus jonoon (Inngest, Trigger.dev, BullMQ).

Miten API ilmoittaa virheistä?+

Muut kuin 2xx-vastaukset sisältävät JSON-rungon, jossa on `error`-objekti: `type`, `code`, `message` ja pyyntötunnus. Yleiset: 400 virheellinen pyyntö, 402 liian vähän krediittejä, 429 nopeusrajoitus (sisältää `retry_after`-tiedon). 5xx-virheet voi yrittää uudelleen.

Node.js · Virtual Try-On API

Luo tili ja hanki API-avain

Aseta `PHOTTA_API_KEY` ympäristömuuttujiin, kirjoita pieni `phottaFetch()`-apufunktio osoitteeseen `https://ai.photta.app/api/v1` otsakkeella `Authorization: Bearer photta_live_xxx`, lähetä POST osoitteeseen `/tryon/apparel` ja pollata `/tryon/apparel/:id` 3 sekunnin välein kunnes `status === 'completed'` — yleensä 1.5–4 minuutissa.

Virtual Try-On API Node.js:lle — Photta | Photta