AutomationFlowsWeb Scraping › Create a Calendly Availability API Endpoint for Real-time Scheduling Data

Create a Calendly Availability API Endpoint for Real-time Scheduling Data

ByOmer Fayyaz @omerfayyaz on n8n.io

This template is designed for developers, businesses, and service providers who need to programmatically check Calendly availability. It's perfect for: Web developers building custom booking interfaces that need real-time availability data Chatbot developers who want to suggest…

Webhook trigger★★★☆☆ complexity13 nodesHTTP Request
Web Scraping Trigger: Webhook Nodes: 13 Complexity: ★★★☆☆ Added:

This workflow corresponds to n8n.io template #11254 — we link there as the canonical source.

The workflow JSON

Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →

Download .json
{
  "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
          }
        ]
      ]
    }
  }
}

Credentials you'll need

Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.

Pro

For the full experience including quality scoring and batch install features for each workflow upgrade to Pro

About this workflow

This template is designed for developers, businesses, and service providers who need to programmatically check Calendly availability. It's perfect for: Web developers building custom booking interfaces that need real-time availability data Chatbot developers who want to suggest…

Source: https://n8n.io/workflows/11254/ — original creator credit. Request a take-down →

More Web Scraping workflows → · Browse all categories →

Related workflows

Workflows that share integrations, category, or trigger type with this one. All free to copy and import.

Web Scraping

Community Node Disclaimer: This workflow uses KlickTipp community nodes.

Crypto, Custom, N8N Nodes Klicktipp +1
Web Scraping

Automatically sync Fizzy cards to Basecamp todos in real-time. When cards are created, assigned, completed, or reopened in Fizzy, the changes sync instantly to your Basecamp project. Card tags determi

HTTP Request, N8N Nodes Basecamp
Web Scraping

This workflow automates accounts payable: upload a PDF invoice, let Claude AI extract the key fields, and automatically create a vendor bill (incoming invoice) in Odoo 18.

HTTP Request
Web Scraping

This n8n workflow automates airline customer support by classifying travel-related questions, fetching relevant information, generating AI answers, and delivering structured responses to users. It ens

HTTP Request
Web Scraping

This n8n template lets you automatically pull market data for the cryptocurrencies from CoinGecko every hour, calculate custom volatility and market-health metrics, classify each coin’s price action i

HTTP Request