Python · API de try-on virtuel
API de try-on virtuel en Python
En une phrase
Installez requests, chargez PHOTTA_API_KEY depuis l'environnement, écrivez un wrapper photta() qui transmet la clé Bearer et lève une exception typée PhottaError sur les réponses non-2xx, puis faites un POST vers /api/v1/tryon/apparel et effectuez un polling sur /api/v1/tryon/apparel/{id} toutes les 3 secondes jusqu'à ce que status passe à completed.
- Délai typique: 1.5–4 min
- Crédits: 5 crédits en 2K · 6 crédits en 4K
- Traitement: asynchrone, polling
- Limites: 600 requêtes/min
- Authentification: Clé Bearer
Chaque chiffre sur cette page provient de la documentation de l'API Photta · vérifié
RESPONSE=$(curl -s -X POST https://api.photta.app/api/v1/tryon/apparel \
-H "Authorization: Bearer $PHOTTA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"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."
}')
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/tryon/apparel/$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/tryon/apparel", {
method: "POST",
headers: { Authorization: `Bearer ${process.env.PHOTTA_API_KEY}`, "Content-Type": "application/json" },
body: JSON.stringify({
"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."
}),
});
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/tryon/apparel/${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/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")En un coup d'œil
En un coup d'œil
- Endpoint
- POST /api/v1/tryon/apparel
- Authentification
- Clé API Bearer
- Traitement
- Asynchrone — interrogez l'endpoint de statut par polling
- Délai typique
- 1.5–4 min
- Crédits
- 5 crédits en 2K · 6 crédits en 4K
- Rapports d'aspect
- 3:4 · 1:1 · 4:3 · 9:16 · 16:9
- Limites d'entrée
- Jusqu'à 10 Mo par image ; JPEG, PNG, WebP
- Idempotent
- Non
Comment ça fonctionne
Cinq étapes, zéro dépendance spécifique à Photta — requests couvre l'ensemble des besoins.
Étape 1
Créer un compte et générer une clé
Même parcours que pour tous les autres langages : ai.photta.app → Developers → Generate API key. Les clés commencent par `photta_live_` et fonctionnent sur l'ensemble des fonctionnalités de Photta.
Étape 2
Charger la clé depuis l'environnement
Définissez `PHOTTA_API_KEY` dans l'environnement et lisez-la via `os.environ`. Dans FastAPI ou Django, chargez-la une seule fois au démarrage dans un module de configuration. N'intégrez pas la clé dans le code source ou dans l'historique Git public.
python3 -m pip install requests export PHOTTA_API_KEY="photta_live_xxxxx"Étape 3
Écrire un wrapper requests
Une fonction `photta_request()` de trente lignes gère l'URL de base, l'en-tête Authorization, la sérialisation JSON et la conversion des erreurs. C'est la seule abstraction dont vous avez besoin en attendant l'arrivée du SDK 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 bodyÉtape 4
Soumettre et effectuer le polling
Envoyez un POST à `/api/v1/tryon/apparel` pour obtenir un ID de génération, puis effectuez un polling sur `/api/v1/tryon/apparel/{id}` avec un intervalle de 3 secondes. Dans Celery ou RQ, répartissez la boucle de polling sur plusieurs tâches afin qu'un traitement de plusieurs minutes ne bloque pas un 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")Étape 5
Persister le résultat
Le payload complété inclut `output_url` et `thumbnail_url`. Téléchargez les octets dans votre propre stockage objet — S3, GCS, Cloudflare R2 — pour que votre produit ne dépende pas du CDN de Photta pour le rendu à long terme.
Erreurs
- 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", "/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:
raiseLimites
- 600 requêtes par minute par clé API (Fenêtre fixe ; la limite est identique sur tous les forfaits)
- Une 429 renvoie Retry-After: 30 secondes
- Jusqu'à 10 Mo par image
- Formats: JPEG, PNG, WebP
- Lots simultanés par forfait: Free 1 · Hobby 2 · Seller 3 · Brand 4 · Studio 6
- Polling uniquement — l'API n'envoie aucun webhook.
Pourquoi requests est le bon choix aujourd'hui
- Aucune dépendance spécifique à Photta — requests est déjà présent dans la plupart des projets Python
- Fonctionne partout où Python s'exécute : Django, FastAPI, Flask, workers Celery, Lambda, scripts
- Le wrapper client fait une trentaine de lignes — collez-le dans photta.py et passez à la suite
- S'associe à asyncio via httpx lorsque vous avez besoin de soumissions parallèles
Ce qu'il ne fait pas
- Aucun package Python Photta officiel pour l'instant — l'utilisation de REST avec requests constitue l'approche documentée
- Le polling est le seul signal d'achèvement ; l'API n'envoie pas de webhooks
- Clé Bearer uniquement ; il n'y a pas de flux client-credentials OAuth
Questions fréquentes des développeurs
Existe-t-il un SDK Python officiel pour Photta ?
Pas encore. La méthode d'intégration prise en charge repose sur la bibliothèque requests (synchrone) ou httpx (asynchrone) — toutes deux ne nécessitent qu'un léger wrapper, et celui présent sur cette page fonctionne pour chaque capability.
Quelles versions de Python sont prises en charge ?
Python 3.9 et versions ultérieures. Le wrapper utilise le typage statique, les f-strings et la syntaxe `str | None`, qui fonctionne parfaitement sur 3.10+. Sur 3.9, remplacez `str | None` par `Optional[str]`. requests prend officiellement en charge 3.8+, mais 3.9+ constitue le minimum pratique pour les projets Photta modernes.
Dois-je utiliser requests ou httpx ?
requests si vous effectuez une poignée d'appels séquentiels — c'est plus simple et déjà intégré dans la plupart des bases de code. httpx si vous avez besoin de concurrence asynchrone (soumissions en parallèle, réexécutions en masse) ou de HTTP/2. Le wrapper reste minimal dans les deux cas ; remplacez `requests.request` par `httpx.Client().request` et le reste du code demeure identique.
Puis-je l'appeler depuis Django ?
Oui. Placez le wrapper dans `services/photta.py`, importez-le depuis une vue ou une tâche Celery. N'appelez pas l'API au sein d'un gestionnaire de requêtes synchrone si le traitement est long — effectuez la soumission depuis la vue, renvoyez l'ID de génération, puis effectuez le polling depuis une tâche en arrière-plan ou un consommateur Channels.
Comment effectuer le polling depuis un worker Celery ?
Soumettez la tâche depuis un premier worker, puis planifiez une tâche de suivi (via `apply_async(countdown=3)`) qui effectue un polling unique et se reprogramme jusqu'à ce que le traitement soit completed ou qu'un seuil de tentatives maximales soit atteint. Cela permet de libérer les workers et d'éviter les tâches à longue durée qui perturbent les mécanismes d'autoscaling.
Comment l'API signale-t-elle les erreurs ?
Les réponses autres que 2xx contiennent un corps JSON avec un objet `error` : `type`, `code`, `message`, ainsi que `param` pour les erreurs 400 et `retry_after` pour les erreurs 429. Le wrapper présenté sur cette page lève une exception `PhottaError` contenant l'ensemble de ces champs, afin que vos appelants puissent gérer les embranchements selon le code de statut sans avoir à analyser le corps eux-mêmes.
Pages associées
Node.js
API de try-on virtuel en Node.js
Appelez aPI de try-on virtuel de Photta depuis un backend Node.js avec fetch natif. Aucun SDK requis : stockez votre clé, soumettez le job, récupérez le résultat par polling.
LirecURL
API de try-on virtuel avec cURL
Appelez aPI de try-on virtuel de Photta directement depuis le shell avec cURL. Soumettez, effectuez le polling, téléchargez — chaque extrait s'associe à jq pour vos pipelines scriptés.
LireFonctionnalités
API de try-on virtuel pour les vêtements
API REST qui positionne des vêtements sur des mannequins générés par IA. Traitement asynchrone, génération en 1.5–4 minutes, 5 crédits en 2K, 6 en 4K. Exemples en cURL, Node.js et Python.
LireDévelopper
Intégrez une fonctionnalité de try-on virtuel à votre application
Guide d'implémentation de bout en bout pour intégrer le try-on virtuel avec l'API Photta : upload, soumission, polling via un worker, rendu du résultat. Architecture TypeScript + server-only.
LireDévelopper
Ajouter le virtual try-on à une application iOS ou Android
Comment ajouter le virtual try-on IA à une application native iOS ou Android avec l'API Photta : ne livrez jamais la clé sur l'appareil, passez par un proxy sur votre backend, répliquez l'état des jobs.
LireDémarrage rapide
Première image Photta en moins de cinq minutes.
Inscrivez-vous, générez une clé d'API, lancez votre premier appel cURL, effectuez le polling jusqu'à la complétion, persistez le résultat. Cinq étapes documentées de bout en bout.
LireRéférence
Tarification de l'API Photta
Le coût en credits de chaque endpoint de l’API Photta en 2K et 4K, le fonctionnement de la facturation et des remboursements, et les endpoints gratuits. Aucun prix monétaire par image.
Lire
Chaque chiffre sur cette page provient de la documentation de l'API Photta · vérifié
Testez l'API en cinq minutes
Générez une clé d'API Photta, collez le snippet cURL ci-dessus, et vous obtiendrez votre première photo portée sur modèle avant même que le café ait fini de couler.
- 1.5–4 min
- 5 crédits en 2K · 6 crédits en 4K
- asynchrone, polling
- 600 requêtes/min
- Clé Bearer