ENFR
API, intégration et exploitation

Un contrat avant le code, une production sans main humaine

Tout ce que fait la console web se fait aussi par l’API, et sous les mêmes autorisations. Le contrat est écrit avant l’implémentation, publié, et comparé à chaque intégration ; la manière dont le logiciel arrive en production fait partie de la conformité.

Contrat et conventions

Rien n’est implémenté avant d’être décrit. Le contrat est la source de vérité des consommateurs.

  • Tout est une ressource à identifiant opaque préfixé ; aucun identifiant séquentiel n’est exposé.
  • Pagination par curseur, jamais par décalage : une page reste stable même si la collection bouge.
  • Créations idempotentes : une clé d’idempotence rejouée pendant vingt-quatre heures rend la réponse d’origine, sans effet de bord.
  • Erreurs au format RFC 9457, avec un code métier stable et un identifiant de requête que l’on retrouve dans le journal d’audit.
  • Dates en ISO 8601, en temps universel, partout.
  • Un espace ne s’indique jamais en paramètre : il est déduit de la clé. Une ressource d’un autre espace est introuvable.
GET /v1/contacts/ctc_…
Authorization: Bearer rt_live_…   # rôle de plateforme

HTTP/1.1 404 Not Found
Content-Type: application/problem+json

{
  "type": "…/errors/not_found",
  "title": "Resource not found",
  "status": 404,
  "code": "not_found",
  "request_id": "req_3f2a…"
}

# Un refus se dit « introuvable », jamais
# « interdit ». Il est écrit au journal
# d’audit ; aucune lecture ne l’est,
# puisqu’il n’y en a pas eu.
Ce que garantit une clé d’idempotence
  • Le même appel rejoué avec la même clé rend la réponse d’origine, à l’identique, pendant vingt-quatre heures — sans créer une seconde ressource ni déclencher un second envoi.
  • Le même appel rejoué avec un corps différent est refusé : la clé engage la requête, pas seulement l’intention.
  • Deux appels concurrents portant la même clé ne produisent qu’un seul effet ; le second attend le résultat du premier.
  • Passé le délai, la clé est oubliée : une réutilisation ultérieure est une nouvelle requête.

Cinq appels jusqu’au premier contact

Le chemin le plus court entre un formulaire de collecte et un premier message parti.

  1. Créer une liste — le point d’entrée des contacts et le déclencheur le plus courant.
  2. Créer un template — le lien de désinscription est obligatoire pour un contenu marketing ; le domaine expéditeur doit être vérifié.
  3. Créer et activer un parcours — envoi, attente, condition, envoi…
  4. Pousser le contact avec ses actes de consentement et son inscription, en un seul appel.
  5. Lire son état — statut, listes, enrôlements, dernier événement.
PUT /v1/contacts
Authorization: Bearer rt_live_…
Idempotency-Key: 7f1c…

{
  "email": "contact@example.com",
  "first_name": "Camille",
  "consents": [
    { "purpose": "marketing_email", "status": "granted",
      "at": "2026-09-19T14:32:00Z", "source": "form:landing",
      "proof_url": "https://proofs.example.com/abc" }
  ],
  "subscriptions": [{ "list_id": "lst_…" }]
}

→ 201  le contact entre dans le parcours ;
       le premier message part en moins d’une minute.

Bac à sable

Un mode où rien ne part, pour intégrer sans risque.

  • Les clés de test sont distinctes et visiblement préfixées ; une clé de test n’atteint jamais les données de production.
  • Les messages sont capturés au lieu d’être remis, et restent consultables pour vérification.
  • Les retours et les plaintes peuvent être simulés, pour éprouver les branches d’un parcours qui en dépendent.
  • Les mêmes règles de consentement s’appliquent : un bac à sable qui laisserait passer ce que la production refuse ne servirait à rien.

Webhooks, événements et exports

Deux manières de récupérer ce qui se passe, et une règle commune : aucune donnée personnelle en sortie.

  • En traction : le journal d’événements se lit par appel, avec filtres et pagination par curseur.
  • En poussée : des livraisons HTTPS signées, avec réessais espacés et journal des tentatives.
  • Protection contre les redirections vers des adresses internes : l’URL d’un abonnement est vérifiée avant chaque appel.
  • Les charges utiles ne portent que des identifiants opaques — jamais une adresse e-mail, un sujet ou un corps.
  • Les événements métier poussés par vos outils reviennent dans les segments, les conditions et les déclencheurs.
  • Exports de statistiques et du journal d’événements, à la demande ou planifiés, en CSV ou en JSON, récupérés par téléchargement ou poussés vers un webhook.
Ce qu’une livraison contient, et comment elle se vérifie
  • Un identifiant d’événement, un type, une date en temps universel et des identifiants opaques de ressources — rien d’autre.
  • Une signature calculée avec un secret propre à l’abonnement, et une date dans l’en-tête pour écarter les rejeux.
  • Le secret n’est restitué qu’à la création de l’abonnement ; il se change sans interrompre les livraisons.
  • Les tentatives infructueuses sont réessayées à intervalles croissants, puis abandonnées, et chacune est consultable.
  • Un événement manqué se rattrape par le journal d’événements : la traction reste la source de vérité.

Console web

La même plateforme, avec des écrans — et exactement les mêmes autorisations.

  • Contacts, listes, segments, consentements ; parcours, campagnes et messages de service ; templates, fragments, fichiers et pages publiques ; statistiques et exports ; domaines, clés et réglages de conservation.
  • La console est un client de l’API comme un autre : elle n’a aucun accès privilégié, et sa navigation se construit sur l’autorisation effective renvoyée par le serveur.
  • Les actions sont rattachées à la personne qui les a déclenchées, en plus de la clé employée, par un en-tête signé qui nomme sans autoriser.
  • Double authentification obligatoire pour tous ; authentification unique par le fournisseur d’identité du client possible.
  • Aucun écran ne contourne une règle de consentement : ce que le serveur refuse, la console ne l’obtient pas non plus.

Exploitation et déploiement

Ce qui n’est pas automatisé finit par être fait à la main, un soir, sans trace.

  • Déploiement par artefact : une version est un artefact de build vérifié — sans historique, sans tests, sans outillage de développement — publié après une intégration continue verte et déployé tel quel. Le retour arrière consiste à redéployer la version précédente.
  • Intégration continue bloquante : analyse statique, vérification de types, contrat régénéré et comparé, tests unitaires, d’intégration et d’isolation entre espaces, détection de secrets, audit des dépendances, démarrage réel de l’artefact.
  • Migrations déployées, pas lancées : le changement de schéma est du code embarqué dans la version et exécuté au déploiement. Personne n’ouvre de session sur la production.
  • Environnements de revue éphémères, avec base dédiée et données synthétiques générées. Aucune donnée de production hors production : ni copie, ni restauration ailleurs, ni extrait dans un artefact.
  • Aucun secret dans les dépôts : le démarrage refuse une valeur vide, une valeur d’exemple, une longueur insuffisante ou deux secrets identiques.