Python · API för virtuell try-on

API för virtuell try-on i Python

I en mening

Installera requests, läs in PHOTTA_API_KEY från env, skriv en photta()-wrapper som skickar Bearer-nyckeln och kastar ett typat PhottaError vid svar som inte är 2xx, gör sedan en POST till /api/v1/tryon/apparel och polla /api/v1/tryon/apparel/{id} var 3:e sekund tills status är completed.

  • Typisk tid: 1.5–4 min
  • Credits: 5 credits vid 2K · 6 credits vid 4K
  • Bearbetning: asynkron, polling
  • Gränser: 600 requests/min
  • Autentisering: Bearer-nyckel

Varje siffra på den här sidan kommer från Photter API-dokumentationen · kontrollerad

POST/api/v1/tryon/apparel
import os, requests

res = requests.post(
    "https://api.photta.app/api/v1/tryon/apparel",
    headers={"Authorization": f"Bearer {os.environ['PHOTTA_API_KEY']}"},
    json={
      "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."
    },
)
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/apparel/{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")

I korthet

I korthet

Endpoint
POST /api/v1/tryon/apparel
Autentisering
Bearer API-nyckel
Bearbetning
Asynkron — polla status-endpointen
Typisk tid
1.5–4 min
Credits
5 credits vid 2K · 6 credits vid 4K
Bildförhållanden
3:4 · 1:1 · 4:3 · 9:16 · 16:9
Indatagränser
Upp till 10 MB per bild; JPEG, PNG, WebP
Idempotent
Nej

Hur det fungerar

Fem steg, noll Photta-specifika beroenden — requests täcker allt.

  1. Steg 1

    Skapa konto och generera en nyckel

    Samma väg som för alla andra språk: ai.photta.app → Developers → Generate API key. Nycklar börjar med `photta_live_` och fungerar över alla Photta-capabilities.

  2. Steg 2

    Läs in nyckeln från env

    Sätt `PHOTTA_API_KEY` i miljön och läs den via `os.environ`. I FastAPI eller Django, läs in den en gång vid uppstart i en settings-modul. Bädda inte in nyckeln i källkod eller publik Git-historik.

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

    Skriv en requests-wrapper

    En trettioraders `photta_request()`-funktion hanterar bas-URL:en, Authorization-headern, JSON-serialisering och felöversättning. Det är den enda abstraktionen du behöver tills Python-SDK:t släpps.

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

    Skicka och polla

    Gör en POST till `/api/v1/tryon/apparel` för att få ett generations-ID, och polla sedan `/api/v1/tryon/apparel/{id}` med ett 3-sekundersintervall. I Celery eller RQ, dela upp poll-loopen över flera tasks så att ett jobb på flera minuter inte låser en worker.

    import os, requests
    
    res = requests.post(
        "https://api.photta.app/api/v1/tryon/apparel",
        headers={"Authorization": f"Bearer {os.environ['PHOTTA_API_KEY']}"},
        json={
          "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."
        },
    )
    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/apparel/{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. Steg 5

    Spara resultatet

    Den färdiga payloaden innehåller `output_url` och `thumbnail_url`. Ladda ner byten till din egen objektlagring — S3, GCS, Cloudflare R2 — så att din produkt inte är bunden till Phottas CDN för långsiktig rendering.

Fel

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/apparel", json={
      "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."
    })
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

Gränser

  • 600 anrop per minut per API-nyckel (Fast fönster; gränsen är densamma på alla planer)
  • En 429 innehåller Retry-After: 30 sekunder
  • Upp till 10 MB per bild
  • Format: JPEG, PNG, WebP
  • Samtidiga batcher per plan: Free 1 · Hobby 2 · Seller 3 · Brand 4 · Studio 6
  • Endast polling — API:et skickar inga webhooks.

Varför requests är rätt val idag

  • Inget Photta-specifikt beroende — requests finns redan i de flesta Python-projekt
  • Fungerar överallt där Python körs: Django, FastAPI, Flask, Celery-workers, Lambda, skript
  • Klient-wrappern är på cirka trettio rader — klistra in den i photta.py och gå vidare
  • Fungerar utmärkt med asyncio via httpx när du behöver parallella anrop

Vad det inte gör

  • Inget officiellt Photta Python-paket än — REST med requests är det dokumenterade mönstret
  • Polling är den enda signalen för slutförande; API:et skickar inga webhooks
  • Endast Bearer-nyckel; det finns inget OAuth-flöde för client-credentials

Vanliga utvecklarfrågor

Finns det ett officiellt Photta Python-SDK?

Inte än. Den stödda integrationsvägen är biblioteket requests (synkront) eller httpx (asynkront) — båda kräver bara en tunn wrapper, och wrappern på den här sidan fungerar för alla capabilities.

Vilka Python-versioner stöds?

Python 3.9 och senare. Wrappern använder typannoteringar, f-strängar och syntaxen `str | None`, vilket fungerar fint i 3.10+. I 3.9 byter du ut `str | None` mot `Optional[str]`. requests i sig stöder officiellt 3.8+, men 3.9+ är det praktiska minimikravet för moderna Photta-projekt.

Bör jag använda requests eller httpx?

requests om du gör en handfull sekventiella anrop — det är enklare och finns redan i de flesta kodbaser. httpx om du behöver asynkron samtidighet (parallella anrop, massuppdateringar i efterhand) eller HTTP/2. Wrappern är minimal oavsett vilket; byt `requests.request` mot `httpx.Client().request` så förblir resten av koden identisk.

Kan jag anropa det från Django?

Ja. Lägg wrappern i `services/photta.py`, importera den från en view eller en Celery-task. Anropa inte API:et i en synkron request-handler om jobbet tar lång tid — skicka anropet från din view, returnera generations-ID:t och polla från en bakgrundstask eller en Channels-konsument.

Hur pollar jag från en Celery-worker?

Skicka jobbet från en task och schemalägg sedan en uppföljningstask (via `apply_async(countdown=3)`) som pollar en gång och schemalägger om sig själv tills jobbet är klart eller en maxgräns för retries nås. Detta håller workers lediga och undviker långkörande tasks som stör autoskalare.

Hur signalerar API:et fel?

Svar som inte är 2xx innehåller en JSON-body med ett `error`-objekt: `type`, `code`, `message`, samt `param` vid 400 och `retry_after` vid 429. Wrappern på den här sidan kastar ett `PhottaError` som innehåller alla dessa, så att dina anropare kan förgrena logiken baserat på statuskod utan att själva behöva parsa bodyn.

Relaterade sidor

Varje siffra på den här sidan kommer från Photter API-dokumentationen · kontrollerad

Testa API:et på fem minuter

Generera en Photta API-nyckel, klistra in cURL-kodfragmentet ovan, och du har din första bild på en modell innan kaffet har bryggts klart.

  • 1.5–4 min
  • 5 credits vid 2K · 6 credits vid 4K
  • asynkron, polling
  • 600 requests/min
  • Bearer-nyckel