Node.js · API de try-on de joias
API de try-on de joias em Node.js
Em uma frase
Defina PHOTTA_API_KEY no ambiente, escreva um helper simples com fetch para https://api.photta.app/api/v1 com uma chave Bearer, faça POST para /api/v1/tryon/jewelry e depois faça polling em /api/v1/tryon/jewelry/{id} a cada 3 segundos até que o status seja completed.
- Tempo típico: 1.5–4 min
- Credits: 5 credits em 2K · 6 credits em 4K
- Processamento: assíncrono, polling
- Limites: 600 requisições/min
- Autenticação: Chave Bearer
Todos os números nesta página vêm de a documentação da API da Photta · verificado
RESPONSE=$(curl -s -X POST https://api.photta.app/api/v1/tryon/jewelry \
-H "Authorization: Bearer $PHOTTA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"jewelry_image": "https://cdn.yourstore.com/products/gold-necklace.jpg",
"jewelry_type": "necklace",
"mannequin_id": "mnk_j9k1l2",
"background": "soft window light on dark velvet",
"resolution": "2K",
"aspect_ratio": "3:4",
"user_instruction": "Make the pendant 10% smaller."
}')
ID=$(echo "$RESPONSE" | jq -r '.data.id')
# $ID is data.id from the POST response. Poll every 3 seconds until status is "completed" or "failed".
for i in $(seq 1 120); do
RESULT=$(curl -s "https://api.photta.app/api/v1/tryon/jewelry/$ID" -H "Authorization: Bearer $PHOTTA_API_KEY")
STATUS=$(echo "$RESULT" | jq -r '.data.status')
[ "$STATUS" = "completed" ] && break
[ "$STATUS" = "failed" ] && echo "generation failed" && exit 1
sleep 3
done
echo "$RESULT" | jq -r '.data.output_url'const res = await fetch("https://api.photta.app/api/v1/tryon/jewelry", {
method: "POST",
headers: { Authorization: `Bearer ${process.env.PHOTTA_API_KEY}`, "Content-Type": "application/json" },
body: JSON.stringify({
"jewelry_image": "https://cdn.yourstore.com/products/gold-necklace.jpg",
"jewelry_type": "necklace",
"mannequin_id": "mnk_j9k1l2",
"background": "soft window light on dark velvet",
"resolution": "2K",
"aspect_ratio": "3:4",
"user_instruction": "Make the pendant 10% smaller."
}),
});
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/jewelry/${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");
}import os, requests
res = requests.post(
"https://api.photta.app/api/v1/tryon/jewelry",
headers={"Authorization": f"Bearer {os.environ['PHOTTA_API_KEY']}"},
json={
"jewelry_image": "https://cdn.yourstore.com/products/gold-necklace.jpg",
"jewelry_type": "necklace",
"mannequin_id": "mnk_j9k1l2",
"background": "soft window light on dark velvet",
"resolution": "2K",
"aspect_ratio": "3:4",
"user_instruction": "Make the pendant 10% smaller."
},
)
data = res.json()["data"] # data["id"], data["status"]
import time
def wait_for(job_id):
for _ in range(120):
res = requests.get(f"https://api.photta.app/api/v1/tryon/jewelry/{job_id}", headers={"Authorization": f"Bearer {os.environ['PHOTTA_API_KEY']}"})
data = res.json()["data"]
if data["status"] == "completed":
return data["output_url"]
if data["status"] == "failed":
raise RuntimeError(data.get("error_message", "generation failed"))
time.sleep(3)
raise TimeoutError("timed out after 6 minutes")Visão geral
Visão geral
- Endpoint
- POST /api/v1/tryon/jewelry
- Autenticação
- API key Bearer
- Processamento
- Assíncrono — faça polling no endpoint de status
- Tempo típico
- 1.5–4 min
- Credits
- 5 credits em 2K · 6 credits em 4K
- Proporções de tela
- 3:4 · 1:1 · 4:3 · 9:16 · 16:9
- Limites de entrada
- Até 10 MB por imagem; JPEG, PNG, WebP
- Idempotente
- Não
Como funciona
Cinco etapas, cerca de cinco minutos do cadastro à primeira imagem.
Passo 1
Cadastre-se e gere uma chave
Crie uma conta em ai.photta.app. Abra a seção Desenvolvedores do painel, clique em Generate API key e copie a chave de produção. Ela começa com `photta_live_` seguido por 32 caracteres hexadecimais.
Passo 2
Armazene a chave no ambiente, não no código-fonte
Adicione `PHOTTA_API_KEY=...` ao `.env` (ou ao gerenciador de segredos da sua plataforma) e carregue-a via `process.env`. Nunca comite a chave; nunca a importe em um arquivo marcado com `'use client'` — o empacotador irá incluí-la no navegador.
node --version # 18 or later ships fetch echo "PHOTTA_API_KEY=photta_live_xxxxx" >> .envPasso 3
Escreva um helper de fetch enxuto
Um wrapper de 20 linhas em torno de `fetch()` lida com a URL base, o header Authorization, o body JSON e a normalização de erros. Esta é a única abstração de que você precisa até o lançamento de um SDK oficial.
// photta.js — one helper for every endpoint const BASE = "https://api.photta.app/api/v1"; export async function photta(path, init = {}) { const res = await fetch(BASE + path, { ...init, headers: { Authorization: `Bearer ${process.env.PHOTTA_API_KEY}`, "Content-Type": "application/json", ...(init.headers ?? {}) } }); const body = await res.json(); if (!res.ok) throw Object.assign(new Error(body.error?.message ?? res.statusText), { status: res.status, retryAfter: res.headers.get("Retry-After"), body }); return body; }Passo 4
Envie um try-on e faça polling
Envie um POST para `/api/v1/tryon/jewelry` com o body de exemplo documentado — o código abaixo inclui todos os campos. A API retorna um generation ID imediatamente. Faça polling em `/api/v1/tryon/jewelry/{id}` a cada 3 segundos até que `status === 'completed'`.
const res = await fetch("https://api.photta.app/api/v1/tryon/jewelry", { method: "POST", headers: { Authorization: `Bearer ${process.env.PHOTTA_API_KEY}`, "Content-Type": "application/json" }, body: JSON.stringify({ "jewelry_image": "https://cdn.yourstore.com/products/gold-necklace.jpg", "jewelry_type": "necklace", "mannequin_id": "mnk_j9k1l2", "background": "soft window light on dark velvet", "resolution": "2K", "aspect_ratio": "3:4", "user_instruction": "Make the pendant 10% smaller." }), }); 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/jewelry/${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"); }Passo 5
Persista o resultado
O payload concluído inclui `output_url` e `thumbnail_url`. Faça o fetch dos bytes uma vez e armazene-os no seu próprio object storage — as URLs são estáveis, mas o seu produto não deve depender da CDN do Photta para renderização.
Erros
- 400
invalid_request_error - The request is malformed or contains invalid parameters.
- 401
authentication_error - The API key is missing, invalid, or expired.
- 402
insufficient_credits_error - Your account does not have enough credits.
- 404
not_found_error - The requested resource does not exist.
- 409
conflict_error - The request conflicts with current state — e.g. your concurrent-batch cap is reached.
- 429
rate_limit_error - Too many requests. Slow down and retry.Retry-After: 30
- 500
api_error - An internal server error occurred. Retry later.
try {
await photta("/tryon/jewelry", { method: "POST", body: JSON.stringify({
"jewelry_image": "https://cdn.yourstore.com/products/gold-necklace.jpg",
"jewelry_type": "necklace",
"mannequin_id": "mnk_j9k1l2",
"background": "soft window light on dark velvet",
"resolution": "2K",
"aspect_ratio": "3:4",
"user_instruction": "Make the pendant 10% smaller."
}) });
} catch (err) {
if (err.status === 402) console.error("insufficient_credits_error: top up before retrying");
else if (err.status === 429) await new Promise((r) => setTimeout(r, Number(err.retryAfter ?? 30) * 1000));
else throw err;
}Limites
- 600 requisições por minuto por API key (Janela fixa; o limite é o mesmo em todos os planos)
- Um 429 retorna Retry-After: 30 segundos
- Até 10 MB por imagem
- Formatos: JPEG, PNG, WebP
- Batches concorrentes por plano: Free 1 · Hobby 2 · Seller 3 · Brand 4 · Studio 6
- Apenas polling — a API não envia webhooks.
Por que um helper é melhor que uma biblioteca cliente — por enquanto
- O Node 18+ traz fetch nativo — sem dependências em tempo de execução
- O mesmo helper funciona em route handlers do Next.js, server actions e em qualquer worker
- Mantenha a chave de API em variáveis de ambiente; nunca importe o helper a partir de um módulo 'use client', caso contrário o bundler irá expô-la
- Funciona com qualquer fila ou cron: BullMQ, Inngest, Trigger.dev, Vercel Cron, Cloudflare Queues
O que ela não faz
- Ainda não há um pacote oficial @photta/node — REST é o único caminho atualmente
- Polling é o único sinal de conclusão; a API não envia webhooks
- Apenas chave Bearer; não há fluxo OAuth client-credentials
Dúvidas frequentes de desenvolvedores
Existe um SDK oficial do Photta para Node.js?
Ainda não. O caminho documentado é REST puro via fetch nativo do Node — o helper nesta página cobre toda a superfície de integração e funciona da mesma forma para todas as capabilities.
Quais versões do Node.js são suportadas?
Qualquer uma que suporte `fetch` nativo — ou seja, Node 18 e versões posteriores. No Node 16, você usa um polyfill com `node-fetch` ou atualiza o runtime. O restante do código é ECMAScript 2020 puro (async/await, template literals, dynamic imports), portanto não há outros requisitos de runtime.
Como faço a autenticação no Node?
Envie `Authorization: Bearer photta_live_xxx` em todas as requisições. Defina a chave em uma variável de ambiente e carregue-a via `process.env`; nunca a importe em um arquivo executado no navegador.
Como gerencio a janela de geração?
O endpoint de geração é totalmente assíncrono. O POST retorna um generation ID imediatamente com `status: 'processing'`. Faça polling com `GET /api/v1/tryon/jewelry/{id}` a cada 3–5 segundos até que o `status` mude para `completed` ou `failed`, e limite o número de tentativas para que um job travado não prenda a requisição.
Posso chamar a API dentro do Next.js?
Sim — a partir de um route handler (`app/**/route.ts`), uma server action (`'use server'`) ou middleware. Mantenha a chave de API no servidor; nunca importe o helper de um arquivo `'use client'`. Para jobs longos que excedam o timeout de função da Vercel, delegue o polling para uma fila (Inngest, Trigger.dev, BullMQ) e retorne o generation ID para o navegador fazer polling no seu próprio status endpoint.
Como a API sinaliza erros?
Respostas não-2xx contêm um body JSON com um objeto `error`: `type`, `code`, `message` e um ID de requisição para suporte. Casos comuns: 400 invalid_request_error com `param` apontando para o campo inválido; 402 insufficient_credits com contagens de `required` e `available`; 429 rate_limit_exceeded com `retry_after` em segundos e o header Retry-After correspondente. Erros 5xx podem ser repetidos com segurança usando backoff exponencial.
Páginas relacionadas
Python
API de try-on de joias em Python
Chame aPI de try-on de joias do Photta em Python com a biblioteca requests. Wrapper de trinta linhas, compatível com async via httpx, funciona em Django, FastAPI e Celery.
LercURL
API de try-on de joias com cURL
Chame a aPI de try-on de joias da Photta diretamente do shell com cURL. Envie, faça polling, baixe — todos os snippets funcionam com o jq para pipelines em script.
LerRecursos
API de try-on de joias para colares, anéis, pulseiras e brincos
Insira colares, anéis, pulseiras e brincos em modelos de IA via REST. 5 credits em 2K, manequins em close-up integrados, renderização sensível a reflexos direto da documentação da Photta.
LerConstruir
Crie um serviço de fotografia de produtos com IA
O playbook de um fundador para revender a API de virtual try-on da Photta como um SaaS white-label: chaves por tenant, fanout em lote, faturamento por credit, realidade de SLA.
LerInício rápido
Primeira imagem no Photta em menos de cinco minutos.
Cadastre-se, gere uma chave de API, execute sua primeira chamada cURL, faça polling até a conclusão, persista o resultado. Cinco etapas, documentadas de ponta a ponta.
LerReferência
Preços da API Photta
Quanto custa em credits cada endpoint da Photta API em 2K e 4K, como funcionam as cobranças e reembolsos, e quais endpoints são gratuitos. Sem preço monetário por imagem.
Ler
Todos os números nesta página vêm de a documentação da API da Photta · verificado
Experimente a API em cinco minutos
Gere uma chave de API do Photta, cole o snippet de cURL acima e você terá sua primeira imagem com modelo antes que o café termine de passar.
- 1.5–4 min
- 5 credits em 2K · 6 credits em 4K
- assíncrono, polling
- 600 requisições/min
- Chave Bearer