Node.js · API de Try-On Virtual

API de Try-On Virtual en Node.js

Aún no hay un paquete @photta/node — y no lo necesitas. Node 18+ incluye `fetch` de forma nativa, y un helper de 20 líneas te permite obtener tu primera imagen con modelo en unos cinco minutos.

En una frase

Configura `PHOTTA_API_KEY` en el entorno, escribe un pequeño helper `phottaFetch()` que llame a `https://ai.photta.app/api/v1` con `Authorization: Bearer photta_live_xxx`, haz un POST a `/tryon/apparel` con la URL de una imagen de producto, un mannequin ID y un pose ID, luego sondea `/tryon/apparel/:id` cada 3 segundos hasta que `status === 'completed'` — típicamente en 1.5–4 minutos.

Actualizado · 2026-04-19

Tu primera solicitud

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);

Qué esperar

Typical completion

1–3min

2K / 4K credits

4 / 6

Styles

2

Batch-ready

yes

Cómo funciona

API de Try-On Virtual en Node.js

Cinco pasos, unos cinco minutos desde el registro hasta la primera imagen.

  1. 01

    Paso 1

    Regístrate y genera una clave

    Crea una cuenta en ai.photta.app. Abre la sección de Desarrolladores del dashboard, haz clic en Generar API key y copia la clave activa. Comienza con `photta_live_` seguido de 32 caracteres hexadecimales.

  2. 02

    Paso 2

    Guarda la clave en env, no en el código

    Añade `PHOTTA_API_KEY=...` a `.env` (o al gestor de secretos de tu plataforma) y cárgala mediante `process.env`. Nunca subas la clave al repositorio; nunca la importes en un archivo marcado como `'use client'` — el bundler la llevará al navegador.

  3. 03

    Paso 3

    Escribe un pequeño helper de fetch

    Un envoltorio de 20 líneas alrededor de `fetch()` gestiona la URL base, el header Authorization, el cuerpo JSON y la normalización de errores. Esta es la única abstracción que necesitas hasta que se lance un SDK oficial.

  4. 04

    Paso 4

    Envía un try-on y sondea

    POST a `/tryon/apparel` con `product_type`, `product_images`, `mannequin_id`, `pose_id`, `resolution` y `aspect_ratio`. La API devuelve un ID de generación de inmediato. Sondea `/tryon/apparel/:id` cada 3 segundos hasta que `status === 'completed'`.

  5. 05

    Paso 5

    Persistir el resultado

    El payload completado incluye `output_url` y `thumbnail_url`. Obtén los bytes una vez y almacénalos en tu propio almacenamiento de objetos — las URLs son estables pero tu producto no debería depender del CDN de Photta para el renderizado.

Código, de punta a punta

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;
}

Por qué esta estructura

Por qué un helper es mejor que una librería cliente — por ahora

  • 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

Qué no hace

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

Preguntas de otros desarrolladores

Questions other developers ask

¿Existe un SDK oficial de Photta para Node.js?+

Aún no. La documentación de Photta planea explícitamente los SDKs tras alcanzar ciertos umbrales de adopción: Python cuando haya diez usuarios de la API, Node.js al llegar a veinte. Hasta entonces, la ruta documentada es REST directo vía cURL, fetch nativo de Node o la librería requests de Python. El helper de 20 líneas en esta página equivale a un cliente para los endpoints que más usarás.

¿Qué versiones de Node.js están soportadas?+

Cualquiera que soporte `fetch` nativo — lo que significa Node 18 y versiones posteriores. En Node 16 puedes usar un polyfill con `node-fetch` o actualizar. El resto del código es ECMAScript 2020 estándar (async/await, template literals, dynamic imports), por lo que no hay otros requisitos de runtime.

¿Cómo me autentico desde Node?+

Envía `Authorization: Bearer photta_live_xxx` en cada solicitud. La clave comienza con `photta_live_` en producción y `photta_test_` cuando se lance el modo sandbox. Ponla en una variable de entorno y cárgala mediante `process.env.PHOTTA_API_KEY`. La API aún no soporta credenciales de cliente OAuth o autenticación basada en sesiones.

¿Cómo manejo la ventana de generación de 1.5–4 minutos?+

El endpoint de try-on es totalmente asíncrono. POST devuelve un ID de generación de inmediato con `status: 'processing'`. Sondea `GET /tryon/apparel/:id` cada 3–5 segundos hasta que `status` cambie a `completed` o `failed`. Establece un límite superior de intentos para que un trabajo atascado no bloquee tu solicitud para siempre — 120 intentos cada 3 segundos cubren la ventana documentada con margen.

¿Puedo llamar a la API dentro de Next.js?+

Sí — desde un route handler (`app/**/route.ts`), una server action (`'use server'`) o un middleware. Mantén la API key en el servidor; nunca importes el helper desde un archivo `'use client'`. Para trabajos de larga duración que superen el tiempo de espera de las funciones de Vercel, delega el polling a una cola (Inngest, Trigger.dev, BullMQ) y devuelve el ID de generación al navegador para que pueda sondear un webhook o tu propio endpoint de estado.

¿Cómo señala los errores la API?+

Las respuestas que no son 2xx llevan un cuerpo JSON con un objeto `error`: `type`, `code`, `message` y un ID de solicitud para soporte. Casos comunes: 400 invalid_request_error con `param` apuntando al campo incorrecto; 402 insufficient_credits con los conteos `required` y `available`; 429 rate_limit_exceeded con `retry_after` en segundos y un header Retry-After correspondiente. Los errores 5xx son seguros para reintentar con backoff exponencial.

Node.js · API de Try-On Virtual

Crea una cuenta y obtén una API key

Configura `PHOTTA_API_KEY` en el entorno, escribe un pequeño helper `phottaFetch()` que llame a `https://ai.photta.app/api/v1` con `Authorization: Bearer photta_live_xxx`, haz un POST a `/tryon/apparel` con la URL de una imagen de producto, un mannequin ID y un pose ID, luego sondea `/tryon/apparel/:id` cada 3 segundos hasta que `status === 'completed'` — típicamente en 1.5–4 minutos.

API de Try-On Virtual para Node.js — Photta | Photta