Python · Jewelry-Try-on-API

Jewelry-Try-on-API in Python

In aller Kürze

Installieren Sie requests, laden Sie PHOTTA_API_KEY aus env, schreiben Sie einen photta()-Wrapper, der den Bearer-Key sendet und bei Nicht-2xx-Antworten einen typisierten PhottaError wirft, senden Sie dann einen POST-Request an /api/v1/tryon/jewelry und pollen Sie /api/v1/tryon/jewelry/{id} alle 3 Sekunden, bis der status completed ist.

  • Typische Dauer: 1.5–4 min
  • Credits: 5 Credits bei 2K · 6 Credits bei 4K
  • Verarbeitung: asynchron, Polling
  • Limits: 600 Anfragen/Min.
  • Authentifizierung: Bearer-Key

Jeder Zahlenwert auf dieser Seite stammt aus der Photta-API-Dokumentation · geprüft

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

Auf einen Blick

Auf einen Blick

Endpoint
POST /api/v1/tryon/jewelry
Authentifizierung
Bearer-API-Schlüssel
Verarbeitung
Asynchron — Polling über den Status-Endpoint
Typische Dauer
1.5–4 min
Credits
5 Credits bei 2K · 6 Credits bei 4K
Seitenverhältnisse
3:4 · 1:1 · 4:3 · 9:16 · 16:9
Eingabelimits
Bis zu 10 MB pro Bild; JPEG, PNG, WebP
Idempotent
Nein

Funktionsweise

Fünf Schritte, null Photta-spezifische Abhängigkeiten — requests deckt alles ab.

  1. Schritt 1

    Registrieren und einen Key generieren

    Derselbe Weg wie in jeder anderen Sprache: ai.photta.app → Developers → Generate API key. Keys beginnen mit `photta_live_` und funktionieren über alle Photta-Capabilities hinweg.

  2. Schritt 2

    Den Key aus env laden

    Setzen Sie `PHOTTA_API_KEY` in der Umgebung und lesen Sie ihn über `os.environ` aus. Laden Sie ihn in FastAPI oder Django einmalig beim Start in ein Settings-Modul. Betteln Sie den Key nicht im Quellcode oder der öffentlichen Git-Historie ein.

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

    Einen requests-Wrapper schreiben

    Eine 30-zeilige `photta_request()`-Funktion übernimmt die Basis-URL, den Authorization-Header, die JSON-Serialisierung und die Fehlerübersetzung. Das ist die einzige Abstraktion, die Sie brauchen, bis das Python-SDK erscheint.

    # 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. Schritt 4

    Übermitteln und pollen

    Senden Sie einen POST an `/api/v1/tryon/jewelry`, um eine Generierungs-ID zu erhalten, und pollen Sie anschließend `/api/v1/tryon/jewelry/{id}` in einem 3-Sekunden-Intervall. Verteilen Sie die Polling-Schleife in Celery oder RQ über mehrere Tasks, damit ein minutenlanger Job keinen Worker blockiert.

    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. Schritt 5

    Ergebnis persistieren

    Die Payload nach Abschluss enthält `output_url` und `thumbnail_url`. Laden Sie die Bytes in Ihren eigenen Object Storage herunter — S3, GCS, Cloudflare R2 —, damit Ihr Produkt für das langfristige Rendering nicht an das CDN von Photta gebunden ist.

Fehler

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

Limits

  • 600 Anfragen pro Minute pro API-Schlüssel (Festes Zeitfenster; das Limit ist in jedem Tarif identisch)
  • Ein 429 enthält Retry-After: 30 Sekunden
  • Bis zu 10 MB pro Bild
  • Formate: JPEG, PNG, WebP
  • Gleichzeitige Batches pro Tarif: Free 1 · Hobby 2 · Seller 3 · Brand 4 · Studio 6
  • Nur Polling — die API sendet keine Webhooks.

