Passer au contenu principal

Guide d'intégration n8n

Réponse rapide : utilisez le nœud déclencheur Webhook de n8n pour recevoir les événements report.completed de Surmado. Faites pointer le webhook_url de Surmado vers l’URL du webhook n8n, filtrez sur event et report.product, puis transmettez le payload à Google Sheets, Slack, Postgres ou toute autre intégration. n8n auto-hébergé est gratuit ; n8n Cloud coûte $20/mois.

Temps de lecture : 16 minutes


Prérequis

  1. Une instance n8n (auto-hébergée via Docker, ou n8n Cloud)
  2. Une clé d’API Surmado (sur_live_...) : créez-la sur app.surmado.com → Settings → API Keys
  3. Une URL publique pour votre webhook n8n (n8n Cloud s’en charge ; en auto-hébergé, il faut un domaine ou un tunnel)

Pourquoi n8n

  • Auto-hébergeable : votre workflow tourne sur votre propre infrastructure (Docker, Kubernetes, serveur dédié)
  • Open source : inspectez chaque nœud, étendez n8n avec du code personnalisé
  • Pas de facturation à la tâche : exécutions illimitées en auto-hébergé (seul le coût du serveur s’applique)
  • Plus de 400 nœuds intégrés : Notion, Google Sheets, Slack, Airtable, PostgreSQL, HTTP Request, Code, etc.
  • Coffre d’identifiants : enregistrez votre clé d’API Surmado une seule fois et réutilisez-la dans tous vos workflows

Démarrage rapide : auto-hébergement via Docker

docker volume create n8n_data

docker run -d --name n8n \
  -p 5678:5678 \
  -v n8n_data:/home/node/.n8n \
  -e N8N_HOST="n8n.yourdomain.com" \
  -e WEBHOOK_URL="https://n8n.yourdomain.com/" \
  n8nio/n8n

Placez ensuite n8n.yourdomain.com derrière un reverse proxy (Caddy, Nginx ou Traefik) vers http://localhost:5678, pour que Surmado puisse joindre votre point d’accès webhook en HTTPS.


Enregistrer votre clé d’API Surmado

Dans n8n, allez dans Credentials → New → Header Auth (ou utilisez l’identifiant intégré du nœud générique HTTP Request) :

  • Name: Surmado API
  • Header name: Authorization
  • Header value: Bearer sur_live_YOUR_API_KEY

Référencez cet identifiant dans tout nœud HTTP Request qui appelle api.surmado.com.


Le schéma d’intégration

  1. Un nœud déclencheur Webhook. n8n vous donne une URL du type https://n8n.yourdomain.com/webhook/abc123.
  2. Configurez Surmado pour envoyer (POST) les rapports terminés à cette URL via webhook_url à la création d’un rapport.
  3. Un nœud IF pour filtrer sur event et report.product.
  4. (Facultatif) Un nœud HTTP Request pour appeler GET /v1/reports/{{ $json.report.id }} et obtenir des données plus détaillées.
  5. Des nœuds de destination : Google Sheets, Slack, Notion, Postgres, etc.

Exemple de payload reçu par le nœud Webhook

{
  "event": "report.completed",
  "timestamp": "2026-04-15T12:00:00+00:00",
  "report": {
    "id": "rpt_abc123xyz",
    "token": "SIG-2026-04-A1B2C",
    "product": "signal",
    "status": "completed",
    "tier": "basic",
    "data_url": "https://api.surmado.com/v1/reports/rpt_abc123xyz",
    "pdf_url": "https://api.surmado.com/v1/reports/view/VIEW_TOKEN",
    "summary": {
      "business_name": "Acme Coffee Roasters",
      "presence_score": 34.2,
      "authority_score": 42.7,
      "competitive_rank": 4,
      "top_competitor": "Blue Bottle"
    }
  }
}

Rapports Strategy ("product": "solutions") : ils arrivent sans objet summary, uniquement avec report.token et report.pdf_url.


Workflow 1 : AI Visibility vers Google Sheets

