{
  "name": "Vocra — qualified leads to CRM, the rest to Slack",
  "nodes": [
    {
      "parameters": { "httpMethod": "POST", "path": "vocra-leads", "options": { "rawBody": true } },
      "id": "webhook",
      "name": "Vocra webhook",
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 2,
      "position": [0, 0],
      "webhookId": "vocra-leads"
    },
    {
      "parameters": {
        "jsCode": "// Same verification as every other template — see docs/n8n/README.md.\nconst crypto = require('crypto');\n\nconst SECRET = 'VOCRA_WEBHOOK_SECRET';\nconst TOLERANCE_SECONDS = 300;\n\nconst headers = $input.first().json.headers ?? {};\nconst raw = $input.first().json.body;\nconst body = typeof raw === 'string' ? raw : JSON.stringify(raw);\n\nconst parts = Object.fromEntries(\n  (headers['x-vocra-signature'] ?? '').split(',').map((p) => p.trim().split('='))\n);\nconst timestamp = Number.parseInt(parts.t ?? '', 10);\nif (!Number.isFinite(timestamp)) throw new Error('Missing signature timestamp');\nif (Math.abs(Math.floor(Date.now() / 1000) - timestamp) > TOLERANCE_SECONDS) {\n  throw new Error('Signature too old');\n}\n\nconst expected = crypto\n  .createHmac('sha256', SECRET)\n  .update(`${timestamp}.${body}`)\n  .digest('hex');\nif (expected !== parts.v1) throw new Error('Bad signature');\n\nreturn [{ json: typeof raw === 'string' ? JSON.parse(raw) : raw }];"
      },
      "id": "verify",
      "name": "Verify signature",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [220, 0]
    },
    {
      "parameters": {
        "conditions": {
          "options": { "caseSensitive": true, "version": 2 },
          "conditions": [
            {
              "leftValue": "={{ $json.event }}",
              "rightValue": "call_analyzed",
              "operator": { "type": "string", "operation": "equals" }
            }
          ],
          "combinator": "and"
        }
      },
      "id": "filter",
      "name": "Only call_analyzed",
      "type": "n8n-nodes-base.filter",
      "typeVersion": 2,
      "position": [440, 0]
    },
    {
      "parameters": {
        "rules": {
          "values": [
            {
              "conditions": {
                "options": { "caseSensitive": true, "version": 2 },
                "conditions": [
                  {
                    "leftValue": "={{ $json.call.analysis?.call_successful }}",
                    "rightValue": true,
                    "operator": { "type": "boolean", "operation": "true", "singleValue": true }
                  }
                ],
                "combinator": "and"
              },
              "outputKey": "qualified"
            }
          ]
        },
        "options": { "fallbackOutput": "extra" }
      },
      "id": "switch",
      "name": "Qualified?",
      "type": "n8n-nodes-base.switch",
      "typeVersion": 3,
      "position": [660, 0],
      "notes": "call_successful is the model's judgement of whether the agent achieved its purpose. Add your own custom analysis fields to this condition for a stricter rule."
    },
    {
      "parameters": {
        "method": "POST",
        "url": "https://your-crm.example.com/api/leads",
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={{ JSON.stringify({ phone: $json.call.from_number, summary: $json.call.analysis.summary, sentiment: $json.call.analysis.sentiment, fields: $json.call.analysis.custom_analysis_data, vocra_call_id: $json.call.call_id }) }}",
        "options": {}
      },
      "id": "crm",
      "name": "Create CRM lead",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4,
      "position": [880, -80]
    },
    {
      "parameters": {
        "select": "channel",
        "channelId": "#calls",
        "text": "={{ `Unqualified call from ${$json.call.from_number}: ${$json.call.analysis?.summary ?? 'no summary'}` }}",
        "otherOptions": {}
      },
      "id": "slack",
      "name": "Notify Slack",
      "type": "n8n-nodes-base.slack",
      "typeVersion": 2,
      "position": [880, 100]
    }
  ],
  "connections": {
    "Vocra webhook": { "main": [[{ "node": "Verify signature", "type": "main", "index": 0 }]] },
    "Verify signature": { "main": [[{ "node": "Only call_analyzed", "type": "main", "index": 0 }]] },
    "Only call_analyzed": { "main": [[{ "node": "Qualified?", "type": "main", "index": 0 }]] },
    "Qualified?": {
      "main": [
        [{ "node": "Create CRM lead", "type": "main", "index": 0 }],
        [{ "node": "Notify Slack", "type": "main", "index": 0 }]
      ]
    }
  },
  "settings": { "executionOrder": "v1" },
  "pinData": {}
}