Warum requests heute die richtige Wahl ist

  • Keine Photta-spezifische Abhängigkeit — requests ist bereits in den meisten Python-Projekten vorhanden
  • Funktioniert überall, wo Python läuft: Django, FastAPI, Flask, Celery-Worker, Lambda, Skripte
  • Der Client-Wrapper umfasst etwa 30 Zeilen — fügen Sie ihn in photta.py ein und machen Sie weiter
  • Lässt sich über httpx mit asyncio kombinieren, wenn Sie parallele Übermittlungen benötigen

Was es nicht tut

  • Noch kein offizielles Photta-Python-Paket — REST mit requests ist das dokumentierte Muster
  • Polling ist das einzige Fertigstellungssignal; die API sendet keine Webhooks
  • Nur Bearer-Key; es gibt keinen OAuth-Client-Credentials-Flow

Häufige Fragen von Entwicklern

Gibt es ein offizielles Photta-Python-SDK?

Noch nicht. Der unterstützte Integrationspfad ist die requests-Bibliothek (synchron) oder httpx (asynchron) — beide erfordern lediglich einen schlanken Wrapper, und der Wrapper auf dieser Seite funktioniert für jede Funktion.

Welche Python-Versionen werden unterstützt?

Python 3.9 und höher. Der Wrapper verwendet Type Hints, f-Strings und die `str | None`-Syntax, was ab 3.10 einwandfrei funktioniert. Unter 3.9 ersetzen Sie `str | None` durch `Optional[str]`. requests selbst unterstützt offiziell 3.8+, aber 3.9+ ist das praktische Minimum für moderne Photta-Projekte.

Sollte ich requests oder httpx verwenden?

requests, wenn Sie eine Handvoll sequenzieller Aufrufe durchführen — es ist einfacher und bereits in den meisten Codebasen vorhanden. httpx, wenn Sie asynchrone Nebenläufigkeit (parallele Übermittlungen, Bulk-Backfills) oder HTTP/2 benötigen. Der Wrapper ist in beiden Fällen winzig; tauschen Sie `requests.request` gegen `httpx.Client().request` aus und der restliche Code bleibt identisch.

Kann ich es über Django aufrufen?

Ja. Legen Sie den Wrapper in `services/photta.py` ab und importieren Sie ihn aus einem View oder einem Celery-Task. Rufen Sie die API bei langen Jobs nicht innerhalb eines synchronen Request-Handlers auf — übermitteln Sie den Job aus dem View, geben Sie die Generierungs-ID zurück und pollen Sie über einen Hintergrund-Task oder einen Channels-Consumer.

Wie polle ich über einen Celery-Worker?

Übermitteln Sie den Job über einen Task und planen Sie dann einen Folge-Task (über `apply_async(countdown=3)`), der einmal pollt und sich selbst neu einplant, bis der Job abgeschlossen ist oder ein Max-Retries-Schwellenwert erreicht wird. Das hält Worker frei und verhindert lang laufende Tasks, die Autoscaler stören.

Wie signalisiert die API Fehler?

Nicht-2xx-Antworten enthalten einen JSON-Body mit einem `error`-Objekt: `type`, `code`, `message`, sowie `param` bei 400ern und `retry_after` bei 429ern. Der Wrapper auf dieser Seite löst einen `PhottaError` aus, der all diese Angaben enthält, sodass Ihre Aufrufer nach Statuscode verzweigen können, ohne den Body selbst parsen zu müssen.

Testen Sie die API in fünf Minuten

Generieren Sie einen Photta-API-Schlüssel, fügen Sie das obige cURL-Snippet ein, und Sie erhalten Ihr erstes Bild am Model, noch bevor der Kaffee fertig gebrüht ist.

  • 1.5–4 min
  • 5 Credits bei 2K · 6 Credits bei 4K
  • asynchron, Polling
  • 600 Anfragen/Min.
  • Bearer-Key