{
  "nodes": [
    {
      "id": "3ff42eda-d35f-4baa-b4c9-6e0ac6d615d1",
      "name": "5. Set \u2014 Build Success Response",
      "type": "n8n-nodes-base.set",
      "position": [
        -912,
        192
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "resp-html",
              "name": "confirmationHtml",
              "type": "string",
              "value": "=<div style=\"font-family:sans-serif;max-width:520px;margin:48px auto;padding:32px;border:1px solid #e0e0e0;border-radius:12px;text-align:center\"><h2 style=\"color:#22c55e\">&#9989; Fireflies Bot Invited</h2><p><strong>{{ $('2. Set \u2014 Validate and Prepare Inputs').item.json.meeting_title }}</strong></p><p>The bot will join your meeting automatically.<br>Duration: {{ $('2. Set \u2014 Validate and Prepare Inputs').item.json.meeting_duration }} minutes</p><p style=\"color:#888;font-size:13px\">Transcript and summary will appear in your Fireflies dashboard after the call ends.</p></div>"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "fc84d244-ddf0-4181-9cdf-7a641110c522",
      "name": "6. Respond \u2014 Bot Invited Successfully",
      "type": "n8n-nodes-base.respondToWebhook",
      "position": [
        -608,
        192
      ],
      "parameters": {
        "options": {},
        "respondWith": "html"
      },
      "typeVersion": 1.1
    },
    {
      "id": "fad4ccc3-d401-4071-a44e-1cd10eac432c",
      "name": "Overview1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -2848,
        -48
      ],
      "parameters": {
        "color": 4,
        "width": 508,
        "height": 928,
        "content": "## Fireflies Bot Meeting Inviter \u2014 One-Click Form\n\nFor sales teams, account managers, and consultants who manually invite the Fireflies recording bot to every meeting and keep forgetting in the rush before calls. Bookmark this form URL. Before any sales call, open it, paste the meeting link, and submit. The bot joins instantly. No Fireflies dashboard needed, no login, no navigation \u2014 just the form.\n\nTitle defaults to Sales Meeting - Incrementors if left blank. Duration is clamped between 15 and 120 minutes. Invalid meeting links get an immediate error response instead of silently failing.\n\n## How it works\n- **1. Form \u2014 Invite Fireflies Bot** collects the meeting link, title, password, duration, and language\n- **2. Set \u2014 Validate and Prepare Inputs** cleans and normalises all five fields with sensible defaults\n- **3. IF \u2014 Valid Meeting Link?** checks the link is non-empty and starts with http \u2014 invalid links exit with an error message\n- **4. HTTP \u2014 Send to Fireflies API** calls the Fireflies GraphQL addToLiveMeeting mutation\n- **5. Set \u2014 Build Success Response** prepares the confirmation message shown on screen\n- **6. Respond \u2014 Bot Invited Successfully** returns the confirmation page to the submitter\n- **7. Set \u2014 Build Error Response** prepares the error message for invalid links\n- **8. Respond \u2014 Invalid Link Error** returns the error page to the submitter\n\n## Set up steps\n1. In **4. HTTP \u2014 Send to Fireflies API** \u2014 replace YOUR_FIREFLIES_API_KEY in the Authorization header with your actual key from app.fireflies.ai under Integrations then API\n2. In **2. Set \u2014 Validate and Prepare Inputs** \u2014 update the default title from Sales Meeting - Incrementors to your own default\n3. Activate the workflow and bookmark the Form URL from node 1\n4. Share the form URL with your sales team"
      },
      "typeVersion": 1
    },
    {
      "id": "30ed9178-2679-4169-9fef-64742636d4bd",
      "name": "Section \u2014 Form Input and Link Validation1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -2272,
        144
      ],
      "parameters": {
        "color": 5,
        "width": 772,
        "height": 356,
        "content": "## Form Input and Link Validation\nForm collects meeting link, title, password, duration, and language. Inputs are cleaned with defaults applied. The IF node checks the link is non-empty and starts with http \u2014 invalid links route to the error path immediately."
      },
      "typeVersion": 1
    },
    {
      "id": "76e58703-3e58-46bf-a365-2b6216360f41",
      "name": "Section \u2014 Fireflies API Call and Success Response1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1408,
        80
      ],
      "parameters": {
        "color": 6,
        "width": 1028,
        "height": 388,
        "content": "## Fireflies API Call and Success Response\nGraphQL mutation sends the meeting link to Fireflies. On success, a confirmation page is shown to the submitter with the meeting title and a reminder to check the Fireflies dashboard."
      },
      "typeVersion": 1
    },
    {
      "id": "c1109d3a-a245-4be0-a6a6-f045efa512b3",
      "name": "Note \u2014 Fireflies API Key Required1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1920,
        592
      ],
      "parameters": {
        "color": 3,
        "width": 1004,
        "height": 140,
        "content": "## \u26a0\ufe0f Fireflies API Key Required\nReplace YOUR_FIREFLIES_API_KEY in the Authorization header. Get your key from app.fireflies.ai \u2014 go to Integrations, then API, then copy your Personal API Key."
      },
      "typeVersion": 1
    },
    {
      "id": "2100ecbd-7e06-4c8e-b5eb-5038b4b84c95",
      "name": "1. Form \u2014 Invite Fireflies Bot",
      "type": "n8n-nodes-base.formTrigger",
      "position": [
        -2208,
        272
      ],
      "parameters": {
        "options": {},
        "formTitle": "Invite Fireflies Bot to Sales Meeting",
        "formFields": {
          "values": [
            {
              "fieldLabel": "Meeting Link",
              "placeholder": "https://meet.google.com/xxx-xxxx-xxx",
              "requiredField": true
            },
            {
              "fieldLabel": "Meeting Title",
              "placeholder": "e.g. Sales Call - ClientName"
            },
            {
              "fieldLabel": "Meeting Password (if any)",
              "placeholder": "Leave blank if no password"
            },
            {
              "fieldType": "number",
              "fieldLabel": "Duration in Minutes",
              "placeholder": "60 (min 15, max 120)"
            },
            {
              "fieldType": "dropdown",
              "fieldLabel": "Meeting Language",
              "fieldOptions": {
                "values": [
                  {
                    "option": "en"
                  },
                  {
                    "option": "hi"
                  },
                  {
                    "option": "es"
                  },
                  {
                    "option": "fr"
                  },
                  {
                    "option": "pt"
                  }
                ]
              }
            }
          ]
        },
        "responseMode": "lastNode",
        "formDescription": "Enter your meeting details \u2014 the bot will automatically join and begin recording instantly."
      },
      "typeVersion": 2.2
    },
    {
      "id": "6739a7e5-61fb-4cd3-86e1-9323ef8a6bdf",
      "name": "2. Set \u2014 Validate and Prepare Inputs",
      "type": "n8n-nodes-base.set",
      "position": [
        -1952,
        272
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "assign-link",
              "name": "meeting_link",
              "type": "string",
              "value": "={{ $json['Meeting Link'].trim() }}"
            },
            {
              "id": "assign-title",
              "name": "meeting_title",
              "type": "string",
              "value": "={{ $json['Meeting Title'] || 'Sales Meeting - Incrementors' }}"
            },
            {
              "id": "assign-password",
              "name": "meeting_password",
              "type": "string",
              "value": "={{ $json['Meeting Password (if any)'] || '' }}"
            },
            {
              "id": "assign-duration",
              "name": "meeting_duration",
              "type": "number",
              "value": "={{ Math.min(Math.max(parseInt($json['Duration in Minutes']) || 60, 15), 120) }}"
            },
            {
              "id": "assign-language",
              "name": "meeting_language",
              "type": "string",
              "value": "={{ $json['Meeting Language'] || 'en' }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "58876f51-d0d0-4dd3-b3bd-1e1ac6cb9c46",
      "name": "3. IF \u2014 Valid Meeting Link?",
      "type": "n8n-nodes-base.if",
      "position": [
        -1696,
        272
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 1,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "link-not-empty",
              "operator": {
                "type": "string",
                "operation": "notEquals"
              },
              "leftValue": "={{ $json.meeting_link }}",
              "rightValue": ""
            },
            {
              "id": "link-starts-http",
              "operator": {
                "type": "boolean",
                "operation": "equals"
              },
              "leftValue": "={{ $json.meeting_link.startsWith('http') }}",
              "rightValue": true
            }
          ]
        }
      },
      "typeVersion": 2
    },
    {
      "id": "42280d1f-ea15-4476-96fb-f65b259a2728",
      "name": "4. HTTP \u2014 Send to Fireflies API",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        -1264,
        192
      ],
      "parameters": {
        "url": "https://api.fireflies.ai/graphql",
        "method": "POST",
        "options": {},
        "jsonBody": "={\n  \"query\": \"mutation AddToLiveMeeting($meetingLink: String!, $title: String, $duration: Int, $meetingPassword: String, $language: String) { addToLiveMeeting(meeting_link: $meetingLink, title: $title, duration: $duration, meeting_password: $meetingPassword, language: $language) { success } }\",\n  \"variables\": {\n    \"meetingLink\": \"{{ $json.meeting_link }}\",\n    \"title\": \"{{ $json.meeting_title }}\",\n    \"duration\": {{ $json.meeting_duration }},\n    \"meetingPassword\": \"{{ $json.meeting_password }}\",\n    \"language\": \"{{ $json.meeting_language }}\"\n  }\n}",
        "sendBody": true,
        "sendHeaders": true,
        "specifyBody": "json",
        "headerParameters": {
          "parameters": [
            {
              "name": "Content-Type",
              "value": "application/json"
            },
            {
              "name": "Authorization",
              "value": "Bearer YOUR_TOKEN_HERE"
            }
          ]
        }
      },
      "typeVersion": 4.2
    }
  ],
  "connections": {
    "3. IF \u2014 Valid Meeting Link?": {
      "main": [
        [
          {
            "node": "4. HTTP \u2014 Send to Fireflies API",
            "type": "main",
            "index": 0
          }
        ],
        []
      ]
    },
    "1. Form \u2014 Invite Fireflies Bot": {
      "main": [
        [
          {
            "node": "2. Set \u2014 Validate and Prepare Inputs",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "4. HTTP \u2014 Send to Fireflies API": {
      "main": [
        [
          {
            "node": "5. Set \u2014 Build Success Response",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "5. Set \u2014 Build Success Response": {
      "main": [
        [
          {
            "node": "6. Respond \u2014 Bot Invited Successfully",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "2. Set \u2014 Validate and Prepare Inputs": {
      "main": [
        [
          {
            "node": "3. IF \u2014 Valid Meeting Link?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}