{
  "name": "calendly-reminder-24hr",
  "nodes": [
    {
      "parameters": {
        "httpMethod": "POST",
        "path": "calendly-booking",
        "responseMode": "responseNode",
        "options": {}
      },
      "id": "webhook-calendly",
      "name": "Webhook (Calendly invitee.created)",
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 2,
      "position": [240, 300],
      "webhookId": "calendly-booking",
      "notes": "Configure this URL in Calendly: Account \u2192 Webhooks \u2192 Create new \u2192 Scope: User, Event: invitee.created. Paste the production URL of this webhook node."
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict"
          },
          "conditions": [
            {
              "id": "is-invitee-created",
              "leftValue": "={{ $json.body.event }}",
              "rightValue": "invitee.created",
              "operator": {
                "type": "string",
                "operation": "equals"
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "id": "if-event-type",
      "name": "Is invitee.created?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2,
      "position": [460, 300]
    },
    {
      "parameters": {
        "jsCode": "// Calendly sends event.start_time as ISO 8601 UTC.\n// Compute the moment we should fire the reminder: start_time minus 24 hours.\n// If that moment is already in the past (event is < 24 hr away when booked),\n// fire immediately by setting waitUntil to now.\n\nconst body = $input.item.json.body;\nconst startTime = body?.payload?.event?.start_time;\n\nif (!startTime) {\n  throw new Error('Missing payload.event.start_time in Calendly webhook payload');\n}\n\nconst startMs = new Date(startTime).getTime();\nconst remindMs = startMs - (24 * 60 * 60 * 1000);\nconst nowMs = Date.now();\nconst waitUntilMs = Math.max(remindMs, nowMs + 5000); // at least 5s out so the wait node behaves\nconst waitUntilIso = new Date(waitUntilMs).toISOString();\n\nreturn {\n  invitee_name:  body?.payload?.invitee?.name  || 'there',\n  invitee_email: body?.payload?.invitee?.email,\n  event_name:    body?.payload?.event_type?.name || 'our call',\n  event_start:   startTime,\n  event_start_local_hint: new Date(startTime).toUTCString(),\n  cancel_url:    body?.payload?.invitee?.cancel_url,\n  reschedule_url: body?.payload?.invitee?.reschedule_url,\n  meeting_join_url: body?.payload?.event?.location?.join_url || null,\n  wait_until:    waitUntilIso,\n  fired_immediately: waitUntilMs <= nowMs + 5000\n};\n"
      },
      "id": "compute-wait",
      "name": "Compute reminder time",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [680, 200]
    },
    {
      "parameters": {
        "resume": "specificTime",
        "dateTime": "={{ $json.wait_until }}",
        "options": {}
      },
      "id": "wait-until-24hr-before",
      "name": "Wait until 24 hr before",
      "type": "n8n-nodes-base.wait",
      "typeVersion": 1.1,
      "position": [900, 200],
      "webhookId": "calendly-reminder-resume"
    },
    {
      "parameters": {
        "sendTo": "={{ $('Compute reminder time').item.json.invitee_email }}",
        "subject": "=Reminder: our call is tomorrow \u2014 {{ $('Compute reminder time').item.json.event_name }}",
        "emailType": "text",
        "message": "=Hey {{ $('Compute reminder time').item.json.invitee_name }},\n\nQuick reminder \u2014 we're set to talk in about 24 hours.\n\n  When: {{ $('Compute reminder time').item.json.event_start_local_hint }}\n  Where: {{ $('Compute reminder time').item.json.meeting_join_url || 'Google Meet link is in the original calendar invite' }}\n\nIf something came up, no hard feelings:\n  Reschedule: {{ $('Compute reminder time').item.json.reschedule_url }}\n  Cancel: {{ $('Compute reminder time').item.json.cancel_url }}\n\nOtherwise, talk tomorrow.\n\n\u2014 Greg\nMeerkat LLC \u2022 Anna, Texas\n",
        "options": {}
      },
      "id": "gmail-send-reminder",
      "name": "Gmail: send 24-hr reminder",
      "type": "n8n-nodes-base.gmail",
      "typeVersion": 2.1,
      "position": [1120, 200],
      "credentials": {
        "gmailOAuth2": {
          "id": "REPLACE_WITH_GMAIL_CRED_ID",
          "name": "Gmail (ugwade8@gmail.com)"
        }
      }
    },
    {
      "parameters": {
        "respondWith": "json",
        "responseBody": "={ \"ok\": true, \"scheduled_for\": $('Compute reminder time').item.json.wait_until }",
        "options": {}
      },
      "id": "respond-success",
      "name": "Respond 200 OK",
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 1.1,
      "position": [680, 300]
    },
    {
      "parameters": {
        "respondWith": "json",
        "responseBody": "={ \"ok\": true, \"ignored\": $json.body.event }",
        "options": {}
      },
      "id": "respond-ignored",
      "name": "Respond 200 (ignored event)",
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 1.1,
      "position": [680, 420]
    }
  ],
  "connections": {
    "Webhook (Calendly invitee.created)": {
      "main": [
        [
          {
            "node": "Is invitee.created?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Is invitee.created?": {
      "main": [
        [
          {
            "node": "Compute reminder time",
            "type": "main",
            "index": 0
          },
          {
            "node": "Respond 200 OK",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Respond 200 (ignored event)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Compute reminder time": {
      "main": [
        [
          {
            "node": "Wait until 24 hr before",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Wait until 24 hr before": {
      "main": [
        [
          {
            "node": "Gmail: send 24-hr reminder",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "active": false,
  "settings": {
    "executionOrder": "v1",
    "saveExecutionProgress": true,
    "saveManualExecutions": true,
    "callerPolicy": "workflowsFromSameOwner"
  },
  "versionId": "",
  "meta": {
    "templateCredsSetupCompleted": false,
    "instanceId": ""
  },
  "id": "calendly-reminder-24hr",
  "tags": [
    { "name": "meerkat-llc" },
    { "name": "calendly" },
    { "name": "reminders" }
  ]
}
