# API (`app/main.py`) ## `POST /analyze` ### Requête (`multipart/form-data`) | Champ | Type | Requis | Description | |---|---|---|---| | `image` | fichier | oui | photo du terminal de pompe (jpeg/png/bmp/webp/tiff) | | `fuel_price` | float | non | prix du litre configuré côté YELY — fait autorité sur celui lu à l'écran | | `driver_id` | string | non | identifiant chauffeur (issu du scan QR côté YELY) | | `pompiste_id` | string | non | identifiant pompiste | | `station_id` | string | non | identifiant station | Volontairement **pas** de paramètres techniques (seuil de confiance OCR, activer/désactiver la détection d'écran...) — contrairement au prototype précédent, ce endpoint n'expose que les champs métier attendus par le cahier des charges. ### Réponse (`200`) Voir `README.md` pour un exemple complet. Tous les champs correspondent au §13 du cahier des charges — voir `docs/POSTPROCESS_RULES.md` pour le détail du calcul de chaque valeur, `docs/ARCHITECTURE.md` pour le pipeline complet. ### Erreurs | Statut | Cas | |---|---| | `400` | type d'image non supporté, ou fichier illisible | | `500` | erreur interne inattendue pendant le traitement (journalisée dans `logs/api.log` avec la stack trace complète) | ## Chargement du modèle Le CRNN est chargé **une seule fois** au premier appel (singleton `_get_model()`), pas à chaque requête — le chargement prend 30-90s sur CPU. Conséquence pratique : **ne pas lancer `uvicorn --reload` en usage normal**, chaque rechargement de code redémarre le worker et donc le modèle. ## CORS `ALLOWED_ORIGINS` (variable d'environnement, origines séparées par des virgules) contrôle quels domaines peuvent appeler l'API depuis un navigateur — nécessaire car le frontend (Netlify) et l'API (Hugging Face Spaces) sont sur des domaines différents. Par défaut `"*"` (permissif, adapté à une démo) ; à restreindre au domaine Netlify réel en production. ## Journalisation Chaque appel écrit une ligne JSON dans `logs/api.log` : requête (sans l'image elle-même) + réponse complète. C'est la base du suivi de performance — voir `docs/MONITORING.md`. ## Traçabilité Chaque photo reçue est sauvegardée dans `photos/.jpg` et référencée dans la réponse (`photo_reference`) — nécessaire pour qu'un contrôle a posteriori (station, YELY) puisse revérifier une transaction contestée, et c'est aussi la matière première de la boucle d'apprentissage continu (`docs/MONITORING.md`). ## `POST /feedback` Correction a posteriori d'une transaction déjà traitée par `/analyze` — voir `docs/MONITORING.md` pour le fonctionnement complet de la boucle d'apprentissage continu. | Champ | Type | Requis | Description | |---|---|---|---| | `photo_reference` | string | oui | valeur renvoyée par `/analyze` (doit exister dans `photos/`) | | `corrected_prix` | float | non* | montant réellement correct | | `corrected_volume` | float | non* | volume réellement correct | | `corrected_prix_litre` | float | non* | prix du litre réellement correct | | `corrected_by` | string | non | identifiant de qui corrige (pompiste/station) | \* au moins un des trois champs `corrected_*` est requis. Réponses : `200` (`{"success": true, "feedback_id": "..."}`), `404` si `photo_reference` ne correspond à aucune photo connue, `400` si aucune correction n'est fournie. ## `GET /metrics` Aperçu agrégé des performances observées en production, calculé à la volée à partir de `logs/api.log` (pas de paramètre, pas d'état en mémoire) : `total_requests`, `success_rate`, `avg_confidence_score`, `blocking_causes`, `image_quality_distribution`. Voir `docs/MONITORING.md`. ## `GET /failures` Les `limit` (défaut 20) dernières transactions bloquées (`success=false`), les plus récentes en premier — alimente la section « Requêtes échouées » de `web/stats.html`. Chaque élément : `photo_reference`, `message`, `image_quality`, `detected_liters`, `detected_amount`, `fuel_price`, `confidence_score`, `transaction_datetime`. ## `GET /photos/{photo_reference}` Ressert l'image sauvegardée par `/analyze` sous ce `photo_reference` (sert l'affichage dans le tableau de bord et le formulaire de correction). `404` si la référence est inconnue. `photo_reference` est assaini côté serveur (`Path(...).name`) avant résolution sous `PHOTOS_DIR` — aucune traversée de répertoire possible même si la valeur contient `../`.