Skip to main content

Webhooks

Registering a webhook

Visit the Webhooks page in the SavvyCal Dashboard and follow the prompts to register a new webhook.

For platforms, register webhooks on the platform settings page under the "Platform webhooks" section.

Listening for events

When an event occurs that triggers a webhook, we will send an HTTP POST to the URL you specified, with a JSON-encoded body of this shape:

POST /my-webhook-receiver HTTP/1.1

host: https://myapp.com
user-agent: SavvyCal Webhooks (https://savvycal.app)
x-savvycal-signature: sha256=6CAA4DEF5C3463B785E885FF19B8987B348E19399D2C5FB291274EDFA7128105
x-savvycal-webhook-id: wh_XXXXXXXXXX
content-type: application/json

{
"id": "evt_d025a96ac0c6",
"account_id": "acct_d025a96ac0c6",
"version": "1.0",
"created_at": "2025-03-12T12:34:55Z",
"data": {
"type": "appointment.created",
"object": {...}
}
}

Event types

The following event types are available. The Schema definitions referenced in the table below represent the shape of the data field in the webhook payload.

Event TypeDescription
account_user.createdEmitted when a new account user is created. (Schema)
account_user.deletedEmitted when an account user is removed. (Schema)
account_user.updatedEmitted when an existing account user is updated. (Schema)
appointment.createdEmitted when a new appointment is created. (Schema)
appointment.rescheduledEmitted when an existing appointment is rescheduled. (Schema)
appointment.canceledEmitted when an existing appointment is canceled. (Schema)
appointment.confirmedEmitted when an existing appointment is confirmed. (Schema)
appointment.deletedEmitted when an existing appointment is deleted. (Schema)
booking_intent.abandonedEmitted when a booking intent is abandoned. (Schema)
booking_intent.completedEmitted when a booking intent is completed. (Schema)
booking_intent.createdEmitted when a new booking intent is created. (Schema)
booking_intent.updatedEmitted when an existing booking intent is updated. (Schema)
block.createdEmitted when a new block is created. (Schema)
block.updatedEmitted when an existing block is updated. (Schema)
block.deletedEmitted when an existing block is deleted. (Schema)
client.createdEmitted when a new client is created. (Schema)
client.deletedEmitted when a client is deleted. (Schema)
client.updatedEmitted when an existing client is updated. (Schema)
connected_account.createdEmitted when a new calendar integration is connected. (Schema)
connected_account.deletedEmitted when a calendar integration is disconnected. (Schema)
connected_account.refresh_failedEmitted when an OAuth token refresh permanently fails. (Schema)
connected_account.reconnectedEmitted when a previously failed integration is reconnected. (Schema)
provider.createdEmitted when a new provider is created. (Schema)
provider.deactivatedEmitted when a provider is deactivated. (Schema)
provider.reactivatedEmitted when a previously deactivated provider is reactivated. (Schema)
provider.updatedEmitted when an existing provider is updated. (Schema)
provider_schedule.createdEmitted when a new provider schedule is created. (Schema)
provider_schedule.deletedEmitted when a provider schedule is deleted. (Schema)
provider_schedule.updatedEmitted when an existing provider schedule is updated. (Schema)
service.createdEmitted when a new service is created. (Schema)
service.deletedEmitted when a service is deleted. (Schema)
service.updatedEmitted when an existing service is updated. (Schema)
service_provider.createdEmitted when a provider is added to a service. (Schema)
service_provider.deletedEmitted when a provider is removed from a service. (Schema)

Sensitive fields

Webhook payloads err on the side of caution when it comes to personally identifiable information. Fields like first_name, last_name, email, and phone on client objects will be null in webhook payloads.

If you need access to these fields, fetch the full record via the API after receiving the webhook. For example, after receiving a client.created event, you can call GET /v1/clients/:id to retrieve the complete client data.