Events
1 endpoint
/v1/eventsPousser un événement personnalisé qui déclenche les automatisations
Webhook entrant générique par compte : une source externe (Zapier, Make,
n8n, un backend client, un outil tiers) pousse un événement nommé avec
ses données. Capturia résout le contact (external_id → phone →
email), enrichit sa fiche de façon non-destructive, remplit les champs
personnalisés mappés, enregistre l'événement sur la fiche, puis démarre
les automatisations dont le déclencheur « Événement personnalisé »
écoute ce nom d'événement — avec le payload disponible dans les
messages via {{event.<clé>}}.
Résolution du contact
Au moins un identifiant est requis (external_id, email ou phone).
Si aucun contact ne matche, une fiche minimale est créée — sauf si
contact.create_if_missing est false, auquel cas la requête répond
404 contact_not_found sans rien enregistrer. Si les identifiants ne
matchent qu'une fiche archivée, l'événement est enregistré dessus
(traçabilité) mais la fiche n'est pas modifiée et aucune automatisation
n'est enrôlée (contact_archived: true).
Consentement (Loi 25 / LCAP)
La réception d'un événement n'établit aucun consentement de communication. Un contact créé par ce chemin ne peut pas recevoir de SMS/courriel tant qu'un consentement n'est pas capté par un autre flux ; une automatisation déclenchée qui tenterait un envoi sans consentement est bloquée par les gardes du moteur d'exécution.
Signature HMAC optionnelle
En plus de la clé API, la requête peut porter une signature
X-Capturia-Signature: t=<unix>,v1=<hex> — HMAC-SHA256 de
${t}.${corps brut} calculée avec la clé API brute comme secret,
fenêtre anti-replay de 5 minutes. Dès que le header est présent, la
validation est stricte (fail-closed) : signature invalide = 401 invalid_signature. Sans le header, la clé API seule authentifie.
Idempotency
Le header Idempotency-Key est optionnel mais recommandé pour les
retries : une 2e requête avec la même clé et le même payload renvoie la
réponse d'origine sans ré-ingérer l'événement (stockage 24h ; payload
différent = 409 idempotency_conflict). Par ailleurs, l'enrôlement des
automatisations porte sa propre dédup de 5 minutes par contact et par
automatisation.
Codes d'erreur custom
- 429 —
rate_limited_ipquand la limite IP (120 req/min) est atteinte, headerX-RateLimit-Scope: ip. Limite par clé : 60 req/min (modulable par clé).
events:ingestRequest body
#/components/schemas/EventIngestPayload
Responses
| Status | Description |
|---|---|
200 | Événement ingéré ( |
400 | La requête est mal formée (header manquant, JSON invalide, paramètre invalide). |
401 | Clé API inconnue ou format invalide. |
403 | Refus d'autorisation. Deux causes, distinguées par |
404 | La ressource demandée n'existe pas (ou pas dans le scope du tenant). |
409 | Une requête précédente avec la même |
422 | Validation des paramètres ou du body a échoué. |
429 | Le quota de requêtes par fenêtre est dépassé pour cette clé API ou cet endpoint. |
500 | Erreur serveur inattendue. Toujours fournir le |
Example request
curl -X POST 'https://app.capturia.io/api/v1/events' \
-H 'Authorization: Bearer cap_live_<your-key>' \
-H 'Content-Type: application/json' \
-d '{
"event": "abandon_panier",
"contact": {
"external_id": "user-4821",
"external_source": "mon-backend",
"email": "[email protected]",
"first_name": "Alex"
},
"payload": {
"montant": 249.99,
"produit": "Forfait Pro",
"url_panier": "https://boutique.example.com/panier/abc123"
},
"custom_fields": {
"plan_vise": "pro"
},
"source_label": "Boutique en ligne"
}'