{
  "name": "TeamRetro: On Webhook \u2192 Create Action",
  "nodes": [
    {
      "id": "a1b2c3d4-0001-0000-0000-000000000001",
      "name": "Webhook",
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 2,
      "position": [
        240,
        300
      ],
      "parameters": {
        "httpMethod": "POST",
        "path": "teamretro-events",
        "responseMode": "lastNode",
        "options": {
          "rawBody": true
        }
      }
    },
    {
      "id": "a1b2c3d4-0002-0000-0000-000000000002",
      "name": "Verify Signature",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        460,
        300
      ],
      "parameters": {
        "jsCode": "// Verify HMAC-SHA256 signature from TeamRetro.\n// Store your webhook signing secret in an n8n credential or env variable.\n// Header format: X-TeamRetro-Signature: t=<unixTs>,v1=<hexHmac>\n// Signed input: \"<unixTs>.<rawBody>\"\n// CRITICAL: \"Raw Body\" must be enabled on the Webhook node. Re-serializing JSON.stringify(body) will NOT match.\n// Requires NODE_FUNCTION_ALLOW_BUILTIN=crypto in your n8n environment.\n\nconst crypto = require('crypto');\n\nconst item = $input.first();\nconst sigHeader = item.json.headers['x-teamretro-signature'] ?? '';\n// With \"Raw Body\" enabled, the raw bytes arrive as base64 in binary.data.data:\nconst rawBody = Buffer.from(item.binary.data.data, 'base64').toString('utf8');\nconst secret  = 'REPLACE_WITH_YOUR_SIGNING_SECRET';\n\nconst parts = Object.fromEntries(sigHeader.split(',').map((p) => p.split('=')));\n\nif (!parts.t || !parts.v1) {\n  throw new Error('Missing X-TeamRetro-Signature header');\n}\n\nconst expected = crypto\n  .createHmac('sha256', secret)\n  .update(`${parts.t}.${rawBody}`)\n  .digest('hex');\nconst received = Buffer.from(parts.v1, 'hex');\n\nif (received.length !== 32 || !crypto.timingSafeEqual(received, Buffer.from(expected, 'hex'))) {\n  throw new Error('Invalid TeamRetro signature \u2014 request rejected');\n}\n\nreturn $input.all();"
      }
    },
    {
      "id": "a1b2c3d4-0003-0000-0000-000000000003",
      "name": "Only on action.created",
      "type": "n8n-nodes-base.filter",
      "typeVersion": 2,
      "position": [
        680,
        300
      ],
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict"
          },
          "conditions": [
            {
              "id": "cond1",
              "leftValue": "={{ $json.body.event }}",
              "rightValue": "action.created",
              "operator": {
                "type": "string",
                "operation": "equals"
              }
            }
          ],
          "combinator": "and"
        },
        "looseTypeValidation": true
      }
    },
    {
      "id": "a1b2c3d4-0004-0000-0000-000000000004",
      "name": "Create Action in TeamRetro",
      "type": "n8n-nodes-teamretro.teamRetro",
      "typeVersion": 1,
      "position": [
        900,
        300
      ],
      "credentials": {
        "teamRetroApi": {
          "name": "<your credential>"
        }
      },
      "parameters": {
        "resource": "action",
        "operation": "create",
        "teamId": "={{ $json.body.data.teamId }}",
        "title": "={{ $json.body.data.title ?? 'Action from webhook' }}",
        "additionalFields": {
          "priority": "medium"
        }
      }
    }
  ],
  "connections": {
    "Webhook": {
      "main": [
        [
          {
            "node": "Verify Signature",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Verify Signature": {
      "main": [
        [
          {
            "node": "Only on action.created",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Only on action.created": {
      "main": [
        [
          {
            "node": "Create Action in TeamRetro",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "settings": {
    "executionOrder": "v1"
  }
}