Build · Shopify

Crie um app de try-on para Shopify

Em uma frase

Um app de try-on para Shopify lê a imagem do produto da Admin API, faz um POST para o Photta, monitora o job via polling em um worker em segundo plano e, em seguida, entrega a URL finalizada à Shopify via productCreateMedia.

  • Credits: 5 credits em 2K · 6 credits em 4K
  • Tempo típico: 1.5–4 min
  • Processamento: assíncrono, polling

Todos os números nesta página vêm de a documentação da API da Photta · verificado

Leia a foto do produto da Admin API, processe o try-on com o Photta e envie o resultado de volta como mídia do produto. Quatro chamadas, sem necessidade de manipular imagens por conta própria.

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

Como funciona

De uma página de produto a uma imagem de try-on

Defina os escopos do app, leia a foto, envie a requisição, faça polling fora do fluxo principal e anexe a mídia.

  1. Passo 1

    Defina os escopos do app

    Um app de try-on precisa ler produtos e gravar mídias. Solicite apenas os escopos de produto que seu app realmente utiliza — os lojistas prestam atenção na tela de consentimento.

  2. Passo 2

    Obtenha uma chave de API do Photta

    Uma chave por ambiente, mantida nas configurações do servidor do seu app. Ela nunca deve trafegar para a storefront nem para o navegador do lojista.

  3. Passo 3

    Leia a imagem do produto

    Consulte o produto para obter sua primeira imagem. Essa URL é pública, exatamente o que o endpoint do Photta espera — sem novo upload, sem URLs assinadas para gerenciar.

  4. Passo 4

    Envie a requisição de try-on

    Envie a imagem via POST especificando um manequim e uma pose. A resposta é imediata e retorna o ID da geração; nada foi renderizado ainda.

  5. Passo 5

    Faça polling em um job de segundo plano

    A Shopify espera que um webhook handler responda em segundos, e uma geração leva mais tempo do que isso. Confirme o recebimento (ACK), enfileire a tarefa e faça polling a cada 3 segundos a partir do worker.

  6. Passo 6

    Anexe a mídia

    Entregue a URL finalizada à Shopify e ela mesma baixa o arquivo. Persista a imagem no seu lado também, garantindo que a galeria permaneça acessível de forma independente.

As quatro chamadas, de ponta a ponta

A requisição e o polling do Photta são gerados a partir da documentação da API; as chamadas da Shopify são da própria 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" }],
  },
});

Dúvidas frequentes de desenvolvedores

Perguntas frequentes de desenvolvedores Shopify

Onde a chave do Photta deve ficar em um app da Shopify?

Nas variáveis de ambiente do servidor da sua aplicação, nunca no tema, em um app block ou na resposta de um app proxy. Qualquer informação acessível pela storefront pode ser lida por um cliente.

Quais escopos da Shopify são necessários?

Leitura da imagem do produto e gravação de mídias de produto. O Photta não precisa de nenhum acesso à Shopify — seu app é o único intermediário entre os dois lados.

Como mantenho o webhook rápido?

Responda imediatamente confirmando o recebimento, enfileire a tarefa e faça polling a partir do worker. A geração leva mais tempo do que o tempo limite aceitável de um webhook handler, logo, nenhuma operação que aguarde o resultado deve rodar dentro dele.

Posso cobrar os lojistas por imagem?

Essa é uma decisão do seu modelo de preços. O Photta debita da sua conta em credits por chamada, de modo que o custo por imagem é previsível antes da renderização; a margem cobrada a mais fica a seu critério.

E se um produto não tiver foto?

Ignore-o em vez de enviar uma imagem de placeholder. O endpoint precisa da foto real de uma peça de roupa, e usar um placeholder consumirá credits em uma imagem que ninguém vai publicar.

Entregue o app, não a infraestrutura básica

As chamadas ao Photta nesta página vêm diretamente da documentação da API. Obtenha uma chave e a primeira renderização estará pronta em poucos minutos.