Python · API try-on per gioielli

API try-on per gioielli in Python

In sintesi

Installa requests, carica PHOTTA_API_KEY dalle variabili d'ambiente, scrivi un wrapper photta() che invia la chiave Bearer e solleva un PhottaError tipizzato sulle risposte non-2xx, quindi invia una POST a /api/v1/tryon/jewelry ed esegui il polling su /api/v1/tryon/jewelry/{id} ogni 3 secondi finché lo status non è completed.

  • Tempo tipico: 1.5–4 min
  • Credits: 5 credits a 2K · 6 credits a 4K
  • Elaborazione: asincrono, polling
  • Limiti: 600 richieste/min
  • Autenticazione: Chiave Bearer

Ogni dato in questa pagina proviene da la documentazione dell'API di Photta · verificato

POST/api/v1/tryon/jewelry
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")

Panoramica

Panoramica

Endpoint
POST /api/v1/tryon/jewelry
Autenticazione
API key Bearer
Elaborazione
Asincrona — effettua il polling dell'endpoint di stato
Tempo tipico
1.5–4 min
Credits
5 credits a 2K · 6 credits a 4K
Rapporti d'aspetto
3:4 · 1:1 · 4:3 · 9:16 · 16:9
Limiti di input
Fino a 10 MB per immagine; JPEG, PNG, WebP
Idempotente
No

Come funziona

Cinque passaggi, zero dipendenze specifiche di Photta — requests copre tutto.

  1. Passaggio 1

    Registrati e genera una chiave

    Stesso percorso di qualsiasi altro linguaggio: ai.photta.app → Developers → Generate API key. Le chiavi iniziano con `photta_live_` e funzionano per ogni capability di Photta.

  2. Passaggio 2

    Carica la chiave dalle variabili d'ambiente

    Imposta `PHOTTA_API_KEY` nell'ambiente e leggila tramite `os.environ`. In FastAPI o Django, caricala una sola volta all'avvio in un modulo settings. Non incorporare la chiave nel codice sorgente o nella cronologia Git pubblica.

    python3 -m pip install requests
    export PHOTTA_API_KEY="photta_live_xxxxx"
  3. Passaggio 3

    Scrivi un wrapper per requests

    Una funzione `photta_request()` di trenta righe gestisce l'URL di base, l'header Authorization, la serializzazione JSON e la traduzione degli errori. È l'unica astrazione di cui hai bisogno finché non sarà disponibile l'SDK Python.

    # photta.py — one helper for every endpoint
    import os, requests
    BASE = "https://api.photta.app/api/v1"
    
    class PhottaError(Exception):
        def __init__(self, status, error, retry_after=None):
            super().__init__(error.get("message", "request failed"))
            self.status, self.type, self.retry_after = status, error.get("type"), retry_after
    
    def photta(method, path, **kwargs):
        res = requests.request(method, BASE + path, headers={"Authorization": f"Bearer {os.environ['PHOTTA_API_KEY']}"}, timeout=30, **kwargs)
        body = res.json()
        if not res.ok:
            raise PhottaError(res.status_code, body.get("error", {}), res.headers.get("Retry-After"))
        return body
  4. Passaggio 4

    Invia ed effettua il polling

    Invia una POST a `/api/v1/tryon/jewelry` per ottenere un ID di generazione, quindi esegui il polling di `/api/v1/tryon/jewelry/{id}` a intervalli di 3 secondi. In Celery o RQ, suddividi il loop di polling su più task in modo che un job di diversi minuti non blocchi un worker.

    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")
  5. Passaggio 5

    Salva il risultato

    Il payload completato include `output_url` e `thumbnail_url`. Scarica i byte nel tuo object storage — S3, GCS, Cloudflare R2 — così il tuo prodotto non dipenderà dal CDN di Photta per il rendering a lungo termine.

Errori

400invalid_request_error
The request is malformed or contains invalid parameters.
401authentication_error
The API key is missing, invalid, or expired.
402insufficient_credits_error
Your account does not have enough credits.
404not_found_error
The requested resource does not exist.
409conflict_error
The request conflicts with current state — e.g. your concurrent-batch cap is reached.
429rate_limit_error
Too many requests. Slow down and retry.Retry-After: 30
500api_error
An internal server error occurred. Retry later.
try:
    photta("POST", "/tryon/jewelry", 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."
    })
