Webhook Guide

Subscribe to appointment events and receive JSON payloads in your systems as they happen.

When to Use

  • Keep CRMs, marketing platforms, or BI tools in sync without polling.
  • Trigger custom automations (e.g., send swag kits when appointments are confirmed).
  • Receive notifications for failures in external systems.

Core Concepts

  • Location Scoped: Webhooks are created per location, so each header/payload is only sent for events at that location.
  • Triggers: Must be a subset of NEW_APPOINTMENT, APPOINTMENT_CONFIRMED, APPOINTMENT_CANCELLED, APPOINTMENT_RESCHEDULED, APPOINTMENT_REMINDER.
  • Headers: Optional key/value pairs appended to every delivery (use for auth tokens or tenant IDs).
  • Active Flag: Toggle delivery without deleting configuration.

Endpoint Overview

EndpointPurpose
GET /v3/webhook?locationId=<uuid>List webhooks for a location.
POST /v3/webhook?locationId=<uuid>Create a webhook (url, headers, triggers, active).
POST /v3/webhook/setWebhooks?locationId=<uuid>Replace the entire set for a location in one request.

All routes require company authentication. Requests are validated by the schemas under api/validations/webhook/.

Payload Structure

Deliveries are POST requests with body:

{
  "appointment": { ...appointment fields... },
  "trigger": "NEW_APPOINTMENT"
}

The appointment payload matches the object returned by the controller in processWebhooks. Sensitive internal fields are omitted.

Security Recommendations

  • Verify signatures: Store a shared secret in the headers you configure, or include an HMAC signature. The API echoes the headers you define.
  • Allowlist source IPs: Restrict your endpoint to OnSched IP ranges if possible.
  • Respond quickly: Return a 2xx status within a few seconds. Long-running work should happen asynchronously on your side.

Retry Behavior

Webhooks are sent once. If the destination responds with a non-2xx status or times out, an error is logged but the API does not automatically retry. If reliability is critical, relay deliveries through your own queue or monitor logs via observability tooling to reprocess failures.

Troubleshooting

  • Not receiving events: Ensure the webhook is active and that the location ID matches the appointments being created.
  • Multiple events per booking: Actions like rescheduling emit both APPOINTMENT_RESCHEDULED and a new NEW_APPOINTMENT for the replacement slot, so handle idempotency by referencing appointment.id.
  • Headers missing: Remember to send headers as a nested JSON object when creating or setting webhooks. Only string values are supported.

Webhooks keep downstream systems synchronized with zero polling, while the API enforces security and payload consistency.