Python · API de Provador Virtual

API de Provador Virtual em Python

Não é necessário pip install photta — a documentação da Photta recomenda oficialmente a biblioteca requests. Um wrapper de trinta linhas se integra a Django, FastAPI, workers do Celery e handlers do Lambda sem cerimônias.

Em uma frase

Instale `requests`, carregue `PHOTTA_API_KEY` do ambiente, escreva um wrapper `photta_request()` que envia `Authorization: Bearer photta_live_xxx` e lança um `PhottaError` tipado em respostas não-2xx, então envie um POST para `/tryon/apparel` e faça poll em `/tryon/apparel/:id` a cada 3 segundos até que `data.status == 'completed'` — tipicamente entre 1.5 e 4 minutos.

Atualizado · 2026-04-19

Sua primeira requisição

PythonNode.jscURLcURL
import time
from photta import photta_request, PhottaError

# 1. Submit the job
created = photta_request("POST", "/tryon/apparel", json={
    "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",
})
generation_id = created["data"]["id"]

# 2. Poll every 3 seconds. Upper bound: 120 attempts ≈ 6 minutes,
# comfortably above the documented 1.5–4 minute window.
for _ in range(120):
    result = photta_request("GET", f"/tryon/apparel/{generation_id}")
    status = result["data"]["status"]
    if status == "completed":
        print("Result:", result["data"]["output_url"])
        break
    if status == "failed":
        raise RuntimeError(result["data"]["error_message"])
    time.sleep(3)

O que esperar

Typical completion

1.5–4min

2K / 4K credits

5 / 7

Jewelry types

4

Close-up mannequins

built-in

Como funciona

API de Provador Virtual em Python

Cinco passos, zero dependências específicas da Photta — a biblioteca requests cuida de tudo.

  1. 01

    Passo 1

    Cadastre-se e gere uma chave

    Mesmo caminho de qualquer outra linguagem: ai.photta.app → Desenvolvedores → Gerar chave de API. Chaves começam com `photta_live_` e funcionam em todas as funcionalidades da Photta.

  2. 02

    Passo 2

    Carregue a chave do env

    Defina `PHOTTA_API_KEY` no ambiente e leia-a via `os.environ`. No FastAPI ou Django, carregue-a uma vez na inicialização em um módulo de configurações. Não embuta a chave no código-fonte ou no histórico público do Git.

  3. 03

    Passo 3

    Escreva um wrapper de requests

    Uma função `photta_request()` de trinta linhas gerencia a URL base, o header Authorization, a serialização JSON e a tradução de erros. Essa é a única abstração necessária até que o SDK Python seja lançado.

  4. 04

    Passo 4

    Enviar e poll

    Envie um POST para `/tryon/apparel` para obter um ID de geração, então faça poll em `/tryon/apparel/:id` em intervalos de 3 segundos. No Celery ou RQ, divida o loop de poll entre tarefas para que um job de 4 minutos não prenda um worker.

  5. 05

    Passo 5

    Persista o resultado

    O payload final inclui `output_url` e `thumbnail_url`. Baixe os bytes em seu próprio storage de objetos — S3, GCS, Cloudflare R2 — para que seu produto não fique preso ao CDN da Photta para renderização a longo prazo.

Código, ponta a ponta

Copy, paste, done.

Four snippets — install prerequisites, wrap the REST call, submit + poll, then handle the errors that actually happen in production.

01Use the battle-tested requests library
bash
# Photta doesn't ship an official Python SDK yet — requests is the
# recommended path in the docs. Standard library urllib works too if
# you need zero dependencies.
pip install requests

# Store your API key in env (dotenv optional but convenient)
echo "PHOTTA_API_KEY=photta_live_xxxxx" >> .env
02A 30-line client wrapper you can drop into any project
python
# photta.py
import os
import requests

PHOTTA_BASE_URL = "https://ai.photta.app/api/v1"

class PhottaError(Exception):
    def __init__(self, status: int, code: str, message: str, retry_after: int | None = None):
        super().__init__(message)
        self.status = status
        self.code = code
        self.retry_after = retry_after

def photta_request(method: str, path: str, **kwargs):
    headers = {
        "Authorization": f"Bearer {os.environ['PHOTTA_API_KEY']}",
        "Content-Type": "application/json",
        **kwargs.pop("headers", {}),
    }
    response = requests.request(method, f"{PHOTTA_BASE_URL}{path}", headers=headers, **kwargs)
    body = response.json()
    if not response.ok:
        err = body.get("error", {})
        raise PhottaError(
            status=response.status_code,
            code=err.get("code", "unknown"),
            message=err.get("message", response.reason),
            retry_after=err.get("retry_after"),
        )
    return body
