Référence API complète pour le service de Traitement d'Images Asynchrone WXO.
📚 Documentation Associée : Démarrage : README.md · Configuration : CONFIGURATION.md · Conception : ARCHITECTURE.md · Intégration WXO : orchestrate-tools/README.md
Production (IBM Code Engine) :
BASE_URL="https://wxo-fastapi-callback.264onkwcgnav.eu-de.codeengine.appdomain.cloud"
# Optionnel (si WORKSHOP_TOKEN configuré)
export WORKSHOP_TOKEN="votre-token-ici"
# Quick start - vérifier que le service répond
curl "${BASE_URL}/health"Le service est exposé publiquement en HTTPS afin d'être accessible depuis watsonx Orchestrate (SaaS).
Toute la configuration est gérée via des variables d'environnement. Voir CONFIGURATION.md pour le guide de configuration complet.
Validation rapide :
# Sans token
curl "${BASE_URL}/cos/config"
# Avec WORKSHOP_TOKEN (si configuré)
curl "${BASE_URL}/cos/config" -H "x-workshop-token: ${WORKSHOP_TOKEN}"Par défaut, aucune authentification n'est requise.
⚠️ AVERTISSEMENT SÉCURITÉ - Endpoint Public :
- Sans authentification, n'importe qui peut appeler l'API et déclencher des coûts OpenAI/COS
WORKSHOP_TOKENest un garde-fou minimal, pas une vraie sécurité- En production : Implémentez auth + rate limiting + allowlist IP (si possible)
- Surveillez les coûts et l'utilisation pour détecter les abus
Workshop guard (optionnel)
Si la variable WORKSHOP_TOKEN est définie, les endpoints suivants exigent le header :
x-workshop-token: <WORKSHOP_TOKEN>Endpoints protégés par WORKSHOP_TOKEN :
POST /process-image-async-b64POST /process-image-asyncPOST /batch-process-imagesGET /cos/config
Endpoints non protégés :
GET /health
En production, implémentez un mécanisme d'authentification approprié (API keys, OAuth 2.0, JWT, etc.).
callbackUrl est requis uniquement pour :
POST /process-image-async-b64POST /process-image-asyncPOST /batch-process-images
Exemple complet des en-têtes requis :
Content-Type: application/json
callbackUrl: https://votre-callback-endpoint.com/callbackImportant :
callbackUrlest sensible à la casse (pascallbackurlouCallbackUrl)- L'URL de callback doit être accessible depuis l'instance Code Engine (généralement HTTPS public en environnement SaaS)
Les endpoints /health et /cos/config ne nécessitent pas ces headers.
Vérifier si le service fonctionne.
Endpoint : GET /health
Réponse :
{
"ok": true,
"mode": "workshop",
"callback_rewrite_enabled": false,
"max_concurrent_jobs": 10,
"callback_retries": 3,
"fallback_single_enabled": true,
"workshop_token_enabled": false
}Codes de Statut :
200 OK- Le service est opérationnel
Obtenir la configuration actuelle de Cloud Object Storage.
Endpoint : GET /cos/config
Réponse :
{
"endpoint": "https://s3.eu-de.cloud-object-storage.appdomain.cloud",
"region": "eu-de",
"input_bucket": "input-images",
"output_bucket": "wxo-images",
"input_prefix": "",
"output_prefix": "results/batch",
"presign_expires": 900
}Codes de Statut :
200 OK- Configuration récupérée avec succès
Traiter une seule image et retourner le résultat sous forme de données encodées en base64.
Endpoint : POST /process-image-async-b64
En-têtes :
Content-Type: application/json
callbackUrl: https://votre-callback-endpoint.com/callbackHeader optionnel (si WORKSHOP_TOKEN configuré) :
x-workshop-token: <WORKSHOP_TOKEN>Corps de la Requête :
{
"prompt": "ajoute un chien à l'image",
"filename": "burger.jpeg",
"image_base64": "iVBORw0KGgoAAAANSUhEUgAA..."
}Schéma de Requête :
| Champ | Type | Requis | Description |
|---|---|---|---|
prompt |
string | Oui | Instruction en langage naturel pour la modification d'image |
filename |
string | Non | Nom de fichier original (pour corrélation/suivi) |
image_base64 |
string | Oui | Image encodée en Base64 (sans préfixe data:) |
Réponse Immédiate :
{
"accepted": true,
"job_id": "550e8400-e29b-41d4-a716-446655440000"
}Codes de Statut :
202 Accepted- Job accepté et traitement démarré500 Internal Server Error- Erreur de configuration (clés API manquantes, etc.)
Payload de Callback (Succès) :
{
"status": "completed",
"job_id": "550e8400-e29b-41d4-a716-446655440000",
"filename": "burger.jpeg",
"result_image_base64": "iVBORw0KGgoAAAANSUhEUgAA...",
"result_mime_type": "image/png"
}Note : Le champ
statuspeut valoir :completed|failed
Payload de Callback (Échec) :
{
"status": "failed",
"job_id": "550e8400-e29b-41d4-a716-446655440000",
"filename": "burger.jpeg",
"error": "ValueError: image_base64 invalide (base64 attendu, sans préfixe data:...)"
}Traiter une seule image et stocker le résultat dans IBM Cloud Object Storage.
Endpoint : POST /process-image-async
En-têtes :
Content-Type: application/json
callbackUrl: https://votre-callback-endpoint.com/callbackHeader optionnel (si WORKSHOP_TOKEN configuré) :
x-workshop-token: <WORKSHOP_TOKEN>Corps de la Requête :
{
"prompt": "rendre l'arrière-plan transparent",
"filename": "product.png",
"image_base64": "iVBORw0KGgoAAAANSUhEUgAA..."
}Schéma de Requête :
| Champ | Type | Requis | Description |
|---|---|---|---|
prompt |
string | Oui | Instruction en langage naturel pour la modification d'image |
filename |
string | Non | Nom de fichier original (pour corrélation/suivi) |
image_base64 |
string | Oui | Image encodée en Base64 (sans préfixe data:) |
Réponse Immédiate :
{
"accepted": true,
"job_id": "550e8400-e29b-41d4-a716-446655440000"
}Codes de Statut :
202 Accepted- Job accepté et traitement démarré500 Internal Server Error- Erreur de configuration
Payload de Callback (Succès) :
{
"status": "completed",
"job_id": "550e8400-e29b-41d4-a716-446655440000",
"filename": "product.png",
"object_key": "results/550e8400-e29b-41d4-a716-446655440000/product_modified.png",
"result_url": "https://s3.eu-de.cloud-object-storage.appdomain.cloud/wxo-images/results/...",
"expires_in": 900
}Note : Le champ
statuspeut valoir :completed|failed
Payload de Callback (Échec) :
{
"status": "failed",
"job_id": "550e8400-e29b-41d4-a716-446655440000",
"filename": "product.png",
"error": "RuntimeError: COS put_object failed: ClientError: ..."
}Traiter toutes les images d'un bucket/préfixe COS avec la même instruction.
Endpoint : POST /batch-process-images
En-têtes :
Content-Type: application/json
callbackUrl: https://votre-callback-endpoint.com/callbackHeader optionnel (si WORKSHOP_TOKEN configuré) :
x-workshop-token: <WORKSHOP_TOKEN>Corps de la Requête :
{
"prompt": "rendre l'image plus belle"
}Schéma de Requête :
| Champ | Type | Requis | Description |
|---|---|---|---|
prompt |
string | Oui | Instruction en langage naturel appliquée à toutes les images |
Réponse Immédiate :
{
"accepted": true,
"job_id": "550e8400-e29b-41d4-a716-446655440000"
}Codes de Statut :
202 Accepted- Job accepté et traitement démarré500 Internal Server Error- Erreur de configuration
Payload de Callback (Succès) :
{
"status": "completed",
"job_id": "550e8400-e29b-41d4-a716-446655440000",
"total_files": 5,
"processed": 5,
"failed": 0,
"fallback_local": 0,
"total_files_processed": 5,
"duration_seconds": 12.345,
"output_bucket": "wxo-images",
"output_prefix": "results/batch/550e8400-e29b-41d4-a716-446655440000/",
"errors": []
}Payload de Callback (Succès avec Fallback, sans échec) :
{
"status": "completed",
"job_id": "550e8400-e29b-41d4-a716-446655440000",
"total_files": 5,
"processed": 5,
"failed": 0,
"fallback_local": 2,
"total_files_processed": 5,
"duration_seconds": 15.678,
"output_bucket": "wxo-images",
"output_prefix": "results/batch/550e8400-e29b-41d4-a716-446655440000/",
"errors": [
"demo/image1.png: OpenAI billing limit -> fallback local applied",
"demo/image2.jpg: OpenAI billing limit -> fallback local applied"
]
}Note : Le statut reste
completedtant quefailed = 0, même sifallback_local > 0.
Payload de Callback (Échec) :
{
"status": "failed",
"job_id": "550e8400-e29b-41d4-a716-446655440000",
"total_files": 0,
"processed": 0,
"failed": 0,
"fallback_local": 0,
"duration_seconds": 0.123,
"output_bucket": "wxo-images",
"output_prefix": "results/batch/550e8400-e29b-41d4-a716-446655440000/",
"errors": [],
"error": "RuntimeError: Missing env var: COS_INPUT_BUCKET"
}Schéma de Réponse Callback :
| Champ | Type | Description |
|---|---|---|
status |
string | Statut du job : completed, completed_with_errors, ou failed |
job_id |
string | Identifiant unique du job (UUID) |
total_files |
integer | Nombre total d'images trouvées dans le bucket d'entrée |
processed |
integer | Nombre d'images ayant produit une sortie dans le bucket de destination (OpenAI + fallback local) |
failed |
integer | Images n'ayant produit aucune sortie (inclut les échecs de traitement et les échecs d'upload COS) |
fallback_local |
integer | Nombre d'images traitées via fallback local (incluses dans processed) |
total_files_processed |
integer | Égal à processed (champ conservé pour compatibilité avec le schéma OpenAPI/WXO) |
duration_seconds |
float | Temps de traitement total en secondes |
output_bucket |
string | Bucket COS contenant les résultats |
output_prefix |
string | Chemin du dossier contenant les images traitées |
errors |
array | Liste des messages d'erreur (max 20) |
error |
string | Message d'erreur fatale (présent uniquement si status est failed) |
total_files
Nombre total d'images trouvées dans le bucket d'entrée.
processed
Nombre d'images ayant produit une sortie valide dans le bucket de destination (OpenAI + fallback local).
fallback_local
Nombre d'images traitées via le fallback local suite à l'erreur billing_hard_limit_reached.
Ces images sont incluses dans processed.
failed
Nombre d'images n'ayant produit aucune sortie (échec OpenAI + fallback + upload).
total_files_processed
Égal à processed (champ conservé pour compatibilité avec le schéma OpenAPI importé dans WXO).
📊 Clarification des métriques : Dans cette implémentation,
processedcompte les images ayant produit une sortie dans COS (OpenAI ou fallback). Le champfallback_localprécise combien en fallback. Le champtotal_files_processedest conservé pour compatibilité et vautprocessed.
completed
Aucune image en échec (failed = 0).
completed_with_errors
Au moins une image en échec (failed > 0).
Important : L'utilisation du fallback local n'entraîne pas à elle seule le statut completed_with_errors.
failed
Erreur système ou configuration empêchant le traitement du lot (identifiants manquants, noms de bucket invalides, erreur critique).
Note : Pour les jobs par lot, le champ
statuspeut valoir :completed|completed_with_errors|failed
duration_seconds
Temps total pris pour traiter l'ensemble du lot, mesuré en secondes. Cela inclut :
- Listage des fichiers dans le bucket d'entrée
- Traitement de chaque image (appels API OpenAI ou fallback)
- Téléchargement des résultats vers le bucket de sortie
- Génération du payload de callback
Utilisez cette métrique pour estimer le temps de traitement pour les futurs lots et optimiser les tailles de lot.
Pour l'intégration complète dans watsonx Orchestrate (import des outils YAML, workflows JSON, configuration, bonnes pratiques), consultez :
Le payload de callback doit contenir exactement les champs déclarés dans la spec OpenAPI de l'outil.
WXO rejette les callbacks qui :
- Contiennent des champs supplémentaires non déclarés dans le YAML
- Ont des types de données incorrects
- Manquent des champs requis
Important :
- L'ordre des champs dans le JSON n'a pas d'importance, mais l'ensemble des champs et les types doivent correspondre
- Si vous ajoutez des champs de debug (ex:
trace_id,debug), vous devez également les ajouter au schéma OpenAPI dans les fichiersorchestrate-tools/*.yaml - Le serveur envoie les callbacks en JSON (généralement
Content-Type: application/json)
Codes de succès :
200 OK- Endpoints de santé et configuration202 Accepted- Job asynchrone accepté et démarré
Codes d'erreur :
401 Unauthorized- Token manquant ou invalide (siWORKSHOP_TOKENconfiguré)500 Internal Server Error- Erreur de configuration serveur (variables d'environnement manquantes, etc.)
Note : FastAPI peut également retourner
422 Unprocessable Entitypour les erreurs de validation de payload (champs manquants, types incorrects).
Configuration Manquante :
{
"detail": "Variable d'environnement manquante : OPENAI_API_KEY"
}Base64 Invalide :
{
"status": "failed",
"job_id": "...",
"error": "ValueError: image_base64 invalide (base64 attendu, sans préfixe data:...)"
}Limite de Facturation OpenAI : Quand la limite de facturation OpenAI est atteinte, le système bascule automatiquement vers le traitement local. Le callback inclura :
{
"fallback_local": 1,
"errors": ["demo/image.png: OpenAI billing limit -> fallback local applied"]
}Note : Le fallback local peut aussi s'appliquer sur les endpoints single image si
fallback_single_enabled=true(voir/health), uniquement surbilling_hard_limit_reached.
Actuellement, aucune limitation de débit n'est implémentée. Pour la production :
- Implémenter une limitation de débit par client/clé API
- Considérer un traitement basé sur file d'attente pour les opérations par lot
- Surveiller l'utilisation et les coûts de l'API OpenAI
Encodage Base64 :
# macOS
export B64=$(base64 -i image.jpg | tr -d '\n')
# Linux (GNU coreutils)
export B64=$(base64 -w 0 image.jpg)
# Alternative universelle (si -w ou -i non disponible)
export B64=$(base64 image.jpg | tr -d '\n')Sans token :
curl -X POST "${BASE_URL}/process-image-async-b64" \
-H "Content-Type: application/json" \
-H "callbackUrl: https://votre-callback-endpoint.com/callback" \
-d "{
\"prompt\": \"ajoute un coucher de soleil en arrière-plan\",
\"filename\": \"image.jpg\",
\"image_base64\": \"$B64\"
}"Avec WORKSHOP_TOKEN (si activé) :
curl -X POST "${BASE_URL}/process-image-async-b64" \
-H "Content-Type: application/json" \
-H "callbackUrl: https://votre-callback-endpoint.com/callback" \
-H "x-workshop-token: $WORKSHOP_TOKEN" \
-d "{
\"prompt\": \"ajoute un coucher de soleil en arrière-plan\",
\"filename\": \"image.jpg\",
\"image_base64\": \"$B64\"
}"Sans token :
curl -X POST "${BASE_URL}/batch-process-images" \
-H "Content-Type: application/json" \
-H "callbackUrl: https://votre-callback-endpoint.com/callback" \
-d '{"prompt": "améliore les couleurs et la luminosité"}'Avec WORKSHOP_TOKEN (si activé) :
curl -X POST "${BASE_URL}/batch-process-images" \
-H "Content-Type: application/json" \
-H "callbackUrl: https://votre-callback-endpoint.com/callback" \
-H "x-workshop-token: $WORKSHOP_TOKEN" \
-d '{"prompt": "améliore les couleurs et la luminosité"}'- Utiliser HTTPS en production
- Implémenter l'idempotence (le même job_id peut être réessayé)
- Retourner
200 OKrapidement (< 5 secondes) - Traiter les données de callback de manière asynchrone si nécessaire
# Correct : base64 sans préfixe data:
base64 -i image.jpg | tr -d '\n'
# Incorrect : inclut le préfixe data:
# data:image/jpeg;base64,iVBORw0...- Commencer avec de petits lots pour tester
- Surveiller
duration_secondspour optimiser la taille du lot - Vérifier le tableau
errorspour les échecs partiels - Suivre le compte
fallback_localpour la disponibilité d'OpenAI
- Les URLs expirent après le temps configuré (par défaut : 900 secondes)
- Télécharger les résultats avant l'expiration
- Stocker
object_keypour régénérer les URLs si nécessaire
Swagger UI :
${BASE_URL}/docs
ReDoc :
${BASE_URL}/redoc
- README.md - Démarrage rapide et configuration
- CONFIGURATION.md - Variables d'environnement
- ARCHITECTURE.md - Architecture technique
- orchestrate-tools/README.md - Intégration watsonX Orchestrate