Integración · Shopify

Crea una app de try-on para Shopify

En una frase

Una app de try-on para Shopify lee la imagen del producto desde la Admin API, hace un POST a Photta, consulta el estado del job en un worker en segundo plano y luego entrega a Shopify la URL final mediante productCreateMedia.

  • 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

Lee la foto del producto desde la Admin API, procesa el try-on con Photta y devuelve el resultado como media del producto. Cuatro llamadas, sin gestionar imágenes por tu cuenta.

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 una página de producto a una imagen de try-on

Define los scopes de la app, lee la foto, envía la petición, haz polling fuera del ciclo de la request y adjunta el contenido multimedia.

  1. Paso 1

    Define los scopes de la app

    Una app de try-on necesita leer productos y escribir media. Solicita únicamente los scopes de producto que tu app realmente utilice — los comerciantes revisan la pantalla de consentimiento.

  2. Paso 2

    Obtén una API key de Photta

    Una clave por entorno, guardada en la configuración del servidor de tu app. Nunca viaja al storefront ni al navegador del comerciante.

  3. Paso 3

    Lee la imagen del producto

    Consulta el producto para obtener su primera imagen. Esa URL es pública, que es exactamente lo que espera el endpoint de Photta — sin resubidas ni URLs firmadas que gestionar.

  4. Paso 4

    Envía la solicitud de try-on

    Haz un POST de la imagen junto con un maniquí y una pose. La respuesta es inmediata e incluye el id de la generación; aún no se ha renderizado nada.

  5. Paso 5

    Haz polling en un job en segundo plano

    Shopify espera que un webhook handler responda en segundos, y una generación tarda más tiempo. Responde con un acuse de recibo, encola el proceso y haz polling cada 3 segundos desde el worker.

  6. Paso 6

    Adjunta el contenido multimedia

    Entrega la URL final a Shopify y esta descargará el archivo por sí misma. Guarda también la imagen en tu servidor para que la galería se conserve de forma independiente.

Las cuatro llamadas, de extremo a extremo

La petición y el polling de Photta se basan en la documentación de la API; las llamadas a Shopify son las nativas de su Admin API.

// Shopify Admin GraphQL — the product's first image is your source photo
const query = `query($id: ID!) {
  product(id: $id) { title images(first: 1) { nodes { url } } }
}`;

const res = await admin.graphql(query, { variables: { id: productGid } });
const { data } = await res.json();
const productImage = data.product.images.nodes[0].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");
}
// Shopify downloads the URL itself, so hand it the Photta output_url
const mutation = `mutation($id: ID!, $media: [CreateMediaInput!]!) {
  productCreateMedia(productId: $id, media: $media) {
    mediaUserErrors { field message }
  }
}`;

await admin.graphql(mutation, {
  variables: {
    id: productGid,
    media: [{ originalSource: outputUrl, mediaContentType: "IMAGE", alt: "Virtual try-on" }],
  },
});

Preguntas frecuentes de desarrolladores

Preguntas frecuentes de desarrolladores de Shopify

¿Dónde debe residir la clave de Photta en una app de Shopify?

En las variables de entorno de tu servidor de aplicaciones, nunca en el theme, en un app block ni en la respuesta de un app proxy. Todo lo que el storefront pueda leer, un comprador también puede leerlo.

¿Qué scopes de Shopify son necesarios?

Lectura de imágenes de producto y escritura de media del producto. Photta no necesita acceso a Shopify en absoluto — tu app es la única pieza que se comunica con ambos extremos.

¿Cómo mantengo la rapidez del webhook?

Devuelve un acuse de recibo de inmediato, encola la tarea y haz polling desde el worker. Una generación tarda más tiempo de lo que debería durar un webhook handler, por lo que nada que deba esperar a que termine debe residir en dicho handler.

¿Puedo cobrar a los comerciantes por imagen?

Esa es una decisión de precios tuya. Photta descuenta credits de tu cuenta por cada llamada, por lo que el coste por imagen se conoce antes de renderizar; el margen que añadas depende de ti.

¿Qué ocurre si un producto no tiene foto?

Ignóralo en lugar de enviar un placeholder. El endpoint requiere una fotografía real de la prenda, y usar un placeholder consumiría credits en una imagen que nadie va a publicar.

Lanza la app, no la infraestructura subyacente

Las llamadas a Photta de esta página proceden directamente de la documentación de la API. Obtén una clave y tendrás el primer render listo en cuestión de minutos.