Nœud 1 : déclencheur Webhook

  • HTTP method: POST
  • Path: surmado-signal (n8n générera https://n8n.yourdomain.com/webhook/surmado-signal)
  • Response mode: Immediately (renvoie 200 OK dès que n8n reçoit la requête)

Transmettez cette URL à Surmado :

curl -X POST https://api.surmado.com/v1/reports/signal \
  -H "Authorization: Bearer sur_live_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "brand_slug": "acme_corp",
    "url": "https://acme.com",
    "email": "founder@acme.com",
    "industry": "B2B SaaS",
    "location": "United States",
    "persona": "Small business owners",
    "pain_points": "Losing track of customer conversations",
    "brand_details": "Simple CRM with email integration",
    "direct_competitors": "HubSpot, Pipedrive",
    "webhook_url": "https://n8n.yourdomain.com/webhook/surmado-signal"
  }'

Cliquez sur Listen for test event dans le nœud Webhook, puis lancez un rapport pour que n8n capture la structure du payload.

Nœud 2 : IF

Condition 1: {{ $json.event }} equals report.completed Condition 2: {{ $json.report.product }} equals signal

Combine: AND

Nœud 3 : Google Sheets, Append row

Operation: Append Spreadsheet / Sheet: votre feuille de suivi

Correspondance des colonnes :

  • Date: {{ $json.timestamp }}
  • Token: {{ $json.report.token }}
  • Business: {{ $json.report.summary.business_name }}
  • Presence Score: {{ $json.report.summary.presence_score }}
  • Authority Score: {{ $json.report.summary.authority_score }}
  • Competitive Rank: {{ $json.report.summary.competitive_rank }}
  • Top Competitor: {{ $json.report.summary.top_competitor }}

Activez le workflow. Chaque rapport AI Visibility terminé est désormais suivi.


Workflow 2 : Site Audit avec alerte Slack conditionnelle

Webhook → IF (report.product = scan) → Google Sheets (toujours) → IF (report.summary.performance_score < 70) → Slack.

Message Slack :

:warning: Performance regression on {{ $json.report.summary.business_name }}

Performance: {{ $json.report.summary.performance_score }} (below 70 threshold)
SEO: {{ $json.report.summary.seo_score }}
Accessibility: {{ $json.report.summary.accessibility_score }}
Critical issues: {{ $json.report.summary.critical_issues_count }}

View report: {{ $json.report.pdf_url }}

Workflow 3 : synthèse PDF Strategy

Strategy n’inclut pas de résumé. Schéma :

  1. Webhook → IF (report.product = solutions) → Send Email (Gmail, SMTP, SendGrid).

Corps de l’e-mail :

<p>Strategy report <code>{{ $json.report.token }}</code> is ready.</p>
<p><a href="{{ $json.report.pdf_url }}">View the full report (PDF)</a></p>

Récupérer des données plus détaillées via l’API REST

Le résumé du webhook couvre la plupart des besoins. Pour la variance par plateforme, les problèmes page par page ou le détail des lacunes de contenu, ajoutez un nœud HTTP Request après le filtre :

Nœud : HTTP Request

  • Method: GET
  • URL: https://api.surmado.com/v1/reports/{{ $json.report.id }}
  • Authentication: predefined credential → Surmado API (le Header Auth créé plus haut)
  • Response format: JSON

Les nœuds suivants peuvent alors référencer {{ $json.public_intelligence.data.platform_variance.chatgpt.presence_score }}, {{ $json.public_intelligence.data.audit_data.enrichment.content_gaps.executive_summary }}, etc.


Vérification de la signature du webhook

En production, vérifiez l’en-tête X-Surmado-Signature avant de faire confiance au payload. Surmado signe les webhooks avec HMAC-SHA256 sur une représentation JSON canonicalisée.

Nœud Function : vérifier la signature

const crypto = require('crypto');

