Documentation API
API PhotoFig
Mettez en file des retouches et redimensionnements d'images produit, appliquez des modèles à des lots entiers, suivez l'avancement et recevez des événements webhook signés avec des clés API.
Besoin d'un schéma lisible par machine ? Téléchargez le JSON OpenAPI.
Sur cette page
Démarrage rapide
Créez une clé API dans Paramètres. Remplacez YOUR_API_KEY ci-dessous et enregistrez une photo sous le nom product.jpg.
Envoyer une photo
Envoyez la photo pour ajouter une ombre au produit. La réponse contient un identifiant de tâche et statusUrl.
curl https://api.photofig.com/v1/tools/ai-shadows/edit \ -H "Authorization: Bearer YOUR_API_KEY" \ -F "image=@product.jpg"Vérifier la tâche
Remplacez STATUS_URL par la valeur statusUrl reçue. Si status vaut queued ou processing, attendez avant de vérifier à nouveau.
curl "STATUS_URL" \ -H "Authorization: Bearer YOUR_API_KEY"Télécharger le résultat
Lorsque status vaut completed, remplacez RESULT_URL par la valeur resultUrl reçue pour enregistrer l’image.
curl -fL "RESULT_URL" -o photofig-result.png
Utilisez les Webhooks pour recevoir automatiquement les événements de fin.
Authentification
Les routes API acceptent les clés API générées à partir de Paramètres. Le secret complet n'est affiché qu'une seule fois lors de la création de la clé.
Authorization: Bearer pf_live_...Les clés d'API ne fonctionnent qu'avec les points de terminaison de cette page ; toutes les autres routes PhotoFig les refusent. Une clé agit pour la personne qui l'a créée, dans l'espace de travail où elle a été créée.
Limites et quotas
L'accès à l'API est inclus dans Pro et Studio. GET /v1/account indique les limites de votre forfait, dont le quota horaire de requêtes dans limits.rateLimitPerHour.
Chaque requête authentifiée compte dans le quota horaire, y compris la consultation de l'état des tâches. Les réponses contiennent X-RateLimit-Limit et X-RateLimit-Remaining. Une fois le quota épuisé, l'API répond 429 rate_limit_exceeded avec un en-tête Retry-After.
mask utilise des suppressions d'arrière-plan, ai-bg et ai-shadows un crédit IA chacun, et resize ni l'un ni l'autre. Les crédits ne sont décomptés qu'à la fin d'une tâche.
Les tâches en attente ou en cours comptent dans la limite de tâches simultanées de votre forfait. Au-delà, les nouvelles retouches reçoivent 429 too_many_jobs jusqu'à la fin des tâches précédentes.
POST /v1/uploads et POST /v1/tools/{tool_id}/edit acceptent un en-tête facultatif X-Idempotency-Key. Une nouvelle tentative avec la même clé renvoie la première réponse au lieu de lancer une seconde tâche ; utilisez donc une nouvelle clé pour chaque requête distincte.
Compte
/v1/accountUtilisez cette route pour vérifier vos identifiants et consulter les limites du forfait, les crédits restants et les outils disponibles.
{
"accountId": "uuid",
"workspaceId": "uuid",
"plan": "pro",
"apiEnabled": true,
"credits": {
"remaining": 2000,
"bonusRemaining": 0,
"periodEndsAt": "2026-11-01T00:00:00Z"
},
"limits": {
"maxFileSizeBytes": 10485760,
"rateLimitPerHour": 60,
"concurrentJobs": 3,
"maxApiKeys": 1,
"freeBgRemovals": 0,
"bgRemovalsUsed": 0,
"aiCredits": 2000
},
"tools": [
"mask",
"ai-bg",
"ai-shadows",
"resize"
]
}Outils
/v1/tools/v1/tools/{tool_id}Chaque outil accepte une image produit ordinaire via imageUrl, uploadSessionId ou un envoi multipart. Inutile d'appeler mask d'abord : ai-bg et ai-shadows suppriment eux-mêmes l'arrière-plan.
mask
Supprime l'arrière-plan et renvoie le produit détouré dans un PNG transparent. Utilisez cet outil pour isoler le produit avant votre propre composition ou traitement destiné à une plateforme de vente.
ai-shadows
Ajoute une ombre de produit réaliste et renvoie une image prête à être placée sur un arrière-plan propre. Fonctionne mieux sur les photos de produits où le sujet est clairement visible et non masqué par une scène animée.
ai-bg
Génère un nouveau fond de produit à partir d'un thème court, tel que warm oak tabletop ou minimal white studio. Soumettez directement l’image du produit ; un appel distinct de suppression d’arrière-plan n’est pas requis.

