automationtutorialscheduling

Automate Demo Scheduling with Cal.com, HubSpot, and n8n

TL;DR

Trigger an n8n webhook on every Cal.com booking, then upsert the contact and create a deal in HubSpot automatically, so no rep ever has to manually log a scheduled demo again.

On this page

Every RevOps team I’ve worked with has the same manual leak. An AE books a demo, Cal.com sends the prospect a confirmation, and then someone (usually the AE, sometimes an SDR coordinator) manually creates a HubSpot contact, logs a meeting, and maybe remembers to push a deal into the pipeline. That gap between “booking confirmed” and “CRM updated” is where deals get lost, forecasts go stale, and attribution breaks. This tutorial closes that gap completely using Cal.com, n8n, and HubSpot, with a workflow you can build in under an hour.

Why These Three Tools Together

Cal.com fires a webhook the instant a booking is created, rescheduled, or cancelled. n8n catches that webhook, lets you reshape the payload however you need, and then calls HubSpot’s API to upsert the contact and create or update a deal. No Zapier tax. No black-box integration that breaks when Cal.com renames a field.

I’ve run this stack at several clients now. What makes it durable is that n8n gives you the raw JSON from Cal.com with nothing stripped out. Calendly’s native HubSpot app maps a small, fixed set of fields and gives you no flexibility. Cal.com’s own HubSpot app in the App Store creates contacts but does not touch deals or pipeline stage at all. That matters a lot when your RevOps motion requires deal creation at the moment of booking, not after the call ends.

0
Deal creation steps
Manual steps your reps take after a booking fires through this workflow
~40min
Build time
Realistic time to build and test this workflow from scratch in n8n
$0
Per-execution cost
n8n self-hosted runs unlimited executions; no Zapier-style task billing
Step 1
Enable webhooks on Cal.com and grab the endpoint

In Cal.com, go to Settings > Developer > Webhooks and create a new webhook. Subscribe to BOOKING_CREATED, BOOKING_RESCHEDULED, and BOOKING_CANCELLED events. Leave the endpoint URL blank for now since you need the n8n URL first. Cal.com sends a JSON payload with attendee name, email, event type, start time, and any custom booking questions you have configured.

Step 2
Create the webhook trigger node in n8n

In n8n, add a Webhook node as your trigger. Set the HTTP method to POST. Copy the production webhook URL n8n generates and paste it back into Cal.com as the endpoint. Set authentication to Header Auth and add a shared secret, then mirror that secret in Cal.com's webhook signature field. n8n will verify every incoming payload before processing it.

Step 3
Parse the payload and branch on event type

Add a Switch node after the webhook trigger. Branch on the triggerEvent field: one branch for BOOKING_CREATED, one for BOOKING_RESCHEDULED, one for BOOKING_CANCELLED. This keeps your logic clean and lets you handle cancellations separately (for example, moving a HubSpot deal back to a prior stage rather than creating a duplicate).

Step 4
Upsert the HubSpot contact from attendee data

On the BOOKING_CREATED branch, add a HubSpot node set to the 'Upsert Contact' operation. Map the Cal.com payload fields: attendees[0].email to Email, attendees[0].name split into firstname and lastname, and any custom booking questions to custom HubSpot properties you have created. The upsert prevents duplicates when a returning prospect books a second demo.

Step 5
Create the deal and associate it to the contact

After the contact upsert node, add a second HubSpot node set to 'Create Deal'. Set dealname using an n8n expression, something like 'Demo, [eventTitle], [attendee email]'. Set dealstage to the pipeline-specific GUID for your 'Demo Scheduled' stage. Grab that ID from HubSpot's pipeline settings or via a GET /crm/v3/pipelines call. Then add a third HubSpot node to associate the deal with the contact ID returned in step four.

Step 6
Handle rescheduled and cancelled bookings

On the BOOKING_RESCHEDULED branch, search HubSpot for an existing deal by the original booking UID (stored as a custom property in step five), then update the closedate and a custom 'Demo Date' property to the new time. On BOOKING_CANCELLED, find the deal by UID and move it to an 'At Risk' or 'No Show' stage. Your pipeline stays accurate without reps touching anything.

n8n workflow canvas with webhook trigger, switch node, and downstream HubSpot integration nodes
The n8n workflow canvas showing the webhook trigger branching into enrichment and HubSpot nodes, a pattern directly applicable to the Cal.com booking flow above.

The Gotchas That Will Burn You

Two fields trip people up every single time: the attendee array structure and HubSpot’s deal stage IDs.

Cal.com sends attendees as an array even when there is only one person. You always reference attendees[0].email in your n8n expressions, never attendee.email. Get that wrong and your contact upsert silently maps a blank email, which means HubSpot either creates a junk contact or throws a 400 and the whole execution fails.

The deal stage issue is worse. HubSpot stage IDs are pipeline-specific GUIDs, not human-readable strings. Hardcoding "Demo Scheduled" as the stage value will return a 400 from the HubSpot API every time. n8n marks the execution failed, your webhook already fired, your contact was created, but no deal exists. The pipeline looks clean while the CRM is actually missing data. Per the HubSpot Deals API docs, you need the actual stageId value from a GET call against your pipeline.

Common trap: Setting the HubSpot deal stage to a label string like "Demo Scheduled" or "demo_scheduled" returns a 400 error. This is especially painful in production because your contact was created successfully, but no deal exists. Your pipeline looks clean while your CRM is missing data.

