Python · Ghost mannequin-API

Ghost mannequin-API i Python

I én setning

Installer requests, last inn PHOTTA_API_KEY fra env, skriv en photta()-wrapper som sender Bearer-nøkkelen og kaster en typet PhottaError ved ikke-2xx-responser, send deretter POST til /api/v1/ghost-mannequin og poll /api/v1/ghost-mannequin/{id} hvert 3. sekund til status er completed.

  • Typisk tidsbruk: 1.5–4 min
  • Credits: 4 credits ved 2K · 5 credits ved 4K
  • Prosessering: asynkron, polling
  • Grenser: 600 forespørsler/min
  • Autentisering: Bearer-nøkkel

Hvert tall på denne siden er hentet fra dokumentasjonen for Photta-API-et · verifisert

POST/api/v1/ghost-mannequin
import os, requests

res = requests.post(
    "https://api.photta.app/api/v1/ghost-mannequin",
    headers={"Authorization": f"Bearer {os.environ['PHOTTA_API_KEY']}"},
    json={
      "product_image": "https://cdn.yourstore.com/products/jacket-front.jpg",
      "back_image": "https://cdn.yourstore.com/products/jacket-back.jpg",
      "image_side": "front",
      "angle": "side",
      "style": "3d",
      "background_color": "white",
      "resolution": "2K",
      "aspect_ratio": "3:4",
      "user_instruction": "closed front, cream interior lining",
      "brand_label_id": "7cc9f988-068b-44cd-8004-22f486b10e67"
    },
)
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/ghost-mannequin/{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")

Kort oppsummert

Kort oppsummert

Endepunkt
POST /api/v1/ghost-mannequin
Autentisering
Bearer API-nøkkel
Prosessering
Asynkron – poll status-endepunktet
Typisk tidsbruk
1.5–4 min
Credits
4 credits ved 2K · 5 credits ved 4K
Bildeformater
3:4 · 1:1 · 4:3 · 9:16 · 16:9
Inndatagrenser
Opptil 10 MB per bilde; JPEG, PNG, WebP
Idempotent
Nei

Slik fungerer det

Fem trinn, null Photta-spesifikke avhengigheter — requests dekker alt.

  1. Trinn 1

    Registrer deg og generer en nøkkel

    Samme fremgangsmåte som alle andre språk: ai.photta.app → Developers → Generate API key. Nøkler starter med `photta_live_` og fungerer på tvers av alle Photta-capabilities.

  2. Trinn 2

    Last inn nøkkelen fra env

    Sett `PHOTTA_API_KEY` i miljøet og les den via `os.environ`. I FastAPI eller Django laster du den inn én gang ved oppstart i en innstillingsmodul. Ikke bygg inn nøkkelen i kildekode eller offentlig Git-historikk.

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

    Skriv en requests-wrapper

    En trettilinrers `photta_request()`-funksjon håndterer base-URL-en, Authorization-headeren, JSON-serialisering og feiloversettelse. Det er den eneste abstraksjonen du trenger inntil Python-SDK-en lanseres.

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

    Send inn og poll

    Gjør en POST til `/api/v1/ghost-mannequin` for å hente en generasjons-ID, og poll deretter `/api/v1/ghost-mannequin/{id}` med 3 sekunders intervall. I Celery eller RQ bør du dele opp polling-løkken på tvers av oppgaver, slik at en jobb som tar flere minutter ikke blokkerer en worker.

    import os, requests
    
    res = requests.post(
        "https://api.photta.app/api/v1/ghost-mannequin",
        headers={"Authorization": f"Bearer {os.environ['PHOTTA_API_KEY']}"},
        json={
          "product_image": "https://cdn.yourstore.com/products/jacket-front.jpg",
          "back_image": "https://cdn.yourstore.com/products/jacket-back.jpg",
          "image_side": "front",
          "angle": "side",
          "style": "3d",
          "background_color": "white",
          "resolution": "2K",
          "aspect_ratio": "3:4",
          "user_instruction": "closed front, cream interior lining",
          "brand_label_id": "7cc9f988-068b-44cd-8004-22f486b10e67"
        },
    )
    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/ghost-mannequin/{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. Trinn 5

    Lagre resultatet permanent

    Den fullførte payloaden inkluderer `output_url` og `thumbnail_url`. Last ned rådataene til din egen objektlagring — S3, GCS, Cloudflare R2 — slik at produktet ditt ikke er låst til Phottas CDN for langsiktig visning.

Feil

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", "/ghost-mannequin", json={
      "product_image": "https://cdn.yourstore.com/products/jacket-front.jpg",
      "back_image": "https://cdn.yourstore.com/products/jacket-back.jpg",
      "image_side": "front",
      "angle": "side",
      "style": "3d",
      "background_color": "white",
      "resolution": "2K",
      "aspect_ratio": "3:4",
      "user_instruction": "closed front, cream interior lining",
      "brand_label_id": "7cc9f988-068b-44cd-8004-22f486b10e67"
    })
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

