Files
Imago/docs/API_GUIDE.md
T
bruno ae072dba26
CI / Lint & Format (push) Failing after 8s
CI / Tests (push) Has been skipped
CI / Security Scan (push) Failing after 9s
CI / Docker Build (push) Has been skipped
Update official docs: API guide v2.0, architecture with new components
2026-06-22 20:34:10 -04:00

201 lines
7.3 KiB
Markdown

# Guide d'utilisation de l'API Imago
Bienvenue dans la documentation officielle de l'API REST d'Imago v2.0.0.
**Note :** Tous les endpoints sont servis sous le préfixe `/api/v1/`.
## Sommaire
- [Authentification](#-authentification)
- [Scopes (Permissions)](#-scopes-permissions)
- [Plans et Rate Limiting](#-plans-et-rate-limiting)
- [Multi-tenancy et Isolation](#-multi-tenancy-et-isolation)
- [Gestion des Clients (Admin)](#-gestion-des-clients-admin)
- [Référence des Endpoints](#-reference-des-endpoints)
- [Gestion des Images](#-gestion-des-images)
- [Intelligence Artificielle](#-intelligence-artificielle)
- [Administration](#-administration-admin)
- [Dead Letter Queue](#-dead-letter-queue-admin)
- [Santé et Status](#-sante-et-status)
- [WebSocket (Temps Réel)](#-websocket-temps-reel)
- [Exemples Rapides](#-exemples-rapides)
---
## Authentification
Tous les endpoints (sauf `/health`, `/`, `/metrics`) nécessitent une clé API.
```
Authorization: Bearer VOTRE_CLE_API
```
Ou via le header alternatif : `X-API-Key: VOTRE_CLE_API`
> La clé API est hashée en SHA-256 + pepper (SECRET_KEY) avant stockage. Les comparaisons sont timing-safe.
### Clé Master Admin
Définie par `ADMIN_API_KEY` dans `.env`. Cette clé spéciale a tous les droits sans être en base de données.
---
## Scopes (Permissions)
| Scope | Accès |
|---|---|
| `images:read` | Lister, voir détails, EXIF, OCR, AI, tags |
| `images:write` | Uploader, relancer le pipeline |
| `images:delete` | Supprimer des images |
| `ai:use` | Résumé d'URL, rédaction de tâches |
| `admin` | Gérer clients, voir stats, DLQ, docs |
Les scopes sont validés à la création du client — les valeurs invalides sont rejetées.
---
## Plans et Rate Limiting
Les limites sont dynamiques par plan et isolées par client. Support Redis pour la persistence.
| Plan | Uploads/h | AI req/h |
|---|---|---|
| `free` | 20 | 50 |
| `standard` | 100 | 200 |
| `premium` | 500 | 1000 |
Config : `RATE_LIMIT_STORAGE_URL=redis://redis:***@## Gestion des Clients (Admin)
```bash
# Créer un client
curl -X POST http://localhost:8000/api/v1/auth/clients \
-H "Authorization: Bearer *** \
-H "Content-Type: application/json" \
-d '{"name":"App Mobile","scopes":["images:read","images:write","ai:use"],"plan":"standard"}'
# Rotation de clé
curl -X POST http://localhost:8000/api/v1/auth/clients/{id}/rotate-key \
-H "Authorization: Bearer ***
```
> La clé API n'est affichée qu'une seule fois à la création. Stockez-la immédiatement.
---
## Multi-tenancy et Isolation
- Chaque client voit uniquement ses propres images (filtrage `WHERE client_id = X`)
- Les IDs sont globaux mais l'accès est vérifié → un client B qui tente l'ID du client A reçoit `404`
- Fichiers stockés dans `uploads/{client_id}/` et `thumbnails/{client_id}/`
---
## Reference des Endpoints
### Gestion des Images
| Méthode | Endpoint | Scope | Description |
|---|---|---|---|
| `POST` | `/api/v1/images/upload` | `images:write` | Upload (multipart) + lancement pipeline AI |
| `GET` | `/api/v1/images` | `images:read` | Lister (pagination, filtres tag/status/search) |
| `GET` | `/api/v1/images/{id}` | `images:read` | Détail complet (EXIF + OCR + AI) |
| `GET` | `/api/v1/images/{id}/status` | `images:read` | Statut du pipeline (pending→done/error) |
| `GET` | `/api/v1/images/{id}/exif` | `images:read` | Métadonnées EXIF + GPS |
| `GET` | `/api/v1/images/{id}/ocr` | `images:read` | Texte extrait par OCR |
| `GET` | `/api/v1/images/{id}/ai` | `images:read` | Description AI + tags + tokens consommés |
| `POST` | `/api/v1/images/{id}/reprocess` | `images:write` | Relancer le pipeline AI |
| `DELETE` | `/api/v1/images/{id}` | `images:delete` | Supprimer image + fichiers |
| `GET` | `/api/v1/images/{id}/download-url` | `images:read` | URL signée temporaire (fichier original) |
| `GET` | `/api/v1/images/{id}/thumbnail-url` | `images:read` | URL signée temporaire (thumbnail) |
| `GET` | `/api/v1/images/tags/all` | `images:read` | Tous les tags uniques du client |
**Recherche :** `GET /api/v1/images?search=motcle&tag=nature&status=done&page=1&page_size=20`
### Intelligence Artificielle
| Méthode | Endpoint | Scope | Description |
|---|---|---|---|
| `POST` | `/api/v1/ai/summarize` | `ai:use` | Résumé AI d'une URL (scraping + résumé + tags) |
| `POST` | `/api/v1/ai/draft-task` | `ai:use` | Génération de tâche structurée |
L'AI utilise le provider configuré (Gemini ou OpenRouter) avec circuit breaker : timeout configurable (`AI_REQUEST_TIMEOUT`) et retry exponentiel (`AI_MAX_RETRIES`).
### Administration (Admin)
| Méthode | Endpoint | Description |
|---|---|---|
| `GET` | `/admin/api/stats` | Stats globales (images, stockage, tokens, clients) |
| `GET` | `/admin/api/clients` | Liste des clients |
| `POST` | `/admin/api/clients/{id}/toggle` | Activer/désactiver un client |
| `POST` | `/admin/api/clients/{id}/reset-quota` | Remettre le quota à zéro |
| `GET` | `/admin/api/queue/status` | File d'attente ARQ (pending + dead jobs) |
| `GET` | `/admin/api/docs` | Liste des documents disponibles |
| `GET` | `/admin/api/docs/{filename}` | Contenu d'un document |
| `POST` | `/api/v1/auth/clients` | Créer un client (retourne la clé) |
| `GET` | `/api/v1/auth/clients` | Lister tous les clients |
| `PATCH` | `/api/v1/auth/clients/{id}` | Modifier un client |
| `DELETE` | `/api/v1/auth/clients/{id}` | Désactiver un client |
### Dead Letter Queue (Admin)
Jobs échoués après `PIPELINE_MAX_RETRIES` tentatives.
| Méthode | Endpoint | Description |
|---|---|---|
| `GET` | `/admin/api/queue/dead?limit=50` | Lister les jobs morts |
| `POST` | `/admin/api/queue/dead/{index}/retry` | Relancer un job mort |
| `DELETE` | `/admin/api/queue/dead` | Vider la DLQ |
### Santé et Status
Endpoints publics (pas d'authentification).
| Méthode | Endpoint | Description |
|---|---|---|
| `GET` | `/` | Version et statut |
| `GET` | `/health` | Santé (AI, OCR, provider) |
| `GET` | `/health/detailed` | Diagnostic complet (BDD, Redis, ARQ, MinIO, OCR, AI, worker) |
| `GET` | `/metrics` | Métriques Prometheus |
### WebSocket (Temps Réel)
| Endpoint | Auth | Description |
|---|---|---|
| `ws://host/ws/pipeline/{image_id}?token=API_KEY` | API Key | Événements live du pipeline + buffer 60s |
| `ws://host/ws/admin/monitor?token=ADMIN_KEY` | Admin | Monitoring global de tous les pipelines |
---
## Exemples Rapides
### Upload + suivi pipeline (Python)
```python
import httpx, asyncio, websockets, json
API = "http://localhost:8000"
KEY = "ma_cle_api"
headers = {"Authorization": f"Bearer {KEY}"}
async def main():
# Upload
files = {"file": open("photo.jpg", "rb")}
r = httpx.post(f"{API}/api/v1/images/upload", files=files, headers=headers)
img = r.json()
print(f"Uploaded: {img['id']}")
# Suivi WebSocket du pipeline
async with websockets.connect(
f"ws://localhost:8000/ws/pipeline/{img['id']}?token={KEY}"
) as ws:
async for msg in ws:
event = json.loads(msg)
print(f"Pipeline: {event['event']}")
if event["event"] in ("pipeline.done", "pipeline.error"):
break
# Résultat final
detail = httpx.get(f"{API}/api/v1/images/{img['id']}/ai", headers=headers).json()
print(f"Description: {detail['description']}")
print(f"Tags: {detail['tags']}")
asyncio.run(main())
```