Python · Virtual Try-On API
Virtual Try-On API w Python
Nie trzeba instalować nic przez pip — dokumentacja Photta oficjalnie zaleca bibliotekę requests. Trzydziestoliniowy wrapper można bez problemu zintegrować z Django, FastAPI, workerami Celery i handlerami Lambda.
W jednym zdaniu
Zainstaluj `requests`, załaduj `PHOTTA_API_KEY` z env, napisz wrapper `photta_request()` wysyłający `Authorization: Bearer photta_live_xxx` i rzucający wyjątek `PhottaError` przy błędach, a następnie wyślij POST do `/tryon/apparel` i odpytuj `/tryon/apparel/:id` co 3 sekundy do `data.status == 'completed'` — zwykle w 1.5 do 4 minut.
Zaktualizowano · 2026-04-19
Twoje pierwsze zapytanie
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)Czego się spodziewać
Typical completion
1.5–4min
2K / 4K credits
5 / 7
Jewelry types
4
Close-up mannequins
built-in
Jak to działa
Virtual Try-On API w Python
Pięć kroków, zero specyficznych zależności Photta — requests załatwia wszystko.
- 01
Krok 1
Zarejestruj się i wygeneruj klucz
Ta sama ścieżka co w innych językach: ai.photta.app → Developers → Generate API key. Klucze zaczynają się od `photta_live_` i działają we wszystkich funkcjach Photta.
- 02
Krok 2
Załaduj klucz z env
Ustaw `PHOTTA_API_KEY` w środowisku i odczytaj go przez `os.environ`. W FastAPI lub Django załaduj go raz przy starcie do modułu ustawień. Nie umieszczaj klucza w kodzie ani w publicznej historii Git.
- 03
Krok 3
Napisz wrapper requests
Trzydziestoliniowa funkcja `photta_request()` obsługuje bazowy URL, nagłówek Authorization, serializację JSON i tłumaczenie błędów. To jedyna abstrakcja, jakiej potrzebujesz do czasu wydania Python SDK.
- 04
Krok 4
Wyślij i odpytuj
Wyślij POST do `/tryon/apparel`, aby otrzymać identyfikator generacji, a następnie odpytuj `/tryon/apparel/:id` w 3-sekundowych odstępach. W Celery lub RQ rozbij pętlę odpytywania na zadania, aby 4-minutowe zadanie nie blokowało workera.
- 05
Krok 5
Zapisz wynik
Zakończone zadanie zawiera `output_url` i `thumbnail_url`. Pobierz bajty do własnego magazynu obiektowego — S3, GCS, Cloudflare R2 — aby Twój produkt nie był zależny od CDN Photta przy długoterminowym renderowaniu.
Kod, od początku do końca
Copy, paste, done.
Four snippets — install prerequisites, wrap the REST call, submit + poll, then handle the errors that actually happen in production.
# 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# 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 bodyimport 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)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:
raiseDlaczego taki format
Dlaczego requests to dziś najlepszy wybór
- 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
Czego to nie robi
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
Pytania innych programistów
Questions other developers ask
Czy istnieje oficjalne Photta Python SDK?+
Jeszcze nie. Mapa drogowa Photta priorytetyzuje Python SDK po pozyskaniu dziesięciu płacących klientów API. Do tego czasu wspieraną ścieżką jest biblioteka requests (synchronicznie) lub httpx (asynchronicznie) — obie są opisane w oficjalnej dokumentacji i obie współpracują z wrapperem z tej strony.
Jakie wersje Pythona są obsługiwane?+
Python 3.9 i nowsze. Wrapper używa type hintów, f-stringów i składni `str | None`, która działa w 3.10+. W 3.9 zamień `str | None` na `Optional[str]`. Sam requests wspiera 3.8+, ale 3.9+ to praktyczne minimum dla nowoczesnych projektów Photta.
Czy powinienem użyć requests czy httpx?+
requests, jeśli wykonujesz kilka sekwencyjnych połączeń — jest prostszy i obecny w większości projektów. httpx, jeśli potrzebujesz asynchronicznej współbieżności (równoległe wysyłanie, masowe aktualizacje) lub HTTP/2. Wrapper jest mały w obu przypadkach; zamień `requests.request` na `httpx.Client().request`, a reszta kodu pozostanie identyczna.
Czy mogę wywołać to z Django?+
Tak. Umieść wrapper w `services/photta.py`, importuj go w widoku lub zadaniu Celery. Nie wywołuj API wewnątrz synchronicznego handlera żądań, jeśli zadanie jest długie — wyślij je z widoku, zwróć identyfikator generacji i odpytuj z zadania w tle lub consumera Channels.
Jak odpytywać z workera Celery?+
Wyślij zadanie z jednego taska, a następnie zaplanuj kolejne zadanie (przez `apply_async(countdown=3)`), które raz odpyta i zaplanuje się ponownie, aż zadanie zostanie zakończone lub osiągnięty zostanie limit powtórzeń. To zwalnia workery i zapobiega długotrwałym zadaniom, które zakłócają autoskalowanie.
Jak API sygnalizuje błędy?+
Odpowiedzi inne niż 2xx zawierają body JSON z obiektem `error`: `type`, `code`, `message`, oraz `param` przy 400 i `retry_after` przy 429. Wrapper na tej stronie rzuca `PhottaError` zawierający te dane, dzięki czemu możesz reagować na kody statusu bez ręcznego parsowania body.
Python · Virtual Try-On API
Utwórz konto i pobierz klucz API
Zainstaluj `requests`, załaduj `PHOTTA_API_KEY` z env, napisz wrapper `photta_request()` wysyłający `Authorization: Bearer photta_live_xxx` i rzucający wyjątek `PhottaError` przy błędach, a następnie wyślij POST do `/tryon/apparel` i odpytuj `/tryon/apparel/:id` co 3 sekundy do `data.status == 'completed'` — zwykle w 1.5 do 4 minut.