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-Typeis alwaysapplication/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 with400. - Active Flag: Toggle delivery without deleting configuration.
Endpoint Overview
| Endpoint | Purpose |
|---|---|
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
httpsURL. Private, loopback, link-local, CGNAT, and cloud-metadata addresses are not delivered. Existing non-https rows remain visible onGETuntil you replace them. - Verify signatures: Store a shared secret in a header such as
AuthorizationorWebhook-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
2xxstatus 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
activeand that the location ID matches the appointments being created. - Multiple events per booking: Actions like rescheduling emit both
APPOINTMENT_RESCHEDULEDand a newNEW_APPOINTMENTfor the replacement slot, so handle idempotency by referencingappointment.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.
Updated 17 days ago
