Webhooks & Intégration API
Intégrez CSWeb avec vos applications tierces pour piloter le breakout, gérer les logs et automatiser vos workflows.
CSWeb Community Platform permet deux types d'intégration :
- Webhooks entrants : CSPro → CSWeb (événements en temps réel)
- API sortante : Application tierce → CSWeb (pilotage du breakout sélectif, logs, monitoring)
Cas d'Usage
1. Piloter le Breakout depuis une Application Tierce
Déclenchez le breakout sélectif d'un dictionnaire spécifique depuis votre dashboard ou application de monitoring.
Exemple : Application de supervision qui lance automatiquement le breakout du dictionnaire MENAGE quand 1000 nouveaux questionnaires sont détectés.
2. Centraliser les Logs dans un SIEM
Envoyez les logs CSWeb vers votre système de monitoring externe (ELK Stack, Splunk, Datadog).
Exemple : Alertes automatiques sur échecs de breakout ou erreurs de synchronisation.
3. Intégration BI/Dashboard
Récupérez les métriques de collecte en temps réel pour alimenter vos dashboards Power BI, Tableau ou Grafana.
Exemple : Dashboard affichant le nombre de questionnaires par région, taux de synchronisation, progression du breakout.
Webhooks racine
CSWeb expose 4 endpoints PHP à la racine, pilotables depuis vos systèmes externes (Kairos, scripts cron, monitoring, BI). Tous partagent :
- Auth :
Authorization: Bearer $BREAKOUT_WEBHOOK_TOKEN - Format de réponse uniforme :
{ "success": true, "data": ... | null, "error": null, "meta": {...}? } { "success": false, "data": null, "error": { "code": "...", "message": "..." } } - Rate-limit : 60 requêtes / 60 secondes par couple (token, IP)
- Body POST max : 64 KB
| Endpoint | Méthode | Rôle | Doc |
|---|---|---|---|
/breakout-webhook.php | POST | Déclencher un breakout pour un dictionnaire | Voir ci-dessous |
/breakout-status-webhook.php | GET | Statut breakout par dictionnaire (paginé) | → détails |
/dictionary-schema-webhook.php | GET / POST | CRUD sur la configuration des cibles breakout | Voir ci-dessous |
/log-reader-webhook.php | GET | Lire les fichiers de log CSWeb | Voir ci-dessous |
Déclencher un breakout
curl -X POST http://csweb.example.com/breakout-webhook.php \
-H "Authorization: Bearer $BREAKOUT_WEBHOOK_TOKEN" \
-H "Content-Type: application/json" \
-d '{"dictionary": "MENAGE_DICT"}'Réponse (succès) :
{
"success": true,
"data": {
"dictionary": "MENAGE_DICT",
"exitCode": 0,
"output": "Processed 1500 cases…",
"stderr": "",
"durationMs": 45230,
"logFile": "MENAGE_DICT_20260321_103015-api.log"
},
"error": null
}output et stderr sont tronqués à 4 KB par défaut. Pour le contenu
complet, soit lire data.logFile via log-reader-webhook.php, soit poser
BREAKOUT_WEBHOOK_VERBOSE=1 côté serveur.
Lire le statut consolidé d'un breakout
Voir la page dédiée : Breakout Status Webhook.
Lister / lire les logs
# Lister les logs disponibles
curl -H "Authorization: Bearer $BREAKOUT_WEBHOOK_TOKEN" \
"http://csweb.example.com/log-reader-webhook.php?action=list"
# Lire les 200 dernières lignes d'un fichier
curl -H "Authorization: Bearer $BREAKOUT_WEBHOOK_TOKEN" \
"http://csweb.example.com/log-reader-webhook.php?file=ui.log&lines=200"Restrictions :
- Seuls les fichiers matchant
^[a-zA-Z0-9._-]+\.log$sont exposés. - Le fichier doit physiquement résider dans
var/logs/(pas de symlink échappant). linesborné à 5000.
Configurer la cible breakout d'un dictionnaire
# Enregistrer (ou mettre à jour) la cible — par dict_name OU dict_id
curl -X POST http://csweb.example.com/dictionary-schema-webhook.php \
-H "Authorization: Bearer $BREAKOUT_WEBHOOK_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"action": "register",
"dictionary_name": "MENAGE_DICT",
"host_name": "host.docker.internal",
"schema_name": "menage_breakout",
"schema_user_name": "csweb",
"schema_password": "<secret>"
}'
# Lire la config existante
curl -H "Authorization: Bearer $BREAKOUT_WEBHOOK_TOKEN" \
"http://csweb.example.com/dictionary-schema-webhook.php?action=list"
# Supprimer la config (par nom OU id)
curl -X POST http://csweb.example.com/dictionary-schema-webhook.php \
-H "Authorization: Bearer $BREAKOUT_WEBHOOK_TOKEN" \
-H "Content-Type: application/json" \
-d '{"action": "unregister", "dictionary_name": "MENAGE_DICT"}'Le schema_password est stocké chiffré (AES_ENCRYPT(?, 'cspro')) en base.
Configuration
Variable d'environnement
# .env (à la racine du projet)
BREAKOUT_WEBHOOK_TOKEN=<32+ octets aléatoires>Important : la variable est obligatoire. Si elle n'est pas définie, les webhooks répondent
500 server_misconfiguredau démarrage. Aucun token par défaut n'est codé en dur.
Pour générer une valeur solide :
openssl rand -hex 32Puis recréer le container csweb pour pick up la variable :
docker compose up -d --no-deps cswebCodes d'erreur
Tous les webhooks utilisent le même catalogue de codes (error.code) :
| HTTP | error.code | Cause |
|---|---|---|
| 400 | invalid_body | JSON invalide ou champs requis manquants |
| 400 | invalid_dictionary | Nom de dict ne matche pas ^[A-Z0-9_]+$ |
| 400 | invalid_filename | Nom de fichier log non conforme |
| 400 | invalid_action | Action inconnue |
| 401 | missing_token | Header Authorization absent ou mal formé |
| 401 | invalid_token | Token reçu ne correspond pas |
| 403 | file_not_readable | Fichier de log non lisible |
| 404 | dictionary_not_found | Dict inexistant |
| 404 | file_not_found | Fichier de log inexistant |
| 405 | method_not_allowed | Verbe HTTP non supporté |
| 413 | body_too_large | Body POST > 64 KB |
| 429 | rate_limited | Quota dépassé (header Retry-After fourni) |
| 500 | server_misconfigured | BREAKOUT_WEBHOOK_TOKEN non défini |
| 500 | process_failed | proc_open impossible |
| 500 | breakout_failed | Breakout terminé avec exit ≠ 0 |
| 500 | internal_error | Erreur DB / exception non spécifique |
HTTPS Recommandé
En production, exposer les webhooks uniquement via HTTPS (Let's Encrypt, reverse proxy, etc.). Le Bearer token transite en clair sur HTTP.
Customisation
Webhook Custom
Créer custom-webhook.php à la racine et réutiliser le helper partagé pour
hériter automatiquement de l'authentification, du rate-limit, du capping
de body et du format de réponse uniforme :
<?php
require_once __DIR__ . '/webhook_helper.php';
requireMethod(['POST']);
requireBearerToken();
$body = readJsonBody();
if (!$body || empty($body['dictionary'])) {
respondError('invalid_body', 'Missing "dictionary" in request body.', 400);
}
// Logique custom : envoyer une notification Slack
$slack = 'https://hooks.slack.com/services/YOUR/WEBHOOK';
$ch = curl_init($slack);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode(['text' => "New case in {$body['dictionary']}"]));
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
curl_exec($ch);
respondSuccess(['notified' => true]);Monitoring
Webhook Deliveries
Tracker succès/échecs :
CREATE TABLE webhook_deliveries (
id SERIAL PRIMARY KEY,
webhook_name VARCHAR(50),
event VARCHAR(50),
status VARCHAR(20),
response_time INT,
created_at TIMESTAMP DEFAULT NOW()
);Metrics
-- Taux de succès
SELECT
webhook_name,
COUNT(*) as total,
SUM(CASE WHEN status = 'success' THEN 1 ELSE 0 END) as success,
AVG(response_time) as avg_response_ms
FROM webhook_deliveries
GROUP BY webhook_name;Troubleshooting
Webhook Non Reçu
Vérifier :
# Firewall
curl http://your-server/breakout-webhook.php
# Logs Nginx/Apache
tail -f /var/log/nginx/access.log
# Logs CSPro (côté client)Token Mismatch (401)
# Vérifier le token côté serveur CSWeb
docker exec csweb-app printenv BREAKOUT_WEBHOOK_TOKEN
# Vérifier le token côté client (.env de Kairos / variable d'environnement
# de votre intégration). Les deux doivent être strictement identiques.Réponse attendue en cas de mismatch :
{
"success": false,
"data": null,
"error": { "code": "invalid_token", "message": "Invalid token." }
}Timeout
Si webhook prend trop de temps :
// Répondre immédiatement
http_response_code(202);
echo json_encode(['status' => 'accepted']);
// Traitement async
fastcgi_finish_request();
exec("php process-breakout.php {$dictionary} > /dev/null 2>&1 &");