Capturia mesure ses publicités et la fréquentation du site avec le pixel Meta et Google Analytics. Tu peux refuser en tout temps. En savoir plus

EN

Events

2 endpoints

post/v1/events

Pousser 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_ip quand la limite IP (120 req/min) est atteinte, header X-RateLimit-Scope: ip. Limite par clé : 60 req/min (modulable par clé).
Scopes requis: events:ingest

Corps de requête

PropriétéTypeObligatoireDescription
eventstringobligatoireNom de l'événement, dans l'espace de noms du compte. Comparé tel quel (sensible à la casse) au nom configuré sur le déclencheur « Événement personnalisé » des automatisations.
contactEventIngestContactobligatoire—
payloadobjectoptionnelDonnées arbitraires de l'événement. Chaque clé de premier niveau est exposée aux messages des automatisations via {{event.<clé>}} (un objet imbriqué est sérialisé en JSON). Le contenu persisté est borné (nombre de clés, profondeur, taille totale).
custom_fieldsobjectoptionnelChamps personnalisés du contact, keyés par le name de la définition (même contrat que /v1/leads/capture). Une clé sans définition correspondante est ignorée silencieusement. Merge additif : la nouvelle valeur gagne sur collision.
source_labelstringoptionnelÉtiquette libre identifiant la source (affichée sur la fiche contact).

Responses

StatutDescription
200

Événement ingéré (status: ingested). enrolled_executions indique combien d'automatisations ont démarré ; 0 signifie qu'aucune automatisation active n'écoute ce nom d'événement — l'événement est quand même enregistré sur la fiche contact.

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 code : insufficient_scope (la clé ne possède pas le scope requis — details.required_scope) ou feature_not_available (l'API publique ou le module visé n'est pas inclus dans le forfait du compte — details.feature nomme la fonctionnalité, ex. public_api, quotes). Un refus de forfait est définitif pour la clé : inutile de réessayer, le compte doit changer de forfait.

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 Idempotency-Key a utilisé un payload différent, ou est encore en cours de traitement.

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 request_id au support.

Exemple de requête

curl -X POST 'https://api.capturia.io/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"
}'
post/v1/event-registrations

Inscrire une fiche à un événement

Inscrit une fiche existante du compte à un événement publié (webinaire, défi, sommet, événement en ligne). La personne reçoit ensuite les messages de l'événement, comme si elle s'était inscrite par sa page.

Une seule inscription par personne et par édition : un second appel pour la même fiche et la même édition rend la même inscription avec 200 et created: false, sans renvoyer la confirmation. Il met la langue à jour, et réinscrit une personne qui avait dit qu'elle ne viendrait pas ; une personne qui a demandé l'arrêt des messages le reste. L'appel est donc sûr à rejouer, sans en-tête Idempotency-Key.

Exige le module d'accompagnement d'événements du forfait (403 feature_not_available sinon) et le scope contacts:write.

Refus

  • 404 resource_not_found avec details.resource : contact (fiche absente, fusionnée ou d'un autre compte), event ou edition.
  • 422 business_rule_violation avec details.rule : event_not_published (brouillon), event_closed (événement archivé, édition annulée, ou aucune édition à venir), event_edition_ended (édition terminée).
  • 400 validation_error : corps invalide, ou event_id et event_slug tous deux présents ou tous deux absents.
Scopes requis: contacts:write

Corps de requête

PropriétéTypeObligatoireDescription
contact_idstringobligatoireFiche à inscrire.
event_idstringoptionnelIdentifiant de l'événement.
event_slugstringoptionnelAdresse de l'événement, telle qu'elle paraît dans son lien d'inscription.
edition_idstringoptionnelÉdition visée. Absente : la prochaine édition ouverte de l'événement, comme sur sa page d'inscription.
languagestringoptionnelLangue des messages. Absente : la première langue de l'événement.

Responses

StatutDescription
200

La fiche était déjà inscrite à cette édition ; la même inscription est rendue.

201

Inscription créée.

400

Validation des paramètres ou du body a échoué.

401

Clé API inconnue ou format invalide.

403

Refus d'autorisation. Deux causes, distinguées par code : insufficient_scope (la clé ne possède pas le scope requis — details.required_scope) ou feature_not_available (l'API publique ou le module visé n'est pas inclus dans le forfait du compte — details.feature nomme la fonctionnalité, ex. public_api, quotes). Un refus de forfait est définitif pour la clé : inutile de réessayer, le compte doit changer de forfait.

404

La ressource demandée n'existe pas (ou pas dans le scope du tenant).

415

Le header Content-Type est manquant ou non supporté pour cet endpoint.

422

La requête est syntaxiquement valide mais viole une règle métier.

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 request_id au support.

503

Service temporairement indisponible (maintenance, dépendance externe down, infra dégradée). Le client devrait retry avec backoff exponentiel.

Exemple de requête

curl -X POST 'https://api.capturia.io/v1/event-registrations' \
  -H 'Authorization: Bearer cap_live_<your-key>' \
  -H 'Content-Type: application/json' \
  -d '{
  "contact_id": "9b8a7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d",
  "event_slug": "defi-5-jours",
  "language": "fr"
}'