Grenser

  • 600 forespørsler per minutt per API-nøkkel (Fast tidsvindu; grensen er lik for alle abonnementer)
  • En 429 inneholder Retry-After: 30 sekunder
  • Opptil 10 MB per bilde
  • Formater: JPEG, PNG, WebP
  • Samtidige batcher per abonnement: Free 1 · Hobby 2 · Seller 3 · Brand 4 · Studio 6
  • Kun polling – API-et sender ikke webhooks.

Hvorfor requests er det rette valget i dag

  • Ingen Photta-spesifikke avhengigheter — requests finnes allerede i de fleste Python-prosjekter
  • Fungerer overalt hvor Python kjører: Django, FastAPI, Flask, Celery-workers, Lambda, skript
  • Klient-wrapperen er på rundt tretti linjer — lim den inn i photta.py og gå videre
  • Fungerer sømløst med asyncio via httpx når du trenger parallell innsending

Hva den ikke gjør

  • Ingen offisiell Photta Python-pakke ennå — REST med requests er det dokumenterte mønsteret
  • Polling er det eneste signalet på fullføring; API-et sender ikke webhooks
  • Kun Bearer-nøkkel; det finnes ingen OAuth client-credentials-flyt

Spørsmål utviklere stiller

Finnes det en offisiell Photta Python-SDK?

Ikke ennå. Den støttede integrasjonsmåten er requests-biblioteket (synkront) eller httpx (asynkront) — begge krever bare en tynn wrapper, og wrapperen på denne siden fungerer for alle funksjoner.

Hvilke Python-versjoner støttes?

Python 3.9 og nyere. Wrapperen bruker type hints, f-strenger og `str | None`-syntaks, som fungerer fint på 3.10+. På 3.9 bytter du ut `str | None` med `Optional[str]`. requests i seg selv støtter offisielt 3.8+, men 3.9+ er det praktiske minimumskravet for moderne Photta-prosjekter.

Bør jeg bruke requests eller httpx?

requests hvis du gjør en håndfull sekvensielle kall — det er enklere og finnes allerede i de fleste kodebaser. httpx hvis du trenger asynkron samtidighet (parallelle innsendinger, backfills i bulk) eller HTTP/2. Wrapperen er minimal uansett; bytt ut `requests.request` med `httpx.Client().request`, så forblir resten av koden identisk.

Kan jeg kalle den fra Django?

Ja. Legg wrapperen i `services/photta.py`, og importer den fra et view eller en Celery-oppgave. Ikke kall API-et direkte i en synkron request-handler hvis jobben tar lang tid — send inn fra viewet, returner generasjons-ID-en, og poll fra en bakgrunnsoppgave eller en Channels-consumer.

Hvordan poller jeg fra en Celery-worker?

Send inn jobben fra én oppgave, og planlegg deretter en oppfølgingsoppgave (via `apply_async(countdown=3)`) som poller én gang og planlegger seg selv på nytt inntil jobben er fullført eller grensen for maks antall forsøk nås. Dette holder workers ledige og unngår langvarige oppgaver som forstyrrer autoskalering.

Hvordan signaliserer API-et feil?

Ikke-2xx-responser returnerer en JSON-body med et `error`-objekt: `type`, `code`, `message`, i tillegg til `param` på 400-feil og `retry_after` på 429-feil. Wrapperen på denne siden kaster en `PhottaError` som inneholder alle disse, slik at kallende kode kan forgrene på statuskode uten å parse bodyen manuelt.

Prøv API-et på fem minutter

Generer en Photta API-nøkkel, lim inn cURL-kodesnutten ovenfor, og du har ditt første bilde på modell før kaffen er ferdig traktet.

  • 1.5–4 min
  • 4 credits ved 2K · 5 credits ved 4K
  • asynkron, polling
  • 600 forespørsler/min
  • Bearer-nøkkel