{
  "id": "oYwsgPiHu1rbAnF3",
  "name": "Calendly Availability Checker",
  "tags": [],
  "nodes": [
    {
      "id": "9f5a31b3-8662-4c93-b7e8-15f9612ef3e0",
      "name": "\ud83d\udccb WORKFLOW OVERVIEW",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -192,
        480
      ],
      "parameters": {
        "color": 5,
        "width": 440,
        "height": 496,
        "content": "## \ud83d\uddd3\ufe0f Calendly Availability Checker\n\n**What this workflow does:**\n1. \ud83d\udd10 Authenticates with Calendly API\n2. \ud83d\udc64 Gets your user information\n3. \ud83d\udccb Lists all your event types\n4. \u23f0 Checks real-time availability for next 7 days\n5. \ud83d\udcca Returns formatted availability data\n\n**Use Cases:**\n- Display available slots on your website\n- Check availability before suggesting times\n- Build custom booking interfaces\n- Integrate with chatbots for scheduling\n\n**Trigger Options:**\n- Webhook (API call)\n- Manual (for testing)\n- Schedule (periodic checks)"
      },
      "typeVersion": 1
    },
    {
      "id": "884e26b4-9f13-4d49-bfa2-3e86f37b6b30",
      "name": "\u2699\ufe0f SETUP GUIDE",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1200,
        480
      ],
      "parameters": {
        "color": 6,
        "width": 448,
        "height": 488,
        "content": "## \u2699\ufe0f Setup Instructions\n\n**Step 1: Calendly Credentials**\n1. Go to calendly.com/integrations\n2. Click \"API & Webhooks\"\n3. Create Personal Access Token\n   OR set up OAuth2 app\n4. In n8n, create credential:\n   - Type: \"Calendly OAuth2 API\"\n   - Follow OAuth flow\n\n**Step 2: Configure Workflow**\n1. Update credential in HTTP nodes\n2. Test \"Get Current User\" first\n3. Verify event types are returned\n\n**Step 3: Customize (Optional)**\n- Change date range (default: 7 days)\n- Filter specific event types\n- Add response formatting\n\n---"
      },
      "typeVersion": 1
    },
    {
      "id": "dfb1be1c-9d70-420b-a6fc-491935039ebe",
      "name": "Webhook Trigger",
      "type": "n8n-nodes-base.webhook",
      "notes": "POST /check-calendly-availability\nOptional body: { \"event_type_uri\": \"...\" }",
      "position": [
        320,
        528
      ],
      "parameters": {
        "path": "check-calendly-availability",
        "options": {},
        "httpMethod": "POST",
        "responseMode": "responseNode"
      },
      "typeVersion": 2
    },
    {
      "id": "d4c04dcb-99d3-4a69-a459-99fe3e1735fa",
      "name": "\ud83c\udfaf TRIGGERS",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -192,
        1008
      ],
      "parameters": {
        "color": 6,
        "width": 436,
        "height": 316,
        "content": "## \ud83c\udfaf Triggers\n\n**Webhook POST Body:**\n```json\n{\n  \"event_type_uri\": \"optional\",\n  \"days_ahead\": 7\n}\n```\n\nIf no event_type_uri provided,\nuses first active event type."
      },
      "typeVersion": 1
    },
    {
      "id": "a443b254-4970-4e23-8bff-d1498a356b01",
      "name": "Set Configuration",
      "type": "n8n-nodes-base.set",
      "notes": "Extract optional parameters from request",
      "position": [
        560,
        528
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "cfg1",
              "name": "requested_event_type",
              "type": "string",
              "value": "={{ $json.body?.event_type_uri || '' }}"
            },
            {
              "id": "cfg2",
              "name": "days_ahead",
              "type": "number",
              "value": "={{ $json.body?.days_ahead || 7 }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "8bafde54-7d0f-43cc-b939-ea7dd7fe67dd",
      "name": "Get Current User",
      "type": "n8n-nodes-base.httpRequest",
      "notes": "GET /users/me",
      "onError": "continueRegularOutput",
      "position": [
        800,
        528
      ],
      "parameters": {
        "url": "https://api.calendly.com/users/me",
        "options": {
          "response": {
            "response": {}
          }
        },
        "authentication": "predefinedCredentialType",
        "nodeCredentialType": "calendlyOAuth2Api"
      },
      "credentials": {
        "calendlyOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.3
    },
    {
      "id": "9d75a542-8b3a-4094-a275-bb57130b706b",
      "name": "Extract User Info",
      "type": "n8n-nodes-base.set",
      "notes": "Parse user data from response",
      "position": [
        560,
        752
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "u1",
              "name": "user_uri",
              "type": "string",
              "value": "={{ $json.resource?.uri }}"
            },
            {
              "id": "u2",
              "name": "user_name",
              "type": "string",
              "value": "={{ $json.resource?.name }}"
            },
            {
              "id": "u3",
              "name": "user_email",
              "type": "string",
              "value": "={{ $json.resource?.email }}"
            },
            {
              "id": "u4",
              "name": "organization_uri",
              "type": "string",
              "value": "={{ $json.resource?.current_organization }}"
            },
            {
              "id": "u5",
              "name": "scheduling_url",
              "type": "string",
              "value": "={{ $json.resource?.scheduling_url }}"
            }
          ]
        },
        "includeOtherFields": true
      },
      "typeVersion": 3.4
    },
    {
      "id": "92a97501-5f67-4a4a-8ffc-9d506eee4532",
      "name": "Get Event Types",
      "type": "n8n-nodes-base.httpRequest",
      "notes": "GET /event_types?user={uri}&active=true",
      "onError": "continueRegularOutput",
      "position": [
        800,
        752
      ],
      "parameters": {
        "url": "https://api.calendly.com/event_types",
        "options": {},
        "sendQuery": true,
        "authentication": "predefinedCredentialType",
        "queryParameters": {
          "parameters": [
            {
              "name": "user",
              "value": "={{ $json.user_uri }}"
            },
            {
              "name": "active",
              "value": "true"
            }
          ]
        },
        "nodeCredentialType": "calendlyOAuth2Api"
      },
      "credentials": {
        "calendlyOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.3
    },
    {
      "id": "222a18e8-f366-4e92-a950-9ea75387cdc9",
      "name": "Select Event Type",
      "type": "n8n-nodes-base.set",
      "notes": "Select requested or first event type",
      "position": [
        560,
        992
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "et1",
              "name": "event_types_count",
              "type": "number",
              "value": "={{ ($json.collection || []).length }}"
            },
            {
              "id": "et2",
              "name": "event_types_list",
              "type": "array",
              "value": "={{ ($json.collection || []).map(e => ({ uri: e.uri, name: e.name, duration: e.duration, slug: e.slug })) }}"
            },
            {
              "id": "et3",
              "name": "selected_event_type_uri",
              "type": "string",
              "value": "={{ $('Set Configuration').item.json.requested_event_type || ($json.collection && $json.collection.length > 0 ? $json.collection[0].uri : '') }}"
            },
            {
              "id": "et4",
              "name": "selected_event_type_name",
              "type": "string",
              "value": "={{ $json.collection && $json.collection.length > 0 ? $json.collection[0].name : 'No event types' }}"
            },
            {
              "id": "et5",
              "name": "selected_event_duration",
              "type": "number",
              "value": "={{ $json.collection && $json.collection.length > 0 ? $json.collection[0].duration : 0 }}"
            }
          ]
        },
        "includeOtherFields": true
      },
      "typeVersion": 3.4
    },
    {
      "id": "9aab3b00-d855-4ea2-9389-e2b43c0c7d94",
      "name": "Get Available Times",
      "type": "n8n-nodes-base.httpRequest",
      "notes": "GET /event_type_available_times",
      "onError": "continueRegularOutput",
      "position": [
        800,
        992
      ],
      "parameters": {
        "url": "https://api.calendly.com/event_type_available_times",
        "options": {},
        "sendQuery": true,
        "authentication": "predefinedCredentialType",
        "queryParameters": {
          "parameters": [
            {
              "name": "event_type",
              "value": "={{ $json.selected_event_type_uri }}"
            },
            {
              "name": "start_time",
              "value": "={{ new Date(Date.now() + 1 * 24 * 60 * 60 * 1000).toISOString() }}"
            },
            {
              "name": "end_time",
              "value": "={{ new Date(Date.now() + ($('Set Configuration').item.json.days_ahead || 7) * 24 * 60 * 60 * 1000).toISOString() }}"
            }
          ]
        },
        "nodeCredentialType": "calendlyOAuth2Api"
      },
      "credentials": {
        "calendlyOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.3
    },
    {
      "id": "dabe7159-de5b-45a6-bdaa-eeffe493f3f0",
      "name": "Format Availability",
      "type": "n8n-nodes-base.set",
      "notes": "Format slots for easy consumption",
      "position": [
        560,
        1232
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "av1",
              "name": "total_slots_available",
              "type": "number",
              "value": "={{ ($json.collection || []).length }}"
            },
            {
              "id": "av2",
              "name": "has_availability",
              "type": "boolean",
              "value": "={{ ($json.collection || []).length > 0 }}"
            },
            {
              "id": "av3",
              "name": "next_available_slot",
              "type": "string",
              "value": "={{ ($json.collection && $json.collection.length > 0) ? $json.collection[0].start_time : null }}"
            },
            {
              "id": "av4",
              "name": "next_available_formatted",
              "type": "string",
              "value": "={{ ($json.collection && $json.collection.length > 0) ? new Date($json.collection[0].start_time).toLocaleString('en-US', { weekday: 'long', month: 'short', day: 'numeric', hour: '2-digit', minute: '2-digit' }) : 'No slots available' }}"
            },
            {
              "id": "av5",
              "name": "available_slots",
              "type": "array",
              "value": "={{ ($json.collection || []).slice(0, 20).map(slot => ({ start_time: slot.start_time, formatted: new Date(slot.start_time).toLocaleString('en-US', { weekday: 'short', month: 'short', day: 'numeric', hour: '2-digit', minute: '2-digit' }), booking_url: slot.scheduling_url })) }}"
            },
            {
              "id": "av6",
              "name": "slots_by_day",
              "type": "object",
              "value": "={{ Object.entries(($json.collection || []).reduce((acc, slot) => { const day = new Date(slot.start_time).toLocaleDateString('en-US', { weekday: 'long', month: 'short', day: 'numeric' }); if (!acc[day]) acc[day] = []; acc[day].push({ time: new Date(slot.start_time).toLocaleTimeString('en-US', { hour: '2-digit', minute: '2-digit' }), url: slot.scheduling_url }); return acc; }, {})).reduce((obj, [k, v]) => { obj[k] = v; return obj; }, {}) }}"
            }
          ]
        },
        "includeOtherFields": true
      },
      "typeVersion": 3.4
    },
    {
      "id": "f67a6696-b3b0-4ad2-a38c-f9040aaba04c",
      "name": "Respond with Availability",
      "type": "n8n-nodes-base.respondToWebhook",
      "notes": "Returns comprehensive availability data",
      "position": [
        992,
        1232
      ],
      "parameters": {
        "options": {
          "responseCode": 200,
          "responseHeaders": {
            "entries": [
              {
                "name": "Content-Type",
                "value": "application/json"
              }
            ]
          }
        },
        "respondWith": "json",
        "responseBody": "={\n  \"success\": true,\n  \"user\": {\n    \"name\": \"{{ $('Extract User Info').item.json.resource.name }}\",\n    \"email\": \"{{ $('Extract User Info').item.json.resource.email }}\",\n    \"scheduling_url\": \"{{ $('Extract User Info').item.json.resource.scheduling_url }}\"\n  },\n  \"event_type\": {\n    \"name\": \"{{ $('Select Event Type').item.json.selected_event_type_name }}\",\n    \"duration_minutes\": {{ $('Select Event Type').item.json.selected_event_duration }},\n    \"uri\": \"{{ $('Select Event Type').item.json.selected_event_type_uri }}\"\n  },\n  \"availability\": {\n    \"has_slots\": {{ $json.has_availability }},\n    \"total_slots\": {{ $json.total_slots_available }},\n    \"next_available\": \"{{ $json.next_available_formatted }}\",\n    \"next_available_iso\": {{ $json.next_available_slot ? '\"' + $json.next_available_slot + '\"' : 'null' }}\n  },\n  \"slots\": {{ JSON.stringify($json.available_slots) }},\n  \"slots_by_day\": {{ JSON.stringify($json.slots_by_day) }},\n  \"all_event_types\": {{ JSON.stringify($('Select Event Type').item.json.event_types_list) }},\n  \"checked_at\": \"{{ new Date().toISOString() }}\"\n}"
      },
      "typeVersion": 1.1
    },
    {
      "id": "11b7d4fb-b6ce-479a-b8c7-bbfcb6b3dea9",
      "name": "\ud83d\udce4 RESPONSE FORMAT",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1200,
        992
      ],
      "parameters": {
        "color": 5,
        "width": 452,
        "height": 372,
        "content": "## \ud83d\udce4 Response Format\n\n```json\n{\n  \"success\": true,\n  \"user\": { ... },\n  \"event_type\": { ... },\n  \"availability\": {\n    \"has_slots\": true,\n    \"total_slots\": 45,\n    \"next_available\": \"Mon, Dec 2, 10:00 AM\"\n  },\n  \"slots\": [...],\n  \"slots_by_day\": {\n    \"Monday, Dec 2\": [...],\n    \"Tuesday, Dec 3\": [...]\n  }\n}\n```"
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "4e611e92-190b-4e4d-9b3a-270808b3be07",
  "connections": {
    "Get Event Types": {
      "main": [
        [
          {
            "node": "Select Event Type",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Webhook Trigger": {
      "main": [
        [
          {
            "node": "Set Configuration",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Current User": {
      "main": [
        [
          {
            "node": "Extract User Info",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Extract User Info": {
      "main": [
        [
          {
            "node": "Get Event Types",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Select Event Type": {
      "main": [
        [
          {
            "node": "Get Available Times",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Set Configuration": {
      "main": [
        [
          {
            "node": "Get Current User",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Format Availability": {
      "main": [
        [
          {
            "node": "Respond with Availability",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Available Times": {
      "main": [
        [
          {
            "node": "Format Availability",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}