{
  "name": "Owepo — Webhook sécurisé",
  "nodes": [
    {
      "parameters": {
        "httpMethod": "POST",
        "path": "owepo-entree",
        "responseMode": "responseNode",
        "options": { "rawBody": false }
      },
      "id": "c3d2e4f6-0003-4000-8000-000000000001",
      "name": "Point d'entrée",
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 2,
      "position": [-300, 0],
      "webhookId": "c3d2e4f6-0003-4000-8000-0000000000aa"
    },
    {
      "parameters": {
        "conditions": {
          "options": { "caseSensitive": true, "version": 2 },
          "conditions": [{
            "id": "tok",
            "leftValue": "={{ $json.headers['x-owepo-token'] }}",
            "rightValue": "={{ $env.OWEPO_WEBHOOK_TOKEN }}",
            "operator": { "type": "string", "operation": "equals" }
          }],
          "combinator": "and"
        },
        "options": {}
      },
      "id": "c3d2e4f6-0003-4000-8000-000000000002",
      "name": "Jeton valide ?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.2,
      "position": [-60, 0],
      "notesInFlow": true,
      "notes": "Le jeton vient des variables d'environnement, jamais écrit en dur ici"
    },
    {
      "parameters": {
        "conditions": {
          "options": { "caseSensitive": true, "version": 2 },
          "conditions": [
            { "id": "e", "leftValue": "={{ $json.body.email }}", "rightValue": "", "operator": { "type": "string", "operation": "notEmpty" } },
            { "id": "f", "leftValue": "={{ $json.body.email }}", "rightValue": "^[^@\\s]+@[^@\\s]+\\.[a-z]{2,}$", "operator": { "type": "string", "operation": "regex" } }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "id": "c3d2e4f6-0003-4000-8000-000000000003",
      "name": "Contenu conforme ?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.2,
      "position": [200, -100]
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            { "id": "e", "name": "email", "value": "={{ $json.body.email.toLowerCase().trim() }}", "type": "string" },
            { "id": "n", "name": "nom", "value": "={{ ($json.body.nom || '').toString().slice(0, 120) }}", "type": "string" },
            { "id": "r", "name": "recuLe", "value": "={{ $now.toISO() }}", "type": "string" }
          ]
        },
        "options": {}
      },
      "id": "c3d2e4f6-0003-4000-8000-000000000004",
      "name": "Nettoyer et borner",
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [460, -180],
      "notesInFlow": true,
      "notes": "Branchez ici la suite de votre traitement"
    },
    {
      "parameters": {
        "respondWith": "json",
        "responseBody": "={{ { \"ok\": true } }}",
        "options": { "responseCode": 200 }
      },
      "id": "c3d2e4f6-0003-4000-8000-000000000005",
      "name": "Répondre 200",
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 1.1,
      "position": [720, -180]
    },
    {
      "parameters": {
        "respondWith": "json",
        "responseBody": "={{ { \"ok\": false, \"error\": \"requete invalide\" } }}",
        "options": { "responseCode": 400 }
      },
      "id": "c3d2e4f6-0003-4000-8000-000000000006",
      "name": "Répondre 400",
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 1.1,
      "position": [460, 40]
    },
    {
      "parameters": {
        "respondWith": "json",
        "responseBody": "={{ { \"ok\": false, \"error\": \"non autorise\" } }}",
        "options": { "responseCode": 401 }
      },
      "id": "c3d2e4f6-0003-4000-8000-000000000007",
      "name": "Répondre 401",
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 1.1,
      "position": [200, 160]
    }
  ],
  "connections": {
    "Point d'entrée": { "main": [[{ "node": "Jeton valide ?", "type": "main", "index": 0 }]] },
    "Jeton valide ?": { "main": [[{ "node": "Contenu conforme ?", "type": "main", "index": 0 }], [{ "node": "Répondre 401", "type": "main", "index": 0 }]] },
    "Contenu conforme ?": { "main": [[{ "node": "Nettoyer et borner", "type": "main", "index": 0 }], [{ "node": "Répondre 400", "type": "main", "index": 0 }]] },
    "Nettoyer et borner": { "main": [[{ "node": "Répondre 200", "type": "main", "index": 0 }]] }
  },
  "settings": { "executionOrder": "v1" },
  "pinData": {},
  "meta": { "description": "Webhook public correctement fermé : jeton d'en-tête, validation du contenu, réponses explicites. Fourni par Owepo (owepo.com), réutilisable et modifiable librement." }
}
