Contrat d’envoi des articles
Référence développeur pour recevoir des articles publiés complets.
Utilisez un secret distinct par récepteur. Les secrets sont chiffrés et jamais renvoyés dans les résumés de connexion. Authentifiez la signature avant de faire confiance à l’identifiant du site.
Requête et vérification
Structura envoie HTTPS POST avec Content-Type: application/json, X-Structura-Event-Id, X-Structura-Timestamp (secondes Unix) et X-Structura-Signature (sha256= suivi du condensat hexadécimal en minuscules). Calculez HMAC-SHA256 sur timestamp + "." + rawBody avec le secret en UTF-8. Comparez les octets de même longueur en temps constant, refusez un décalage supérieur à cinq minutes, puis analysez JSON. L’ID d’en-tête doit correspondre au corps. Ne sérialisez pas de nouveau le JSON pour vérifier la signature.
Format du message
{
"schema_version": 1,
"event": "post.published",
"event_id": "article_<sha256>",
"delivered_at": "2026-09-28T10:00:00.000Z",
"site": {
"id": "site_123"
},
"post": {
"id": "post_123",
"slug": "first-article",
"title": "First article",
"html": "<p>Article body</p>",
"markdown": "Article body",
"excerpt": null,
"metaTitle": null,
"metaDescription": null,
"focusKeyword": null,
"locale": "en",
"publishedAt": "2026-09-28T10:00:00.000Z",
"updatedAt": "2026-09-28T10:00:00.000Z",
"canonicalUrl": "https://example.com/blog/first-article",
"featuredImage": null,
"author": null,
"jsonLd": []
}
}id est une chaîne pour les articles headless ou un nombre pour WordPress. Les métadonnées absentes valent null ; jsonLd est un tableau. Le HTML est assaini et Markdown provient de ce même HTML. La langue du contenu est indépendante des notifications. Les images restent hébergées à leurs URL. L’identité publique de l’auteur est incluse uniquement si la source la fournit.
Avant d’insérer jsonLd dans un élément <script type="application/ld+json">, sérialisez-le et remplacez chaque < par \u003c. Un JSON valide peut contenir </script> ; l’assainissement du HTML ne rend pas ce JSON sûr pour une insertion directe.
La requête complète est limitée à 1 000 000 octets UTF-8, HTML, Markdown, métadonnées et échappement JSON compris. La normalisation autorise 995 904 octets pour l’article et réserve 4 096 octets pour l’enveloppe de l’événement. Les articles trop volumineux sont ignorés avec article_too_large ; utilisez la Content API pour les contenus plus grands.
Stockage et règles d’envoi
Imposez une contrainte unique durable sur event_id. Dans une même transaction, mettez l’article à jour par site.id, post.id et post.locale, puis marquez l’événement comme traité. Confirmez après validation. Un doublon valide reçoit 2xx sans être réappliqué. Comparez updatedAt pour éviter qu’une ancienne requête remplace une révision récente. Les ID incluent l’espace, le site et le contenu ; une révision republiée reçoit un nouvel ID.
Toute réponse 2xx est un succès. Les erreurs réseau et HTTP 408, 429 et 5xx déclenchent une seule nouvelle tentative après 150 ms. Les autres statuts échouent immédiatement. Chaque tentative dispose de 8 secondes ; le corps de réponse est ignoré. Aucun rejeu automatique ultérieur. Les redirections, adresses privées et récepteurs sans HTTPS sont refusés. Stockez d’abord et traitez le travail coûteux dans votre propre file.
Seule la publication déclenche un envoi. Les modifications et suppressions ne génèrent pas d’événements. Réconciliez les articles manquants ou modifiés via la Content API publique. WordPress nécessite un plugin envoyant le champ facultatif article. Les anciennes versions continuent les autres notifications, mais ne transmettent pas d’articles complets.