> Calendly developer docs. For page Markdown, append .md to any URL.
> Index: https://developer.calendly.com/llms.txt
> API catalog: https://developer.calendly.com/.well-known/api-catalog
> OpenAPI: https://developer.calendly.com/openapi/calendly-api.yaml
> OAuth authorization server: https://calendly.com/.well-known/oauth-authorization-server
> MCP protected resource: https://mcp.calendly.com/.well-known/oauth-protected-resource
> Scheduling MCP endpoint: https://mcp.calendly.com
> Docs search MCP: https://developer.calendly.com/_mcp/server

# Webhooks

## Create a webhook subscription

Subscribe to `invitee.created` and `invitee.canceled` webhook events. Replace `token`, `org`, `user`, and `webhook_url` with values for your account.

```ruby
require 'faraday'
require 'json'

token       = '<your oauth token>'
org         = 'https://api.calendly.com/organizations/<org_uuid>'
user        = 'https://api.calendly.com/users/<user_uuid>'
webhook_url = '<your webhook endpoint>'
base_url    = 'https://api.calendly.com'

conn = Faraday.new(
  url: base_url,
  headers: {
    'Content-Type'  => 'application/json',
    'Authorization' => "Bearer #{token}"
  }
)

response = conn.post('/webhook_subscriptions') do |req|
  req.body = {
    url:          webhook_url,
    events:       ['invitee.created', 'invitee.canceled'],
    organization: org,
    user:         user,
    scope:        'user'
  }.to_json
end
```

## Receive webhook events and filter by event type

Calendly sends webhook events for all meetings booked through our platform. You can filter by a specific event type if you only want to process certain events.

```ruby
require 'sinatra'

EVENT_TYPE_FILTER = 'https://api.calendly.com/event_types/<uuid>'

post '/webhook' do
  request.body.rewind
  payload    = JSON.parse(request.body.read)
  event_type = payload['scheduled_event']['event_type']

  if event_type == EVENT_TYPE_FILTER
    puts '--Received webhook event from Calendly--'
    pp payload
  else
    puts '--Skipping webhook event--'
  end

  status :ok
end
```

Follow these [instructions](https://github.com/sinatra/sinatra) to get started with Sinatra. After that, save this to `webhook_receiver.rb` and run with:

```bash
$ ruby webhook_receiver.rb
```

## Use ngrok to listen for webhook events locally

You can use [ngrok](https://ngrok.com) to tunnel connections for local development. After starting ngrok, update the `webhook_url` in the subscription example above.

```bash
$ ngrok http 4567
```