API Veille
Monitoring récurrent de scrapes et pipelines, avec buckets de diff et signaux de réputation.
API Veille
L'API Veille gère les jobs de monitoring récurrents. Une veille rejoue un scrape source — ou un pipeline entier — à une cadence fixe, puis calcule un diff contre le run précédent pour faire ressortir ce qui a changé.
Voir Concepts de monitoring Veille pour le cycle de vie, l'ordonnancement et le modèle de diff.
Tous les endpoints sont sous /api/veille et requièrent une session authentifiée et active. Les réponses sont en JSON. La propriété de ressource est appliquée à chaque requête : un accès cross-user renvoie 404. Erreurs génériques : 401 (pas de session) et 404 (non trouvé / non propriétaire) ; les causes spécifiques sont en ligne.
Modèle de ressource
Un objet Veille expose les champs suivants :
| Champ | Type | Description |
|---|---|---|
id |
entier | Identifiant stable. |
name |
string | Libellé lisible (2–200 caractères). |
source_job_id |
string | null | Scrape source rejoué à chaque tick (exclusif avec source_pipeline_id). |
source_pipeline_id |
string | null | Pipeline source rejoué à chaque tick. |
frequency_days |
entier | Cadence en jours, entre 1 et 365. |
status |
string | active, paused ou deleted. |
next_run_at |
string (ISO8601) | Prochaine exécution planifiée. |
last_run_at |
string | null | Horodatage du dernier run terminé. |
last_run_job_id |
string | null | Id de job du dernier run. |
run_count |
entier | Total de runs réussis. |
created_at |
string (ISO8601) | Horodatage de création. |
Endpoints
Lister les veilles
GET /api/veille
Renvoie les veilles actives et en pause de l'appelant. Les entrées soft-deleted sont exclues.
Réponse 200 OK — { "items": [Veille, ...] }.
Créer une veille
POST /api/veille
Crée un monitor récurrent à partir d'un scrape ou pipeline terminé appartenant à l'appelant. Exactement un de source_job_id ou source_pipeline_id est requis.
Corps de requête
| Champ | Type | Requis | Notes |
|---|---|---|---|
name |
string | oui | 2–200 caractères. |
source_job_id |
string | un des | 8–64 caractères. |
source_pipeline_id |
string | un des | 8–64 caractères. |
frequency_days |
entier | oui | 1 ≤ valeur ≤ 365. |
{
"name": "Plombiers Lyon 3",
"source_job_id": "job_8f2c91a4",
"frequency_days": 7
}
Réponse 200 OK — la veille nouvellement créée.
Cause spécifique : 400 échec de validation (champs source manquants/doubles, source non possédée, source non terminée, fréquence invalide).
Récupérer une veille
GET /api/veille/{id}
Renvoie une veille appartenant à l'appelant. Les entrées soft-deleted renvoient 404.
Mettre à jour une veille
PATCH /api/veille/{id}
Patche les champs mutables. Les champs omis sont laissés inchangés.
Corps de requête
| Champ | Type | Notes |
|---|---|---|
name |
string | 2–200 caractères. |
frequency_days |
entier | 1 ≤ valeur ≤ 365. Reprogramme next_run_at. |
status |
string | active, paused ou deleted. |
{ "status": "paused", "frequency_days": 14 }
Réponse 200 OK — la veille mise à jour. Cause spécifique : 400 valeur de champ invalide.
Supprimer une veille
DELETE /api/veille/{id}
Soft-delete de la veille. L'enregistrement est conservé pour audit mais exclu de tous les endpoints de liste et n'est plus planifié.
Réponse 200 OK — { "ok": true }.
Runs
Un run est une exécution unique de la veille plus les statistiques de diff calculées contre le run précédent. Le premier run est un baseline (is_baseline: true) et n'a pas de compteurs de diff.
Lister les runs
GET /api/veille/{id}/runs
Renvoie l'historique des runs ordonné par computed_at descendant.
Réponse 200 OK
{
"items": [{
"id": 17,
"job_id": "job_b71e0d22",
"prev_job_id": "job_aa44e0f1",
"is_baseline": false,
"total_count": 312, "prev_total_count": 305,
"new_count": 9, "removed_count": 2,
"modified_count": 24, "unchanged_count": 279,
"computed_at": "2026-05-27T08:11:04Z",
"job_status": "done",
"job_completed_at": "2026-05-27T08:10:48Z"
}]
}
Récupérer un run
GET /api/veille/{id}/runs/{run_id}
Renvoie le run, incluant samples — previews plafonnés des lignes dans chaque bucket de diff.
Réponse 200 OK
{
"id": 17,
"job_id": "job_b71e0d22",
"is_baseline": false,
"new_count": 9,
"removed_count": 2,
"modified_count": 24,
"unchanged_count": 279,
"total_count": 312,
"computed_at": "2026-05-27T08:11:04Z",
"samples": {
"new": [{ "key": "...", "nom": "..." }],
"removed": [{ "key": "...", "nom": "..." }],
"modified": [{
"key": "...", "nom": "...",
"before": { "note": "4.3", "nb_avis": 42 },
"after": { "note": "3.8", "nb_avis": 51 },
"changed_fields": ["note", "nb_avis"]
}]
}
}
Catégories de signaux
Chaque run non-baseline classe chaque ligne du dataset dans exactement un bucket :
| Catégorie | Signification |
|---|---|
new |
Ligne présente dans le run courant, absente du précédent. |
removed |
Ligne présente dans le précédent, absente du courant (fermée/retirée). |
modified |
Ligne présente dans les deux runs avec au moins un champ tracké modifié. |
unchanged |
Ligne présente dans les deux runs, identique sur les champs trackés. |
Les compteurs sont exposés en new_count, removed_count, modified_count et unchanged_count. Les tableaux correspondants samples.{new,removed,modified} portent des previews plafonnés pour l'UI.
Le champ
removedest le bucket fermé/retiré : un enregistrement qui n'est plus listé à la source.
Signaux de réputation
Les signaux de réputation sont une vue dérivée du bucket modified d'un run. Ils isolent les lignes dont la réputation publique a bougé d'une manière critique pour l'outreach — typiquement des listings Google Maps dont la note a baissé ou dont le volume d'avis a explosé entre deux runs.
Logique de classement (vue haute)
Une ligne modifiée devient un signal quand au moins une condition est vraie :
- Chute de note — la note moyenne a baissé d'au moins
0.2point. - Surge d'avis — le nombre d'avis a augmenté d'au moins
3depuis le run précédent.
Chaque signal porte un score qui classe l'urgence. Les chutes de note plus larges dominent ; les surges d'avis contribuent un boost additif plus petit au-dessus d'un seuil de bruit bas volume. Les signaux sont retournés triés par score descendant. La pondération exacte est un détail d'implémentation susceptible d'évoluer ; ne pas dépendre des valeurs absolues, uniquement de l'ordre relatif.
Lister les signaux
GET /api/veille/{id}/runs/{run_id}/signals
Réponse 200 OK
{
"items": [{
"nom": "Garage du Centre",
"adresse": "12 rue Voltaire, 69003 Lyon",
"telephone": "+33 4 78 00 00 00",
"site_web": "https://...", "email": "contact@...",
"lien_google_maps": "https://maps.google.com/...",
"note_avant": 4.3, "note_apres": 3.8, "delta_note": -0.5,
"avis_avant": 42, "avis_apres": 51, "delta_avis": 9,
"score": 12.0
}],
"total": 1
}
Exporter les signaux
GET /api/veille/{id}/runs/{run_id}/signals.{fmt}
Diffuse la même liste classée comme fichier téléchargeable.
| Format | Media type | Extension |
|---|---|---|
csv |
text/csv; charset=utf-8 |
.csv |
json |
application/json |
.json |
xlsx |
application/vnd.openxmlformats-officedocument.spreadsheetml.sheet |
.xlsx |
La réponse pose Content-Disposition: attachment avec un nom de fichier de la forme signaux-reputation-veille-{id}-run-{run_id}.{fmt}.
Cause spécifique : 400 fmt non supporté (doit être csv, json, xlsx).