EN
Copied
API

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 removed est 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 :

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).