Webhooks
Pousser les job completions vers ton endpoint via HTTP — au lieu de poller.
Les webhooks sont la voie push de l'API Rankion : au lieu de monter une boucle de polling après chaque 202 Accepted, tu enregistres un endpoint HTTPS et Rankion livre les job completions par POST dès qu'elles sont prêtes. Idéal pour les intégrations Zapier/Make, des backends maison ou des notifications Slack. Les webhooks sont complémentaires à Automation (pipelines internes) — ils sortent de la plateforme.
Statut : les webhooks outbound sont en planification. Actuellement, il n'existe qu'un webhook inbound pour les sources de reviews externes :
POST /api/v1/webhooks/reviews/{source}(basé sur clé, pas Sanctum, voir Review Sources). Une UI générale sous/settings/webhooksavec gestion d'abonnements et signature HMAC n'est pas encore déployée. La liste d'événements, l'enveloppe de payload et la vérification HMAC décrites ci-dessous sont la convention prévue — elle peut encore évoluer avant la release. Pour des updates de statut de job immédiats : utilise le polling REST sur l'endpoint de détail correspondant.
Configuration (UI) — prévu
Les endpoints de webhook seront créés (après release) dans le frontend sous /settings/webhooks :
- Saisir l'URL d'endpoint (HTTPS obligatoire)
- S'abonner à des Event-Types (multi-select)
- Copier le Signing-Secret (affiché une seule fois)
- Cliquer « Send test payload » — l'endpoint doit répondre
2xxdans les 5 secondes, sinon le test est considéré comme échoué
Event-Types
| Event | Trigger |
|---|---|
article.generated |
Job POST /v1/articles/{id}/generate terminé |
article.optimized |
Job POST /v1/articles/{id}/optimize terminé |
article.published |
Publication CMS terminée (ou échouée) |
tracking.run.completed |
Run de tracking complet sur toutes les plateformes LLM |
tracking.report.ready |
Job generate-report terminé |
content_audit.completed |
Crawl content-audits terminé |
content_optimizer.completed |
Analyse Optimizer terminée |
competitor_analysis.completed |
Analyse de concurrence terminée |
backlinks.refreshed |
Pull delta ou full terminé |
humanize.batch.completed |
Batch Humanizer terminé |
bulk_generation.completed |
Bulk article generation terminée |
pipeline.stage.completed |
Étape de pipeline terminée (pour réactions stage-by-stage) |
keyword.expansion.completed |
Expansion A→Z terminée |
Structure de payload
Tous les events partagent la même enveloppe :
{
"id": "evt_01HW9X8KRJV4M5PXAM",
"type": "article.generated",
"created_at": "2026-04-30T12:14:22Z",
"team_id": 3,
"data": {
"article_id": 88,
"project_id": 12,
"status": "ready",
"credits_used": 5,
"url": "https://rankion.ai/api/v1/articles/88"
}
}
L'objet data varie selon l'Event-Type. Pour les détails, charge la ressource complète via data.url à travers la REST API — les payloads webhook restent volontairement compacts pour ménager les body-limits des récepteurs (Slack, Zapier).
Exemple tracking.run.completed
{
"id": "evt_01HW9XBQS...",
"type": "tracking.run.completed",
"created_at": "2026-04-30T15:00:11Z",
"team_id": 3,
"data": {
"tracking_project_id": 7,
"run_id": 142,
"platforms": ["chatgpt","perplexity","claude"],
"avi_score": 64,
"delta_vs_previous": "+8",
"url": "https://rankion.ai/api/v1/tracking-projects/7/avi"
}
}
Signature HMAC
Chaque requête contient un header X-Rankion-Signature — une signature HMAC-SHA256 du body brut avec le Signing-Secret. Vérifie-la toujours avant de faire confiance au payload.
import hmac, hashlib
def verify(body: bytes, signature_header: str, secret: str) -> bool:
expected = hmac.new(secret.encode(), body, hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, signature_header.replace("sha256=", ""))
function rankion_verify_webhook(string $rawBody, string $sigHeader, string $secret): bool {
$expected = hash_hmac('sha256', $rawBody, $secret);
return hash_equals($expected, str_replace('sha256=', '', $sigHeader));
}
Format du header : X-Rankion-Signature: sha256=<hex>. En complément : X-Rankion-Event (Event-Type) et X-Rankion-Delivery (ID de delivery unique — idéal pour les checks d'idempotence).
Idempotence
À cause des retries, le même event peut être livré plusieurs fois. Stocke les X-Rankion-Delivery entrants pendant au moins 24 h et ignore les répétitions.
Logique de retry
Si ton endpoint ne répond pas en 2xx sous 5 secondes, Rankion retry avec backoff exponentiel :
| Tentative | Délai |
|---|---|
| 1 | immédiat |
| 2 | +30 s |
| 3 | +5 min |
| 4 | +30 min |
| 5 | +2 h |
| 6 | +6 h |
Après le 6e échec, l'abonnement est désactivé automatiquement et tu reçois un mail de notification. Réactivation via l'UI après correction.
Les réponses 4xx (par ex. 401, 403, 410) sont considérées comme un échec permanent → pas de retry, désactivation immédiate. Les 5xx et timeouts déclenchent la boucle de retry.
Exemple : récepteur Express
import express from "express";
import crypto from "crypto";
const app = express();
const SECRET = process.env.RANKION_WEBHOOK_SECRET;
app.post("/webhooks/rankion",
express.raw({ type: "application/json" }),
(req, res) => {
const sig = req.headers["x-rankion-signature"]?.replace("sha256=","");
const expected = crypto.createHmac("sha256", SECRET)
.update(req.body).digest("hex");
if (!sig || !crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(expected))) {
return res.status(401).send("invalid signature");
}
const event = JSON.parse(req.body.toString());
console.log(`Got ${event.type}:`, event.data);
// ack first, process async
res.status(200).send("ok");
handleEvent(event).catch(console.error);
}
);
Notes & pièges
- Réponds vite, traite en async. Un traitement lourd dans le récepteur bloque le timer 5 s. Renvoie d'abord
200, puis enqueue. - HTTPS uniquement. Les URLs HTTP sont rejetées directement dans l'UI.
- Tests locaux : ngrok / cloudflared tunnel sur ton port local → URL à saisir dans l'UI webhook.
- Pas de garantie d'ordre. Si tu déclenches
article.generatedetarticle.optimizedpour le même article rapidement, ils peuvent arriver dans le désordre. Trie côté récepteur parcreated_at. - La section webhook est jeune. S'il manque un Event-Type dont tu as besoin → tu peux atteindre le même effet en interne via les pipelines Automation, ou faire une feature request via le support.
Voir aussi : Vue d'ensemble API · Automation · Crédits.