03Submit a try-on and poll until the result is ready
python
import time
from photta import photta_request, PhottaError

# 1. Submit the job
created = photta_request("POST", "/tryon/apparel", json={
    "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",
})
generation_id = created["data"]["id"]

# 2. Poll every 3 seconds. Upper bound: 120 attempts ≈ 6 minutes,
# comfortably above the documented 1.5–4 minute window.
for _ in range(120):
    result = photta_request("GET", f"/tryon/apparel/{generation_id}")
    status = result["data"]["status"]
    if status == "completed":
        print("Result:", result["data"]["output_url"])
        break
    if status == "failed":
        raise RuntimeError(result["data"]["error_message"])
    time.sleep(3)
04Handle 402 credit exhaustion and 429 rate limits
python
from photta import photta_request, PhottaError
import time

try:
    photta_request("POST", "/tryon/apparel", json={ ... })
except PhottaError as err:
    if err.status == 402:
        # Out of credits — err.code == "insufficient_credits"
        raise
    elif err.status == 429:
        # Rate-limited. Honour the Retry-After header.
        time.sleep(err.retry_after or 30)
        # then retry…
    elif err.status >= 500:
        # Server-side — retry with exponential backoff.
        raise
    else:
        raise

Por que esse formato

Por que requests é a escolha certa hoje

  • Zero Photta-specific dependencies — `requests` is already in most Python projects
  • Works anywhere Python runs: Django, FastAPI, Flask, Celery workers, Lambda, scripts
  • The client wrapper is ~30 lines — paste it into `photta.py` and move on
  • Pairs naturally with asyncio via `httpx` if you need parallel submission

O que não faz

Honest caveats

  • No official @photta/python SDK yet — REST + requests is the documented pattern
  • No async fetch helper shipped; swap `requests` for `httpx` when you need concurrency
  • Bearer token auth only — no OAuth client credentials yet

Perguntas que outros desenvolvedores fazem

Questions other developers ask

Existe um SDK oficial da Photta para Python?+

Ainda não. O roadmap da Photta prioriza o SDK Python assim que houver dez clientes pagantes da API ativos. Até lá, o caminho de integração suportado é a biblioteca requests (síncrona) ou httpx (assíncrona) — ambas estão documentadas nos guias oficiais e funcionam com o wrapper de trinta linhas desta página.

Quais versões do Python são suportadas?+

Python 3.9 e posterior. O wrapper usa type hints, f-strings e a sintaxe `str | None`, que funciona no 3.10+. No 3.9, troque `str | None` por `Optional[str]`. A biblioteca requests suporta oficialmente 3.8+, mas 3.9+ é o mínimo prático para projetos modernos da Photta.

Devo usar requests ou httpx?+

Use requests se estiver fazendo algumas chamadas sequenciais — é mais simples e já está na maioria das bases de código. Use httpx se precisar de concorrência assíncrona (envios paralelos, backfills em massa) ou HTTP/2. O wrapper é minúsculo de qualquer forma; troque `requests.request` por `httpx.Client().request` e o resto do código permanece idêntico.

Posso chamar via Django?+

Sim. Coloque o wrapper em `services/photta.py`, importe-o de uma view ou de uma tarefa do Celery. Não chame a API dentro de um handler de requisição síncrono se o job for longo — envie da view, retorne o ID de geração e faça o poll a partir de uma tarefa em segundo plano ou de um consumer de Channels.

Como faço poll a partir de um worker do Celery?+

Envie o job de uma tarefa e, em seguida, agende uma tarefa de acompanhamento (via `apply_async(countdown=3)`) que faz o poll uma vez e se reagenda até que o job termine ou atinja um limite máximo de tentativas. Isso mantém os workers livres e evita tarefas de longa duração que atrapalham o auto-scaling.

Como a API sinaliza erros?+

Respostas não-2xx trazem um corpo JSON com um objeto `error`: `type`, `code`, `message`, além de `param` em erros 400 e `retry_after` em 429s. O wrapper nesta página lança um `PhottaError` contendo tudo isso para que seus chamadores possam tratar o código de status sem precisar parsear o corpo manualmente.

Python · API de Provador Virtual

Criar conta e obter chave de API

Instale `requests`, carregue `PHOTTA_API_KEY` do ambiente, escreva um wrapper `photta_request()` que envia `Authorization: Bearer photta_live_xxx` e lança um `PhottaError` tipado em respostas não-2xx, então envie um POST para `/tryon/apparel` e faça poll em `/tryon/apparel/:id` a cada 3 segundos até que `data.status == 'completed'` — tipicamente entre 1.5 e 4 minutos.

API de Provador Virtual para Python — Photta | Photta