{
  "name": "Cal.com Booking \u2192 Pre-Meeting Brief",
  "nodes": [
    {
      "parameters": {
        "httpMethod": "POST",
        "path": "calcom/booking",
        "responseMode": "responseNode",
        "options": {}
      },
      "id": "node-webhook",
      "name": "Cal.com Webhook",
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 2,
      "position": [
        220,
        300
      ]
    },
    {
      "parameters": {
        "respondWith": "json",
        "responseBody": "={ {\"status\": \"ok\"} }",
        "options": {}
      },
      "id": "node-respond",
      "name": "Respond OK",
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 1,
      "position": [
        420,
        500
      ]
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict"
          },
          "conditions": [
            {
              "id": "condition-booking-created",
              "leftValue": "={{ $json.triggerEvent }}",
              "rightValue": "BOOKING_CREATED",
              "operator": {
                "type": "string",
                "operation": "equals"
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "id": "node-filter",
      "name": "Filter BOOKING_CREATED",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2,
      "position": [
        420,
        300
      ]
    },
    {
      "parameters": {
        "jsCode": "// Normalize Cal.com booking payload into a flat object\nconst p = $input.first().json.payload;\n\nconst attendee = p.attendee || {};\nconst meta = attendee.metadata || {};\n\n// Split full name into first/last\nconst nameParts = (attendee.name || '').split(' ');\nconst firstName = nameParts[0] || '';\nconst lastName = nameParts.slice(1).join(' ');\n\nreturn [{\n  json: {\n    booking_uid: p.uid,\n    event_title: p.title,\n    start_time: p.startTime,\n    end_time: p.endTime,\n    time_zone: attendee.timeZone || 'UTC',\n    attendee_name: attendee.name,\n    attendee_first_name: firstName,\n    attendee_last_name: lastName,\n    attendee_email: attendee.email,\n    company: meta.company || null,\n    website: meta.website || null,\n    notes: meta.notes || null,\n    meeting_url: (p.conferenceData && p.conferenceData.url) || null,\n    organizer_name: p.organizer?.name,\n    organizer_email: p.organizer?.email\n  }\n}];"
      },
      "id": "node-normalize",
      "name": "Normalize Booking",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        640,
        300
      ]
    },
    {
      "parameters": {
        "method": "POST",
        "url": "https://services.leadconnectorhq.com/contacts/",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Version",
              "value": "2021-07-28"
            }
          ]
        },
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={\n  \"firstName\": \"{{ $json.attendee_first_name }}\",\n  \"lastName\": \"{{ $json.attendee_last_name }}\",\n  \"email\": \"{{ $json.attendee_email }}\",\n  \"companyName\": \"{{ $json.company }}\",\n  \"locationId\": \"{{ $env.GHL_LOCATION_ID }}\",\n  \"tags\": [\"cal-discovery\", \"new-lead\"],\n  \"customFields\": [\n    {\"key\": \"cal_booking_uid\", \"value\": \"{{ $json.booking_uid }}\"},\n    {\"key\": \"cal_start_time\", \"value\": \"{{ $json.start_time }}\"},\n    {\"key\": \"cal_meeting_url\", \"value\": \"{{ $json.meeting_url }}\"},\n    {\"key\": \"cal_event_title\", \"value\": \"{{ $json.event_title }}\"}\n  ]\n}",
        "options": {
          "response": {
            "response": {
              "fullResponse": true
            }
          }
        }
      },
      "id": "node-ghl-upsert",
      "name": "GHL \u2013 Upsert Contact",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        860,
        300
      ],
      "credentials": {
        "httpHeaderAuth": {
          "name": "<your credential>"
        }
      },
      "onError": "continueRegularOutput"
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": false,
            "leftValue": "",
            "typeValidation": "loose"
          },
          "conditions": [
            {
              "id": "condition-not-freemail",
              "leftValue": "={{ $('Normalize Booking').item.json.attendee_email }}",
              "rightValue": "gmail.com|yahoo.com|hotmail.com|outlook.com|aol.com|icloud.com",
              "operator": {
                "type": "string",
                "operation": "notRegex"
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "id": "node-freemail-check",
      "name": "Is Business Email?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2,
      "position": [
        1080,
        300
      ]
    },
    {
      "parameters": {
        "method": "GET",
        "url": "https://api.peopledatalabs.com/v5/person/enrich",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "sendQuery": true,
        "queryParameters": {
          "parameters": [
            {
              "name": "email",
              "value": "={{ $('Normalize Booking').item.json.attendee_email }}"
            },
            {
              "name": "min_likelihood",
              "value": "6"
            }
          ]
        },
        "options": {
          "response": {
            "response": {
              "fullResponse": true
            }
          }
        }
      },
      "id": "node-pdl-enrich",
      "name": "PDL \u2013 Enrich",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        1300,
        200
      ],
      "credentials": {
        "httpHeaderAuth": {
          "name": "<your credential>"
        }
      },
      "onError": "continueRegularOutput"
    },
    {
      "parameters": {
        "jsCode": "// Build context for AI brief by merging booking data with PDL enrichment\nconst booking = $('Normalize Booking').first().json;\n\nlet enrichment = {};\ntry {\n  const pdlResponse = $('PDL \u2013 Enrich').first().json;\n  if (pdlResponse && pdlResponse.status === 200) {\n    enrichment = pdlResponse.data || pdlResponse;\n  }\n} catch (e) {\n  // PDL enrichment failed or was skipped \u2013 continue with booking data only\n  enrichment = {};\n}\n\nreturn [{\n  json: {\n    attendee_name: booking.attendee_name,\n    attendee_email: booking.attendee_email,\n    company_name: booking.company || enrichment.job_company_name || 'Unknown',\n    website: booking.website || enrichment.job_company_website || null,\n    notes: booking.notes || null,\n    company_employees: enrichment.job_company_size || 'n/a',\n    company_industry: enrichment.job_company_industry || 'n/a',\n    company_funding: enrichment.job_company_founded ? ('Founded ' + enrichment.job_company_founded) : 'n/a',\n    job_title: enrichment.job_title || 'n/a',\n    linkedin_url: enrichment.linkedin_url || null,\n    start_time: booking.start_time,\n    end_time: booking.end_time,\n    time_zone: booking.time_zone,\n    meeting_url: booking.meeting_url,\n    booking_uid: booking.booking_uid,\n    organizer_name: booking.organizer_name,\n    organizer_email: booking.organizer_email\n  }\n}];"
      },
      "id": "node-build-context",
      "name": "Build Brief Context",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1520,
        300
      ]
    },
    {
      "parameters": {
        "resource": "chat",
        "model": "gpt-4.1-mini",
        "messages": {
          "values": [
            {
              "role": "system",
              "content": "You are an assistant helping a consultant prepare for a 30-minute discovery call.\nSummarize the prospect and their company, list 3\u20135 talking points,\nand suggest 3 tailored questions for the call. Be concise and skimmable.\nUse markdown formatting for readability."
            },
            {
              "role": "user",
              "content": "=Prospect info:\n- Name: {{ $json.attendee_name }}\n- Email: {{ $json.attendee_email }}\n- Job title: {{ $json.job_title }}\n- LinkedIn: {{ $json.linkedin_url }}\n- Company: {{ $json.company_name }}\n- Website: {{ $json.website }}\n- Notes from booking form: {{ $json.notes }}\n\nEnrichment data:\n- Company employees: {{ $json.company_employees }}\n- Company industry: {{ $json.company_industry }}\n- Company founded: {{ $json.company_funding }}\n\nPlease:\n1) Provide a short company overview.\n2) Suggest 3\u20135 bullet-point talking points for the call.\n3) Propose 3 high-value discovery questions tailored to this prospect."
            }
          ]
        },
        "options": {
          "temperature": 0.7,
          "maxTokens": 800
        }
      },
      "id": "node-openai-brief",
      "name": "OpenAI \u2013 Pre-Meeting Brief",
      "type": "@n8n/n8n-nodes-langchain.openAi",
      "typeVersion": 1.4,
      "position": [
        1740,
        300
      ],
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      },
      "onError": "continueRegularOutput"
    },
    {
      "parameters": {
        "resource": "message",
        "channel": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $env.SLACK_CHANNEL_ID_DISCOVERY }}"
        },
        "text": "=:new: *New Discovery Call Booked*\n\n*Prospect:* {{ $('Build Brief Context').item.json.attendee_name }} ({{ $('Build Brief Context').item.json.attendee_email }})\n*Role:* {{ $('Build Brief Context').item.json.job_title }}\n*Company:* {{ $('Build Brief Context').item.json.company_name }} \u2013 {{ $('Build Brief Context').item.json.company_industry }} \u2013 {{ $('Build Brief Context').item.json.company_employees }} employees\n*Time:* {{ $('Build Brief Context').item.json.start_time }} ({{ $('Build Brief Context').item.json.time_zone }})\n*Meeting Link:* {{ $('Build Brief Context').item.json.meeting_url }}\n\n*AI Pre-Meeting Brief:*\n{{ $json.message?.content || $json.content || $json.text || 'Brief generation failed \u2013 review manually.' }}",
        "otherOptions": {}
      },
      "id": "node-slack-post",
      "name": "Slack \u2013 Post Brief",
      "type": "n8n-nodes-base.slack",
      "typeVersion": 2.2,
      "position": [
        1960,
        300
      ],
      "credentials": {
        "slackApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "jsCode": "// No-op pass-through for free email addresses (skip PDL enrichment)\nconst booking = $('Normalize Booking').first().json;\nreturn [{ json: booking }];"
      },
      "id": "node-skip-pdl",
      "name": "Skip PDL (Free Email)",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1300,
        420
      ]
    }
  ],
  "connections": {
    "Cal.com Webhook": {
      "main": [
        [
          {
            "node": "Filter BOOKING_CREATED",
            "type": "main",
            "index": 0
          },
          {
            "node": "Respond OK",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Filter BOOKING_CREATED": {
      "main": [
        [
          {
            "node": "Normalize Booking",
            "type": "main",
            "index": 0
          }
        ],
        []
      ]
    },
    "Normalize Booking": {
      "main": [
        [
          {
            "node": "GHL \u2013 Upsert Contact",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "GHL \u2013 Upsert Contact": {
      "main": [
        [
          {
            "node": "Is Business Email?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Is Business Email?": {
      "main": [
        [
          {
            "node": "PDL \u2013 Enrich",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Skip PDL (Free Email)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "PDL \u2013 Enrich": {
      "main": [
        [
          {
            "node": "Build Brief Context",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Skip PDL (Free Email)": {
      "main": [
        [
          {
            "node": "Build Brief Context",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Build Brief Context": {
      "main": [
        [
          {
            "node": "OpenAI \u2013 Pre-Meeting Brief",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "OpenAI \u2013 Pre-Meeting Brief": {
      "main": [
        [
          {
            "node": "Slack \u2013 Post Brief",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "settings": {
    "executionOrder": "v1"
  },
  "staticData": null,
  "tags": [
    {
      "name": "cal-pipeline",
      "id": "tag-cal-pipeline"
    },
    {
      "name": "production",
      "id": "tag-production"
    }
  ],
  "triggerCount": 1
}