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). Hop-by-hop and cloud-metadata header names are rejected. Content-Type is always application/json.
  • Destination: Must be public https. Query strings are allowed. http, credentials in the URL, fragments, IP literals, localhost, and internal/metadata hosts are rejected with 400.
  • 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. Create and replace requests reject destinations that are not public https.

Payload Structure

Deliveries are POST requests with body:

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

The appointment payload matches the appointment object used when the event is dispatched, plus trigger.

Security Recommendations

  • Use public HTTPS: The destination must be a globally reachable https URL. Private, loopback, link-local, CGNAT, and cloud-metadata addresses are not delivered. Existing non-https rows remain visible on GET until you replace them.
  • Verify signatures: Store a shared secret in a header such as Authorization or Webhook-Secret. The API echoes the headers you define, except hop-by-hop and metadata names (Host, Cookie, Metadata-Flavor, and similar).
  • Allowlist source IPs: Restrict your endpoint to OnSched IP ranges if possible.
  • Respond quickly: Return a 2xx status within about five seconds. Long-running work should happen asynchronously on your side. Redirects are not followed.

Retry Behavior

Webhooks are sent once. If the destination responds with a non-2xx status, times out (~5 seconds), or is not an allowed public https URL, an error is logged but the API does not automatically retry and the appointment change still succeeds. 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.


Did this page help you?