KKreatoAI/Documentation API

Webhooks

Plutôt que de poller /v1/publish/tiktok/status, enregistrez une URL : KreatoAI suit vos publications côté serveur et vous notifie en POST JSON signé dès qu'un statut terminal est atteint. Les publications par clé API et les posts programmés depuis le dashboard sont couverts.

Principe

1. Créez un endpoint (dashboard → Paramètres → Webhooks, ou API) et conservez son secret whsec_… — affiché une seule fois. 2. Publiez normalement via l'API. 3. Recevez l'événement sur votre URL en ~10-30 s, vérifiez la signature, répondez 2xx. Jusqu'à 3 endpoints par espace de travail — chacun reçoit tous les événements.

Événements

TypeDéclencheur
publish.inbox_deliveredBrouillon (photo ou vidéo) arrivé dans la boîte de réception TikTok
publish.completedUn réseau a publié avec succès (un événement par réseau)
publish.failedUn réseau a échoué — failReason + failType (retriable/permanent)
pingTest manuel depuis le dashboard ou l’API
// Corps du POST reçu — UN événement par réseau visé
{
  "id": "5f1c…",                        // id de livraison (idempotence)
  "type": "publish.completed",
  "createdAt": "2026-07-19T10:00:00.000Z",
  "data": {
    "source": "api",                    // "api" (clé API) ou "scheduled" (dashboard)
    "postId": "9f1c8b2e-…",             // id /v2/posts (GET /v2/posts/:id)
    "platform": "facebook",             // le réseau concerné par CET événement
    "channel": "FACEBOOK_PAGE",
    "accountId": "a3f27c9e-…",          // LE compte concerné (si plusieurs pages connectées)
    "accountName": "Campus Plus",
    "title": "…",
    "externalPostId": "123_456",        // id du post chez le réseau
    "postUrl": "https://…",             // si le réseau l'expose

    // publish.failed uniquement :
    "failReason": "…",
    "failType": "permanent",            // ou "retriable" — ne bouclez pas sur un permanent

    // publications TikTok /v1 (sans /v2/posts) :
    "publishId": "v_pub_url~v2-1.766…",
    "postMode": "DIRECT_POST",
    "publicPostId": "…"
  }
}

// En-têtes
X-Kreato-Event: publish.completed
X-Kreato-Delivery: 5f1c…
X-Kreato-Timestamp: 1784512800
X-Kreato-Signature: v1=<hex HMAC-SHA256>

Un post multi-réseaux (POST /v2/posts ou dashboard) émet un événement par réseau : trois réseaux visés = jusqu'à trois événements, chacun avec son platform et son résultat propre. Si plusieurs comptes d'un même réseau sont connectés, accountId et accountName disent lequel est concerné (voir Comptes connectés). TikTok est notifié à son statut terminal réel (publié en ligne ou brouillon livré), pas à l'acceptation de la demande. Les publications TikTok passées par /v1/publish/tiktok/* émettent le même contrat avec publishId/postMode et sans postId.

Gérer ses endpoints

Gestion par le dashboard (Paramètres → Webhooks) ou par l'API — session dashboard requise (JWT), les clés sk-kre-v1 ne gèrent pas les endpoints :

POST
/v1/webhook-endpoints

Créer — le secret n’est renvoyé qu’une fois

GET
/v1/webhook-endpoints

Lister (sans secret)

POST
/v1/webhook-endpoints/:id/test

Envoyer un ping de test

GET
/v1/webhook-endpoints/:id/deliveries

20 dernières livraisons

PATCH
/v1/webhook-endpoints/:id

Réactiver après désactivation auto

DELETE
/v1/webhook-endpoints/:id

Supprimer

L'URL doit être http(s) publique (pas d'IP privée ni de localhost). Erreurs : 400 invalid_webhook_url, 409 endpoint_limit_reached (3 max).

Vérifier la signature

Chaque requête est signée avec le secret de l'endpoint : v1=HMAC-SHA256(secret, timestamp + "." + corpsBrut). Vérifiez la signature ET la fraîcheur du timestamp (tolérance 5 min) :

// Node.js — le corps doit être lu BRUT (avant tout JSON.parse)
const crypto = require('crypto')

function verifyKreatoWebhook(rawBody, headers, secret) {
  const timestamp = headers['x-kreato-timestamp']
  const signature = headers['x-kreato-signature'] // "v1=<hex>"
  if (Math.abs(Date.now() / 1000 - Number(timestamp)) > 300) return false
  const expected = 'v1=' + crypto
    .createHmac('sha256', secret)
    .update(timestamp + '.' + rawBody)
    .digest('hex')
  return (
    signature.length === expected.length &&
    crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected))
  )
}

Répondez 200 rapidement (traitez en asynchrone si besoin — timeout 10 s). Utilisez id pour l'idempotence : un même événement peut arriver deux fois en cas de retry après un timeout de votre côté.

Retries et désactivation automatique

Toute réponse non-2xx (ou timeout) est retentée : 1 min → 5 min → 30 min → 2 h → 8 h (6 tentatives au total), puis la livraison est abandonnée. Après 10 livraisons abandonnées consécutives, l'endpoint est désactivé automatiquement — notification dans le dashboard, réactivation en un clic (Paramètres → Webhooks) une fois votre service réparé. Un succès remet le compteur à zéro.

Consommer les webhooks

N'importe quel serveur HTTP public fait l'affaire : exposez une route POST capable de lire le corps brut (indispensable pour la signature — désactivez tout parsing JSON automatique sur cette route), vérifiez la signature avec la fonction ci-dessus, répondez 200 immédiatement, puis traitez l'événement en asynchrone. Dédupliquez sur id.

Les plateformes d'automatisation fonctionnent de la même façon : dans n8n, un nœud Webhook (option « Raw Body ») remplace la boucle Wait + IF du guide n8n ; Make et Zapier exposent un déclencheur équivalent. Dans tous les cas, le workflow reprend dès l'événement reçu — zéro polling.