Webhooks
Webhook payloads
The JSON body of every webhook event, field by field.
Envelope
Every body has the same envelope:
| Field | Notes |
|---|---|
event | Same value as the X-OnePath-Event header |
occurred_at | When OnePath recorded the event, ISO 8601 UTC |
notification_id | Unique per event occurrence. Use it to ignore duplicate deliveries. null on test sends |
test | true only for Send test webhook deliveries, which use sample data |
data | The appointment, or the conversation. See below |
Appointment payload
For appointment.created, appointment.rescheduled and appointment.cancelled:
{
"event": "appointment.rescheduled",
"occurred_at": "2026-07-22T09:50:03Z",
"notification_id": 2,
"test": false,
"data": {
"source": "onepath",
"id": 25,
"status": "rescheduled",
"time_window_begin": "2026-07-23T14:00:00Z",
"time_window_end": "2026-07-23T15:00:00Z",
"summary": "Booking a Small Drain / Repair service. The customer reports the drain is slow draining.",
"cancelled_reason": null,
"moved_from": "2026-07-22T14:00:00Z",
"service": { "id": 26, "name": "Small Drain / Repair", "service_type": "Repair", "serviceable_type": "Small Drain" },
"customer": {
"id": 1,
"full_name": "Jane Homeowner",
"contacts": [{ "type": "email", "value": "jane@example.com" }, { "type": "mobile_phone", "value": "5125550100" }]
},
"location": { "street": "2100 Barton Springs Rd", "unit": null, "city": "Austin", "state": "TX", "zip_code": "78704", "country": "US", "location_type": "residential" },
"attribution": {
"vendor": "google_ads", "external_id": "spring_campaign",
"utm_source": "google", "utm_medium": "cpc", "utm_campaign": "spring", "utm_term": null, "utm_content": null,
"campaign_url": "https://example.com/?utm_source=google",
"lead_source": { "type": "url", "value": "https://example.com/?utm_source=google" }
}
}
}
| Field | Notes |
|---|---|
data.source | Always onepath |
data.id | The appointment. The same id appears again on its cancelled or rescheduled event |
data.status | scheduled, rescheduled, cancelled, or done |
data.time_window_begin / time_window_end | The appointment window, ISO 8601 UTC. On rescheduled these are the new times |
data.summary | The booking summary your team sees. Includes the package or offer passed as booking context |
data.cancelled_reason | Set on appointment.cancelled, otherwise null |
data.moved_from | On appointment.rescheduled, when the old window began, ISO 8601 UTC. Otherwise null |
data.service | name is the full display name; service_type and serviceable_type match the Services page |
data.customer.contacts | One entry per contact; type is email, phone, or mobile_phone |
data.location | The service address and location_type (residential or commercial). null when the appointment has no address on file |
data.attribution | null when the visit carried no campaign data. lead_source may also be null |
Treat location, attribution, and attribution.lead_source as optional in your parser.
Call and hand-off payload
For call.emergency, call.callback_overdue, call.unbooked and task.handed_to_account, data is the conversation, with no appointment:
{
"conversation_id": 42,
"customer": { "id": 9, "full_name": "Jane Homeowner", "contacts": [{ "type": "phone", "value": "5125550100" }] },
"caller_number": "(512) 555-0100",
"summary": "The customer wants a manager to call about last week's visit.",
"link": "https://app.onepath.ai/interactions/42",
"task": { "id": 7, "type": "complaint", "list": "service", "hand_over_note": "The customer wants a manager to call about last week's visit." }
}
| Field | Notes |
|---|---|
caller_number | The number of the conversation's latest call, formatted for reading. null when there was no call, as on a hand-off from chat |
summary | The hand-over note on a task, otherwise the call's summary |
link | Where your team picks it up in OnePath |
task | Set on call.callback_overdue and task.handed_to_account. null on call.emergency and call.unbooked |
task.type | complaint, urgent_appointment_request, follow_up, property_owner_verification, appointment_reschedule, appointment_cancel, ai_failed, message_sending_failed, job_application, or other |
task.list | The escalation topic it went to: accounting, service, recruiting, or other |