Python · Ghost mannequin API
Ghost mannequin API w Python
W jednym zdaniu
Zainstaluj requests, załaduj PHOTTA_API_KEY z env, napisz wrapper photta(), który wysyła klucz Bearer i rzuca typowany PhottaError przy odpowiedziach innych niż 2xx, a następnie wyślij POST do /api/v1/ghost-mannequin i wykonuj polling /api/v1/ghost-mannequin/{id} co 3 sekundy, aż status zmieni się na completed.
- Typowy czas: 1.5–4 min
- Credits: 4 credits w 2K · 5 credits w 4K
- Przetwarzanie: asynchroniczne, polling
- Limity: 600 requests/min
- Uwierzytelnianie: Klucz Bearer
Każda liczba na tej stronie pochodzi z dokumentacji API Photta · sprawdzono
RESPONSE=$(curl -s -X POST https://api.photta.app/api/v1/ghost-mannequin \
-H "Authorization: Bearer $PHOTTA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"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"
}')
ID=$(echo "$RESPONSE" | jq -r '.data.id')
# $ID is data.id from the POST response. Poll every 3 seconds until status is "completed" or "failed".
for i in $(seq 1 120); do
RESULT=$(curl -s "https://api.photta.app/api/v1/ghost-mannequin/$ID" -H "Authorization: Bearer $PHOTTA_API_KEY")
STATUS=$(echo "$RESULT" | jq -r '.data.status')
[ "$STATUS" = "completed" ] && break
[ "$STATUS" = "failed" ] && echo "generation failed" && exit 1
sleep 3
done
echo "$RESULT" | jq -r '.data.output_url'const res = await fetch("https://api.photta.app/api/v1/ghost-mannequin", {
method: "POST",
headers: { Authorization: `Bearer ${process.env.PHOTTA_API_KEY}`, "Content-Type": "application/json" },
body: JSON.stringify({
"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"
}),
});
const { data } = await res.json(); // data.id, data.status
async function waitFor(id) {
for (let attempt = 0; attempt < 120; attempt++) {
const res = await fetch(`https://api.photta.app/api/v1/ghost-mannequin/${id}`, { headers: { Authorization: `Bearer ${process.env.PHOTTA_API_KEY}` } });
const { data } = await res.json();
if (data.status === "completed") return data.output_url;
if (data.status === "failed") throw new Error(data.error_message ?? "generation failed");
await new Promise((r) => setTimeout(r, 3000));
}
throw new Error("timed out after 6 minutes");
}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")W skrócie
W skrócie
- Endpoint
- POST /api/v1/ghost-mannequin
- Uwierzytelnianie
- Klucz API Bearer
- Przetwarzanie
- Asynchroniczne — odpytuj endpoint statusu
- Typowy czas
- 1.5–4 min
- Credits
- 4 credits w 2K · 5 credits w 4K
- Proporcje obrazu
- 3:4 · 1:1 · 4:3 · 9:16 · 16:9
- Limity wejściowe
- Do 10 MB na obraz; JPEG, PNG, WebP
- Idempotentne
- Nie
Jak to działa
Pięć kroków, zero specyficznych zależności dla Photta — requests załatwia wszystko.
Krok 1
Zarejestruj się i wygeneruj klucz
Taka sama ścieżka jak w każdym innym języku: ai.photta.app → Developers → Generate API key. Klucze zaczynają się od `photta_live_` i działają we wszystkich capabilities Photta.
Krok 2
Załaduj klucz z env
Ustaw `PHOTTA_API_KEY` w środowisku i odczytuj go przez `os.environ`. W FastAPI lub Django załaduj go raz podczas startu do modułu ustawień. Nie umieszczaj klucza w kodzie źródłowym ani w publicznej historii Git.
python3 -m pip install requests export PHOTTA_API_KEY="photta_live_xxxxx"Krok 3
Napisz wrapper requests
Trzydziestoliniowa funkcja `photta_request()` obsługuje bazowy URL, nagłówek Authorization, serializację JSON i mapowanie błędów. To jedyna abstrakcja, jakiej potrzebujesz do czasu wydania SDK dla języka 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 bodyKrok 4
Wyślij i odpytuj (poll)
Wykonaj POST pod `/api/v1/ghost-mannequin`, aby pobrać ID generowania, a następnie odpytuj `/api/v1/ghost-mannequin/{id}` w 3-sekundowym interwale. W Celery lub RQ rozbij pętlę pollingu na osobne zadania, aby wielominutowe zadanie nie blokowało workera.
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")Krok 5
Zapisz wynik
Payload completed zawiera `output_url` oraz `thumbnail_url`. Pobierz bajty do własnego object storage — S3, GCS, Cloudflare R2 — dzięki czemu Twój produkt nie będzie zależny od CDN Photta w kwestii długoterminowego serwowania plików.
Błędy
- 400
invalid_request_error - The request is malformed or contains invalid parameters.
- 401
authentication_error - The API key is missing, invalid, or expired.
- 402
insufficient_credits_error - Your account does not have enough credits.
- 404
not_found_error - The requested resource does not exist.
- 409
conflict_error - The request conflicts with current state — e.g. your concurrent-batch cap is reached.
- 429
rate_limit_error - Too many requests. Slow down and retry.Retry-After: 30
- 500
api_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:
raiseLimity
- 600 żądań na minutę na klucz API (Stałe okno czasowe; limit jest taki sam w każdym planie)
- Odpowiedź 429 zawiera nagłówek Retry-After: 30 s
- Do 10 MB na obraz
- Formaty: JPEG, PNG, WebP
- Jednoczesne zadania wsadowe w zależności od planu: Free 1 · Hobby 2 · Seller 3 · Brand 4 · Studio 6
- Tylko polling — API nie wysyła webhooków.
Dlaczego requests to dziś właściwy wybór
- Brak specyficznych zależności od Photta — requests znajduje się już w większości projektów w Python
- Działa wszędzie tam, gdzie Python: Django, FastAPI, Flask, workery Celery, Lambda, skrypty
- Wrapper klienta ma około trzydziestu linii — wklej go do photta.py i przejdź do działania
- Działa z asyncio poprzez httpx, gdy potrzebujesz równoległego wysyłania żądań
Czego nie robi
- Brak oficjalnego pakietu Photta dla języka Python — udokumentowanym wzorcem jest REST z requests
- Polling jest jedynym sygnałem ukończenia; API nie wysyła webhooków
- Tylko klucz Bearer; brak przepływu OAuth client-credentials
Pytania zadawane przez programistów
Czy istnieje oficjalne SDK Photta dla języka Python?
Jeszcze nie. Wspieraną ścieżką integracji jest biblioteka requests (synchronicznie) lub httpx (asynchronicznie) — w obu przypadkach wystarczy lekki wrapper, a ten na tej stronie obsługuje każdą funkcjonalność.
Jakie wersje języka Python są wspierane?
Python 3.9 i nowsze. Wrapper korzysta z type hintów, f-stringów oraz składni `str | None`, co działa bez problemu w wersji 3.10+. W 3.9 zamień `str | None` na `Optional[str]`. Samo requests oficjalnie wspiera wersje 3.8+, ale 3.9+ to praktyczne minimum dla współczesnych projektów Photta.
Czy powinienem użyć requests czy httpx?
requests, jeśli wykonujesz kilka sekwencyjnych wywołań — jest prostsze i obecne w większości baz kodu. httpx, jeśli potrzebujesz asynchronicznej współbieżności (równoległe wysyłanie, masowe przetwarzanie wsadowe) lub HTTP/2. W obu przypadkach wrapper jest miniaturowy; zamień `requests.request` na `httpx.Client().request`, a reszta kodu pozostanie identyczna.
Czy mogę wywoływać API z poziomu Django?
Tak. Umieść wrapper w `services/photta.py`, importuj go z widoku lub zadania Celery. Nie wywołuj API wewnątrz synchronicznego handlera żądania, jeśli zadanie trwa długo — wyślij żądanie z widoku, zwróć ID generowania i odpytuj z zadania w tle lub konsumenta Channels.
Jak realizować polling z poziomu workera Celery?
Wyślij zadanie z jednego taska, a następnie zaplanuj kolejne zadanie (za pomocą `apply_async(countdown=3)`), które odpyta API raz i zaplanuje samo siebie ponownie, aż zadanie zakończy się powodzeniem lub osiągnie limit ponowień (max-retries). Zapobiega to blokowaniu workerów i eliminuje długo działające zadania, które zakłócają autoskalowanie.
Jak API sygnalizuje błędy?
Odpowiedzi inne niż 2xx zwracają body JSON z obiektem `error`: `type`, `code`, `message`, a także `param` dla kodów 400 i `retry_after` dla 429. Wrapper na tej stronie rzuca wyjątek `PhottaError` zawierający wszystkie te pola, dzięki czemu kod wywołujący może rozgałęziać logikę na podstawie kodu statusu bez konieczności samodzielnego parsowania body.
Powiązane strony
Node.js
Ghost mannequin API w Node.js
Wywołaj ghost mannequin API od Photta z backendu Node.js za pomocą natywnego fetch. SDK nie jest wymagane: zapisz klucz, wyślij zadanie, odpytuj o wynik.
CzytajcURL
Ghost mannequin API z cURL
Wywołuj ghost mannequin API Photta bezpośrednio z powłoki za pomocą cURL. Wysyłaj, odpytuj, pobieraj — każdy fragment kodu współpracuje z jq w zautomatyzowanych potokach.
CzytajMożliwości
Ghost mannequin API do zdjęć produktowych typu hollow-man
Endpoint AI ghost mannequin. Usuń manekina ze zdjęcia odzieży i zachowaj detale wnętrza. 3D lub flat-lay, przetwarzanie wsadowe, 4 credits w 2K.
CzytajTwórz
Zautomatyzuj wycinanie manekina (ghost mannequin) w swoim katalogu
Przepis na nocną automatyzację katalogu: pobierz wczorajsze aktualizacje produktów, wyślij je wsadowo do API ghost-mannequin w Photta, odpytuj nadrzędny batch i zapisz wyniki w bazie danych.
CzytajSzybki start
Pierwszy obraz z Photta w mniej niż pięć minut.
Zarejestruj się, wygeneruj klucz API, wykonaj pierwsze wywołanie cURL, odpytuj aż do ukończenia, zapisz wynik. Pięć kroków opisanych od początku do końca.
CzytajDokumentacja
Cennik Photta API
Informacje o kosztach każdego endpointu Photta API w credits dla rozdzielczości 2K i 4K, zasadach naliczania opłat i zwrotów oraz bezpłatnych endpointach. Brak bezpośredniej ceny pieniężnej za zdjęcie.
Czytaj
Każda liczba na tej stronie pochodzi z dokumentacji API Photta · sprawdzono
Wypróbuj API w 5 minut
Wygeneruj klucz Photta API, wklej powyższy snippet cURL, a otrzymasz swoje pierwsze zdjęcie na modelu, zanim zaparzy się kawa.
- 1.5–4 min
- 4 credits w 2K · 5 credits w 4K
- asynchroniczne, polling
- 600 requests/min
- Klucz Bearer