Also watch for Cal.com’s webhook retries. If n8n takes more than 10 seconds to respond, Cal.com will retry the webhook and you may create duplicate deals. Return a 200 immediately from n8n’s respond node and handle the HubSpot work after, or add a deduplication check on the booking UID before the deal creation node.

// Cal.com webhook payload shape (abbreviated)
{
  "triggerEvent": "BOOKING_CREATED",
  "uid": "abc123xyz",
  "title": "Product Demo",
  "startTime": "2026-08-01T14:00:00Z",
  "attendees": [
    {
      "name": "Jane Smith",
      "email": "jane@acme.com",
      "timeZone": "America/New_York"
    }
  ],
  "responses": {
    "company": { "value": "Acme Corp" },
    "phone": { "value": "+14155551234" }
  }
}

// n8n expression to get stage ID via API
// GET https://api.hubapi.com/crm/v3/pipelines/deals
// Find your pipeline, copy stageId from the stages array
// e.g. "stageId": "12345678"

One more thing I always add: a Slack notification node at the end of the BOOKING_CREATED branch that posts to a #demos-scheduled channel with the attendee name, company, and a direct link to the HubSpot deal. Reps love it. It also doubles as a live sanity check that the workflow is actually firing. If the Slack message stops coming, something broke upstream.

Which Scheduling Tool Belongs in Your Stack

If you are evaluating Cal.com versus Calendly or Chili Piper for this kind of workflow, the answer mostly comes down to routing requirements and how much you want to own the integration layer. I covered the broader forms and routing decision in detail here, but for the purposes of this specific workflow, the short version is:

Which scheduling tool fits this n8n workflow best?

Choose Cal.com if

  • You want webhook-level control over the full booking payload
  • Your team is cost-sensitive and wants a self-hostable option
  • You are comfortable building the HubSpot integration layer yourself in n8n
Free individual, Team from $12/mo per user Try Cal.com →

Choose Calendly if

  • Your reps already live in Calendly and a migration is not worth the friction
  • You only need basic contact creation in HubSpot, not deal pipeline management
  • You want a larger native integration library without custom middleware
Free, Standard $10/mo per user Try Calendly →

Choose Chili Piper if

  • You need inbound lead routing with round-robin logic at the moment of form submit
  • You are on HubSpot Sales Hub Pro or Enterprise and want native routing rules
  • Demo volume is high enough to justify the per-seat pricing premium
From $30/seat/mo plus platform fee Try Chili Piper →

Extending the Workflow

Once the core booking-to-deal flow is live, the natural extensions are enrichment and sequencing. On the BOOKING_CREATED branch, after you upsert the HubSpot contact, add a Clay or Apollo enrichment step to backfill company size, industry, and LinkedIn URL before your AE ever opens the CRM record. This matters most when prospects book through a self-serve link and only provide name and email. You want your reps walking into a demo with context, not a blank contact.

For post-demo follow-up, wire the deal creation into a HubSpot workflow that auto-enrolls the contact in a follow-up sequence the moment the deal enters “Demo Scheduled” stage. My clients who have built this combination have cut average time-to-follow-up from 8 hours to under 10 minutes. The n8n workflow handles the CRM work. HubSpot’s sequences engine handles the outreach from there. Neither system needs a human to trigger it.

According to HubSpot Research’s State of Sales 2024, reps spend an average of 21% of their week on manual data entry. This workflow does not eliminate all of that, but it removes one of the highest-friction examples entirely.

If you are building out a broader automated pipeline from cold outreach through to booked demo, this workflow connects cleanly to what I described in the Instantly to Pipedrive via n8n tutorial. Just swap Pipedrive for HubSpot as the CRM target and the pattern holds.

The workflow itself is not complicated. But it requires getting three specific things right: a reliable webhook from Cal.com per the Cal.com webhooks documentation, clean payload parsing in n8n, and correct deal stage IDs in HubSpot. Nail those three and you have a demo scheduling motion that feeds your CRM automatically, keeps your pipeline accurate in real time, and removes a manual step that reps resent doing anyway.

Sources

Filed under:

automationtutorialscheduling

Frequently asked questions

Can Cal.com send booking data directly to HubSpot?

Cal.com has a native HubSpot integration in its App Store, but it only creates contacts, not deals or pipeline stages. For full deal creation and custom field mapping you need a middleware layer like n8n.

Do I need a paid Cal.com plan to use webhooks?

Webhooks are available on Cal.com's Team plan and above. The free individual plan does not expose webhook configuration in the UI.

How is this different from using Zapier with Cal.com?

n8n runs on your own infrastructure or cloud instance, so there are no per-task charges. A busy sales team booking 500 demos a month on Zapier Professional adds up fast; n8n's self-hosted tier costs nothing per execution.

What HubSpot tier do I need for this workflow?

The workflow uses the HubSpot API directly via n8n's HubSpot node, so any HubSpot tier with API access works, including Starter. You do not need Sales Hub Professional for this specific automation.

Can I route bookings to different pipelines based on event type?

Yes. Add an n8n IF node after the webhook trigger that checks the eventTitle field from the Cal.com payload, then branch to different HubSpot deal creation nodes per pipeline.


← Back to Blog

Enjoying this? Share it with your team.

Some links are affiliate links. Disclosure.