Build · Virtual Try-On

Crea una función de virtual try-on para tu aplicación

En una frase

Recibe la foto del producto en tu backend, envíala mediante POST a /api/v1/tryon/apparel con un ID de maniquí, haz polling del ID de generación devuelto desde un background worker (nunca en el hilo de la solicitud HTTP) hasta que status cambie a completed, luego persiste output_url en tu propio almacenamiento de objetos y renderízala en la interfaz de usuario.

  • Credits: 5 credits a 2K · 6 credits a 4K
  • Tiempo típico: 1.5–4 min
  • Procesamiento: asíncrono, polling

Cada cifra de esta página proviene de la documentación de la API de Photta · verificado

Una receta lista para producción: el cliente sube una foto del producto, tu backend encola un trabajo de try-on en Photta, un worker hace polling hasta que finalice y el frontend muestra el resultado sobre el modelo. Sin solicitudes bloqueantes, sin claves de API filtradas, sin SDKs falsos.

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

Cómo funciona

De la subida a la imagen con modelo

Seis pasos concretos. Prevé entre diez y quince minutos de trabajo de integración la primera vez.

  1. Paso 1

    Esboza el flujo de datos

    Dispositivo del cliente → tu backend (subida) → Photta API (envío) → Photta API (polling) → tu base de datos (espejo de estado) → dispositivo del cliente (renderizado). Dibuja esto en papel antes de escribir la primera línea: el límite entre tu backend y el de Photta es lo único que importa.

  2. Paso 2

    Genera y almacena una clave de API

    Las claves de producción comienzan con photta_live_. Guárdala en una variable de entorno. Nunca la envíes al navegador. Una sola clave cubre todas las capacidades de Photta, por lo que no necesitas claves separadas para try-on, joyería o maniquí invisible.

  3. Paso 3

    Configura el endpoint de subida

    Recibe primero la foto del producto del cliente en tu almacenamiento de objetos. Proporcionar a Photta una URL pública es más sencillo que usar base64 y te deja un registro de auditoría de cada solicitud.

  4. Paso 4

    Envía el trabajo desde el servidor

    Haz POST a /api/v1/tryon/apparel con la URL del producto, mannequin_id, resolution y aspect_ratio. La API devuelve 202 Accepted + un ID de generación. Guarda el ID en tu base de datos para que tu cliente consulte tu propio endpoint, no el de Photta.

  5. Paso 5

    Haz polling desde un background worker

    No hagas polling dentro de la solicitud HTTP: el trabajo tarda de 1.5 a 4 minutos, lo que excede la mayoría de los tiempos de espera de entornos serverless. Usa Trigger.dev, Inngest, BullMQ, Vercel Cron o tu propia cola para reprogramar un sondeo cada 3 segundos hasta que el trabajo termine.

  6. Paso 6

    Renderiza el resultado

    Cuando status cambie a completed, copia data.output_url en tu base de datos y emite un evento en tiempo real (websocket, SSE o long-poll) hacia el dispositivo del cliente. La interfaz reemplaza el esqueleto de carga por la imagen. Listo.

Tres ejemplos de código, de extremo a extremo

Manejador de subidas, despachador de trabajos y worker para polling: cada pieza que necesitas para lanzar la función.

// 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 });
  },
});

Preguntas frecuentes de desarrolladores

Preguntas antes de pasar a producción

¿Puedo hacer esto sin un backend?

No. Tu API key de Photta debe permanecer en el servidor. Incluso un route handler ligero de Next.js o un Cloudflare Worker cuenta como backend para este propósito; la clave solo necesita estar en un lugar donde un user-agent no pueda leerla.

¿Cómo evito solicitudes HTTP colgadas?

Nunca hagas polling dentro de un request handler. Envía el job de forma síncrona, devuelve el ID de generación al cliente y haz polling desde un background worker. El cliente hace polling a TU endpoint de estado, no al de Photta; de este modo, los rate limits son tu problema a gestionar, no el de cada usuario.

¿Qué sucede si un job falla en plena ejecución?

Photta reembolsa los credits automáticamente en caso de fallo, y la respuesta incluye data.error_code + data.error_message. Muestra un mensaje amigable al usuario y ofrece un botón de reintento que inicie un nuevo job.

¿Puedo mostrar un progreso real?

Photta no emite progreso intermedio: el estado es processing, completed o failed. Lo que funciona bien es una barra de progreso temporizada y calibrada para una ventana de 1.5–4 minutos, o un skeleton loader simple. No mientas con los porcentajes.

¿La URL del resultado es permanente?

La URL de la CDN es estable, pero tu producto no debería depender de ella para el renderizado a largo plazo. Descarga los bytes una vez y guárdalos en tu propio bucket de S3/GCS/R2; así tu PDP seguirá funcionando incluso si la CDN de Photta cambia.

Implementa virtual try-on en una tarde

Cada ejemplo de código en esta página coincide con la documentación oficial de Photta. Obtén una API key y tendrás un prototipo funcional antes de que el café termine de prepararse.