const secret = $env.SURMADO_WEBHOOK_SECRET;
const signature = $('Webhook').first().json.headers['x-surmado-signature'];
const body = $('Webhook').first().json.body;

function canonicalize(value) {
  if (value === null || typeof value !== 'object') return JSON.stringify(value);
  if (Array.isArray(value)) return '[' + value.map(canonicalize).join(',') + ']';
  const keys = Object.keys(value).sort();
  return '{' + keys.map(k => JSON.stringify(k) + ':' + canonicalize(value[k])).join(',') + '}';
}

function asciiEscape(str) {
  return str.replace(/[\u0080-\uffff]/g, c =>
    '\\u' + ('0000' + c.charCodeAt(0).toString(16)).slice(-4)
  );
}

const canonical = asciiEscape(canonicalize(body));
const expected = crypto.createHmac('sha256', secret).update(canonical).digest('hex');

if (!crypto.timingSafeEqual(Buffer.from(expected, 'hex'), Buffer.from(signature, 'hex'))) {
  throw new Error('Invalid webhook signature');
}

return [{ json: body }];

Enchaînement : Webhook → Function (vérification) → IF (filtre) → nœuds de destination.


Formats de token

  • AI Visibility : SIG-YYYY-MM-XXXXX (regex : SIG-\d{4}-\d{2}-[A-Z0-9]{5})
  • Site Audit : SCN-YYYY-MM-XXXXX (regex : SCN-\d{4}-\d{2}-[A-Z0-9]{5})
  • Strategy : SOL-YYYY-MM-XXXXX (regex : SOL-\d{4}-\d{2}-[A-Z0-9]{5})

Les tokens n’expirent pas. Les URL de téléchargement signées de l’API REST sont valables environ 15 minutes ; les liens magiques pdf_url des webhooks sont valables environ 30 jours.


Schémas avancés

Router par produit avec Switch

Utilisez un nœud Switch sur $json.report.product avec des cas pour signal, scan et solutions. Chaque cas mène à un workflow propre au produit. Une seule URL de webhook gère tous les types de rapport.

Conserver dans Postgres pour une analyse chronologique

Ajoutez après le filtre IF un nœud Postgres qui insère (INSERT) (timestamp, token, report_id, product, business_name, presence_score, authority_score, ...) dans une table de rapports. Interrogez-la ensuite avec Grafana ou Metabase pour obtenir des courbes de tendance.

Routage multi-clients pour agences

Utilisez un Data store (ou une base externe) qui associe business_name / brand_slug à la configuration du client (quel canal Slack, quel onglet de feuille, etc.). Faites la recherche pour chaque rapport et routez dynamiquement.


Dépannage

Le webhook ne se déclenche pas : activez le workflow (n8n ne traite les webhooks que lorsque le workflow est actif, pas pendant les tests). Vérifiez que webhook_url a bien été indiqué à la création du rapport. Utilisez webhook.site comme URL de test pour vérifier que Surmado envoie le payload attendu.

Le nœud HTTP Request renvoie 401 : l’identifiant n’est pas rattaché, ou la clé n’a pas le préfixe Bearer . La valeur complète de l’en-tête doit être Bearer sur_live_....

Les champs sont vides en aval : vérifiez le type de produit. Les webhooks Strategy n’incluent pas report.summary ; seuls report.token et report.pdf_url sont renseignés.

Webhook auto-hébergé injoignable : Surmado exige HTTPS. Si vous exécutez n8n sur localhost, utilisez un tunnel (ngrok, Cloudflare Tunnel) ou déployez derrière un reverse proxy avec un certificat TLS valide.

La vérification de signature échoue avec des caractères non ASCII : la fonction canonicalize ci-dessus les gère. Si vous avez écrit la vôtre, assurez-vous d’échapper les caractères non ASCII en ASCII pour correspondre à la sortie de json.dumps(..., ensure_ascii=True) de Python, utilisée par Surmado.


À lire aussi : Guide d’intégration de l’API | Données structurées et Intelligence Tokens | Intégration Zapier | Intégration Make | Intégration Notion