resize
Ajuste une photo à une taille de canevas exacte en conservant son propre arrière-plan, comme « Redimensionner les photos » dans l'application. Choisissez ajuster ou remplir, la position et le remplissage. N'utilise aucun crédit IA.
Importer et modifier en un seul appel
/v1/tools/{tool_id}/editC'est le parcours le plus simple : envoyez une modification avec imageUrl si l'image source est déjà accessible par URL, ou transmettez le champ image en multipart pour un fichier local. Cette méthode convient lorsqu'un seul outil doit traiter une seule image.
Choisissez cette option pour traiter une image une seule fois, sans avoir à réutiliser le fichier source importé.
curl -X POST https://api.photofig.com/v1/tools/ai-shadows/edit \
-H "Authorization: Bearer pf_live_..." \
-F "image=@product.jpg" \
-F "seed=128742"Importez d'abord, modifiez plus tard
/v1/uploadsCréez une session d'envoi pour transmettre l'image directement au stockage, puis lancez une retouche avec l'uploadSessionId renvoyé. La limite de taille est la même que pour une requête multipart, et chaque session sert à une seule retouche.
Choisissez cette méthode lorsque votre client ne doit pas faire transiter l'image par la requête de retouche, par exemple un navigateur qui envoie directement au stockage.
UPLOAD_JSON=$(curl -s -X POST https://api.photofig.com/v1/uploads \
-H "Authorization: Bearer pf_live_..." \
-H "Content-Type: application/json" \
-d '{
"contentType": "image/jpeg",
"filename": "product.jpg",
"sizeBytes": 1842031
}')
curl -X PUT "$(echo "$UPLOAD_JSON" | jq -r '.uploadUrl')" \
-H "Content-Type: image/jpeg" \
--data-binary @product.jpg
curl -X POST https://api.photofig.com/v1/tools/ai-shadows/edit \
-H "Authorization: Bearer pf_live_..." \
-H "Content-Type: application/json" \
-d "{
\"uploadSessionId\": \"$(echo "$UPLOAD_JSON" | jq -r '.uploadSessionId')\",
\"parameters\": { \"seed\": 128742 }
}"Créer des modifications
/v1/tools/{tool_id}/editEnvoyez des retouches avec imageUrl, uploadSessionId ou un champ multipart image. La réponse renvoie un identifiant de tâche pour le suivi, l'annulation, la suppression et la correspondance avec les événements webhook. Les paramètres qu'un outil n'utilise pas sont ignorés.
Arrière-plan IA
Le point de terminaison d'arrière-plan IA fonctionne mieux avec un thème de scène concis : un décor, une surface, un type d'éclairage ou une ambiance en quelques mots. Par exemple warm oak tabletop,minimal white studio, and soft morning kitchen light.
curl -X POST https://api.photofig.com/v1/tools/ai-bg/edit \
-H "Authorization: Bearer pf_live_..." \
-H "Content-Type: application/json" \
-d '{
"imageUrl": "https://cdn.example.com/product.png",
"parameters": {
"theme": "warm oak tabletop",
"seed": 128742
}
}'Product Shadow
curl -X POST https://api.photofig.com/v1/tools/ai-shadows/edit \
-H "Authorization: Bearer pf_live_..." \
-H "Content-Type: application/json" \
-d '{
"imageUrl": "https://cdn.example.com/product.png",
"parameters": { "seed": 128742 }
}'Masque
mask ne prend aucun paramètre et renvoie un détourage PNG avec transparence.
curl -X POST https://api.photofig.com/v1/tools/mask/edit \
-H "Authorization: Bearer pf_live_..." \
-H "Content-Type: application/json" \
-d '{
"imageUrl": "https://cdn.example.com/product.png"
}'Redimensionner
width et height fixent la sortie en pixels, de 100 à 4096. mode vaut fit (la photo entière, par défaut), fill (couvre le canevas et rogne le débordement), width ou height. horizontal et vertical placent la photo, et background remplit l'espace libre : transparent, une couleur #RRGGBB ou un objet de dégradé. Le résultat est un PNG.
curl -X POST https://api.photofig.com/v1/tools/resize/edit \
-H "Authorization: Bearer pf_live_..." \
-H "Content-Type: application/json" \
-d '{
"imageUrl": "https://cdn.example.com/product.jpg",
"parameters": {
"width": 1000,
"height": 1000,
"mode": "fit",
"background": "#ffffff"
}
}'Tâches
/v1/jobs/v1/jobs/{job_id}/v1/jobs/{job_id}/cancel/v1/jobs/{job_id}Répertoriez, consultez, annulez ou supprimez les tâches API. Elles n'apparaissent ni dans les fichiers importés ni dans les créations de l'application. Leur suppression efface également les fichiers associés à l'API.
GET /v1/jobs/{job_id} renvoie l'état de la tâche. Une fois terminée, téléchargez l'image depuis resultUrl avant expiresAt. Chaque consultation compte dans votre quota horaire ; utilisez les webhooks pour recevoir les événements de fin.
{
"id": "api_edit_uuid",
"tool": "ai-shadows",
"status": "completed",
"createdAt": "2026-07-15T10:15:00Z",
"startedAt": "2026-07-15T10:15:04Z",
"finishedAt": "2026-07-15T10:15:23Z",
"statusUrl": "https://api.photofig.com/v1/jobs/api_edit_uuid",
"resultUrl": "https://storage.example.com/signed-result-url",
"thumbnailUrl": "https://storage.example.com/signed-thumbnail-url",
"expiresAt": "2026-07-15T11:15:23Z",
"error": null
}Modèles
/v1/templates/v1/templates/v1/templates/{template_id}/v1/templates/{template_id}/v1/templates/{template_id}Un modèle est un rendu que vous appliquez à de nombreuses photos : détourage, placement, fond et ombre, marge et tailles d'export. Les modèles créés via l'API s'ouvrent et se modifient dans l'application PhotoFig, et inversement. Les modèles système sont prêts à l'emploi et en lecture seule.
mask et resize sont obligatoires ; les autres étapes sont facultatives et s'exécutent dans un ordre fixe. Les étapes ou champs inconnus sont refusés, et les valeurs doivent rester dans les plages proposées par l'éditeur. Le schéma OpenAPI décrit chaque champ.
curl -X POST https://api.photofig.com/v1/templates \
-H "Authorization: Bearer pf_live_..." \
-H "Content-Type: application/json" \
-d '{
"name": "Cream catalog",
"steps": {
"mask": {},
"reposition": { "horizontal": "center", "vertical": "center", "scale": 0.85 },
"background": { "backgroundType": "solid", "color": "#f6f1ea" },
"ai-shadows": { "opacity": 0.8 },
"resize": { "mode": "fit", "targets": [{ "width": 2000, "height": 2000 }] }
},
"export": { "format": "jpg", "background": "#ffffff" }
}'creditsPerPhoto indique ce que le modèle facture pour chaque photo, par exemple un crédit IA pour ai-shadows.
Lots
/v1/batches/v1/batches/{batch_id}/uploads/v1/batches/{batch_id}/uploads/{upload_id}/complete/v1/batches/{batch_id}/process/v1/batches/{batch_id}/v1/batches/v1/batches/{batch_id}/cancel/v1/batches/{batch_id}Un lot applique un modèle à de nombreuses photos. Créez-le, ajoutez les photos, puis traitez-le avec un modèle. Les photos gardent la position que vous leur donnez.
Chaque photo va directement dans le stockage : demandez un téléversement, envoyez les octets par PUT à uploadUrl, puis terminez-le.
BATCH_ID=$(curl -s -X POST https://api.photofig.com/v1/batches \
-H "Authorization: Bearer pf_live_..." \
-H "Content-Type: application/json" \
-d '{ "name": "Spring arrivals" }' | jq -r '.id')
# For each photo: ask for an upload, PUT the bytes, complete it.
UPLOAD=$(curl -s -X POST "https://api.photofig.com/v1/batches/$BATCH_ID/uploads" \
-H "Authorization: Bearer pf_live_..." \
-H "Content-Type: application/json" \
-d '{ "filename": "boots.jpg", "contentType": "image/jpeg", "sizeBytes": 1842031, "position": 0 }')
curl -X PUT "$(echo "$UPLOAD" | jq -r '.uploadUrl')" \
-H "Content-Type: image/jpeg" --data-binary @boots.jpg
curl -X POST "https://api.photofig.com/v1/batches/$BATCH_ID/uploads/$(echo "$UPLOAD" | jq -r '.uploadId')/complete" \
-H "Authorization: Bearer pf_live_..."
curl -X POST "https://api.photofig.com/v1/batches/$BATCH_ID/process" \
-H "Authorization: Bearer pf_live_..." \
-H "Content-Type: application/json" \
-d '{ "templateId": "TEMPLATE_ID" }'Savoir quand un lot est terminé
Enregistrez une fois un webhook pour batch.completed au lieu d'interroger. PhotoFig l'appelle à la fin de chaque lot, avec l'ID du lot et le nombre de photos réussies ou en échec.
curl -X POST https://api.photofig.com/v1/webhooks \
-H "Authorization: Bearer pf_live_..." \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com/photofig/webhooks",
"events": ["batch.completed"]
}'{
"event": "batch.completed",
"eventId": "uuid",
"createdAt": "2026-10-06T12:00:00Z",
"data": {
"batchId": "uuid",
"status": "completed",
"totalItems": 12,
"completedItems": 12,
"failedItems": 0
}
}Quand batch.completed arrive, lisez le lot. Chaque photo terminée a un lien d'aperçu, jusqu'à 1024 pixels. Les détourages et crédits IA sont facturés comme dans l'application.
{
"id": "uuid",
"name": "Spring arrivals",
"status": "completed",
"templateName": "Cream catalog",
"totalItems": 2,
"completedItems": 2,
"failedItems": 0,
"resultsAvailableUntil": "2026-10-20T12:00:00Z",
"items": [
{
"id": "uuid",
"position": 0,
"filename": "boots.jpg",
"status": "completed",
"width": 3024,
"height": 4032,
"preview": {
"url": "https://...",
"width": 1024,
"height": 1024
}
}
]
}Télécharger les résultats
/v1/batches/{batch_id}/items/{item_id}/download/v1/batches/{batch_id}/download-urlTéléchargez chaque résultat en taille réelle au format d'export du modèle, ou tout le lot en ZIP. Chaque résultat compte une fois comme export, comme dans l'application ; le retélécharger est gratuit.
Partager les résultats
/v1/batches/{batch_id}/share/v1/batches/{batch_id}/share/v1/batches/{batch_id}/shareUn lien de partage est une page publique avec des aperçus avant/après et un téléchargement ZIP, sans connexion. Un lot a un seul lien : le redemander renvoie le même, et le révoquer y met fin aussitôt. Les téléchargements depuis la page comptent comme vos exports, et la page fonctionne jusqu'à availableUntil. Le partage nécessite un forfait payant.
curl -X POST "https://api.photofig.com/v1/batches/$BATCH_ID/share" \
-H "Authorization: Bearer pf_live_..."{
"url": "https://photofig.com/share/TOKEN",
"availableUntil": "2026-10-20T12:00:00Z",
"createdAt": "2026-10-06T12:05:00Z",
"downloadCount": 0
}Webhooks
Les webhooks permettent à PhotoFig d'avertir votre serveur quand une tâche API se termine, échoue ou est annulée, et quand un lot est terminé, sans que votre backend ait à interroger. Enregistrez une URL HTTPS sur un hôte public. Un point de terminaison reçoit les événements des tâches et lots créés avec les clés API de son propriétaire.
/v1/webhooks/v1/webhooks/v1/webhooks/{webhook_id}/v1/webhooks/{webhook_id}/v1/webhooks/{webhook_id}/v1/webhooks/{webhook_id}/testLes événements pris en charge sont webhook.test,job.completed,job.failed,job.cancelled, et batch.completed. Les événements de tâche utilisent l'ID de tâche renvoyé à la création de la retouche ; batch.completed contient l'ID du lot.
{
"event": "job.completed",
"eventId": "uuid",
"createdAt": "2026-07-15T10:15:23Z",
"data": {
"id": "api_edit_uuid",
"tool": "ai-shadows",
"status": "completed",
"resultUrl": "https://storage.example.com/signed-result-url",
"thumbnailUrl": "https://storage.example.com/signed-thumbnail-url",
"expiresAt": "2026-07-15T11:15:23Z"
}
}Vérifiez chaque livraison
Chaque requête contient PhotoFig-Webhook-Timestamp et PhotoFig-Webhook-Signature. Calculez avec le secret du point de terminaison un HMAC-SHA256 de l'horodatage, d'un point et du corps brut de la requête, puis comparez-le à la valeur qui suit v1=. Rejetez les horodatages de plus de quelques minutes. Le secret n'est affiché qu'à la création du point de terminaison.
import crypto from 'node:crypto';
// rawBody is the request body exactly as received, before JSON parsing.
export function verifyPhotoFigWebhook(headers, rawBody, secret) {
const timestamp = headers['photofig-webhook-timestamp'];
const signature = headers['photofig-webhook-signature'] ?? '';
if (Math.abs(Date.now() / 1000 - Number(timestamp)) > 300) return false;
const expected = 'v1=' + crypto
.createHmac('sha256', secret)
.update(`${timestamp}.${rawBody}`)
.digest('hex');
return signature.length === expected.length
&& crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected));
}Répondez avec n'importe quel statut 2xx en moins de 10 secondes. Les autres réponses sont relancées après 1 minute, 5 minutes, 30 minutes, 2 heures et 12 heures. PhotoFig-Webhook-Id reste identique d'une tentative à l'autre : utilisez-le pour ignorer les doublons. Les liens de téléchargement du contenu sont signés à chaque tentative et cessent de fonctionner à l'expiration du résultat.
Erreurs
Les réponses d'erreur contiennent un code stable lisible par machine et un message compréhensible. Utilisez le code pour adapter la logique du client.
{
"code": "invalid_request",
"message": "imageUrl or uploadSessionId is required"
}Codes courants
invalid_request- Un paramètre est manquant ou invalide ; le message précise lequel.
api_key_not_allowed- Une clé d'API a été utilisée sur une route hors de l'API publique.
api_access_disabled- Le forfait de l'espace de travail n'inclut pas l'accès à l'API.
insufficient_funds- Il ne reste ni crédits IA ni suppressions d'arrière-plan pour cet outil.
rate_limit_exceeded- Le quota horaire de requêtes est épuisé ; attendez Retry-After.
too_many_jobs- Trop de tâches sont en attente ou en cours ; réessayez quand les précédentes sont terminées.
tool_unavailable- Les workers de l'outil sont brièvement indisponibles ; réessayez sous peu.
webhook_limit_reached- Le propriétaire de la clé a atteint la limite de points de terminaison webhook pour cet espace de travail.
Durée de conservation des résultats
Les tâches d'API terminées restent visibles via GET /v1/jobs et GET /v1/jobs/{job_id}. La réponse d'état contient des liens resultUrl et thumbnailUrl signés tant que les résultats sont disponibles.
Les fichiers produits par l'API sont stockés séparément des fichiers importés et des créations de l'application. Ils n'apparaissent pas dans la bibliothèque.
Les enregistrements des tâches API ainsi que leurs fichiers d'entrée, résultats et miniatures sont conservés pendant 1 heure une fois la tâche terminée, échouée ou annulée. Le champ expiresAt indique l'heure de suppression prévue.
Utilisez DELETE /v1/jobs/{job_id} après avoir téléchargé les résultats dont vous n'avez plus besoin. Cela annule si possible le travail inachevé et supprime l'enregistrement de la tâche ainsi que les fichiers propres à l'API avant le nettoyage automatique.