except PhottaError as e:
    if e.status == 402:
        print("insufficient_credits_error: top up before retrying")
    elif e.status == 429:
        time.sleep(int(e.retry_after or 30))
    else:
        raise

Limiti

  • 600 richieste al minuto per API key (Finestra fissa; il limite è lo stesso per ogni piano)
  • Un 429 restituisce Retry-After: 30 secondi
  • Fino a 10 MB per immagine
  • Formati: JPEG, PNG, WebP
  • Batch simultanei per piano: Free 1 · Hobby 2 · Seller 3 · Brand 4 · Studio 6
  • Solo polling — l'API non invia webhook.

Perché requests è la scelta giusta oggi

  • Nessuna dipendenza specifica per Photta — requests è già presente nella maggior parte dei progetti Python
  • Funziona ovunque giri Python: Django, FastAPI, Flask, worker Celery, Lambda, script
  • Il wrapper client è di circa trenta righe — incollalo in photta.py e vai avanti
  • Si abbina ad asyncio tramite httpx quando hai bisogno di invii paralleli

Cosa non fa

  • Nessun pacchetto Python ufficiale di Photta per ora — REST con requests è il pattern documentato
  • Il polling è l'unico segnale di completamento; l'API non invia webhook
  • Solo Bearer key; non esiste un flusso OAuth client-credentials

Domande frequenti degli sviluppatori

Esiste un SDK Python ufficiale di Photta?

Non ancora. Il percorso di integrazione supportato prevede la libreria requests (sincrona) o httpx (asincrona) — entrambe richiedono solo un sottile wrapper, e quello presente in questa pagina funziona per ogni funzionalità.

Quali versioni di Python sono supportate?

Python 3.9 e successive. Il wrapper utilizza type hint, f-string e la sintassi `str | None`, perfetta su 3.10+. Su 3.9 sostituisci `str | None` con `Optional[str]`. requests supporta ufficialmente la versione 3.8+, ma la 3.9+ rappresenta il minimo pratico per i progetti Photta moderni.

Dovrei usare requests o httpx?

requests se devi effettuare una manciata di chiamate sequenziali — è più semplice ed è già presente nella maggior parte delle codebase. httpx se ti serve la concorrenza asincrona (invii paralleli, backfill massivi) o HTTP/2. Il wrapper è minuscolo in entrambi i casi; sostituisci `requests.request` con `httpx.Client().request` e il resto del codice rimane identico.

Posso chiamarlo da Django?

Sì. Inserisci il wrapper in `services/photta.py`, importalo da una view o da un task Celery. Non chiamare l'API all'interno di un request handler sincrono se il job richiede tempo — invialo dalla view, restituisci l'ID di generazione ed esegui il polling da un background task o da un consumer Channels.

Come eseguo il polling da un worker Celery?

Invia il job da un task, poi pianifica un task successivo (tramite `apply_async(countdown=3)`) che effettua il polling una volta e si rischedula da solo fino al completamento del job o al raggiungimento della soglia massima di tentativi. In questo modo i worker rimangono liberi ed eviti task a lunga esecuzione che mandano in crisi l'autoscaling.

In che modo l'API segnala gli errori?

Le risposte non-2xx contengono un body JSON con un oggetto `error`: `type`, `code`, `message`, oltre a `param` sui 400 e `retry_after` sui 429. Il wrapper in questa pagina solleva un `PhottaError` contenente tutti questi campi, consentendo al codice chiamante di gestire i branch in base allo status code senza dover parsare manualmente il body.

Pagine correlate

Ogni dato in questa pagina proviene da la documentazione dell'API di Photta · verificato

Prova l'API in 5 minuti

Genera una chiave API di Photta, incolla lo snippet cURL qui sopra e otterrai la tua prima immagine con modello prima ancora che il caffè sia pronto.

  • 1.5–4 min
  • 5 credits a 2K · 6 credits a 4K
  • asincrono, polling
  • 600 richieste/min
  • Chiave Bearer