Webhooks

Webhook events

OnePath sends a JSON POST to your URL when an appointment changes, a call needs attention, or a conversation is handed to your team.

POST https://example.com/onepath/webhooks/9f2c1a7e
Content-Type: application/json
X-OnePath-Event: appointment.created
import express from 'express';

const app = express();

app.post('/onepath/webhooks/:secret', express.json(), (req, res) => {
  if (req.params.secret !== process.env.ONEPATH_WEBHOOK_SECRET) return res.sendStatus(404);

  res.sendStatus(200);                        // acknowledge first; OnePath waits 10 seconds

  const event = req.get('X-OnePath-Event');   // appointment.created, call.emergency, ... (see Events)
  const { notification_id, test, data } = req.body;
  if (test) return;                           // "Send test webhook" deliveries carry sample data

  // dedupe on notification_id, then branch on event:
  // appointment.* has data.id (the appointment); call.* and task.* have data.conversation_id
});

Turn it on

A URL on an event's list is what turns it on. There is no switch and no Save button: the list saves itself, and removing the URL turns the event off for that endpoint.

  1. Go to Account settings → AI & Alerts → Notifications.
  2. On the event's row, type your http:// or https:// URL into Add email, phone or webhook URL and press Enter.
  3. Click Send test webhook on that row.

Each row has its own list, so creations can go to one system and cancellations to another. A CRM needs all three appointment.* rows, or it keeps showing appointments that no longer exist.

task.handed_to_account has no row there. Add the URL to a topic's list under Escalations instead.

Events

X-OnePath-EventFired whenSet on
appointment.createdA booking is createdNew booking
appointment.rescheduledAn appointment moves to a new timeReschedule
appointment.cancelledAn appointment is cancelledCancellation
call.emergencyA caller reported an emergency, booked or notEmergency call
call.callback_overdueAn escalation passed the promised call-back window without being marked called backCall back overdue
call.unbookedA bookable caller hung up without a bookingUnbooked call
task.handed_to_accountA conversation is handed to the account's own teamA topic list on Escalations
  • appointment.* fire per appointment, not per lead, and only for changes made through OnePath: by the AI assistant, the online scheduler, or someone working a task in OnePath.
  • A change made directly in the field service software sends nothing. Neither does moving or cancelling, through OnePath, a visit that was booked directly there.
  • Each call.* event fires at most once for the same conversation or task.
  • A visitor who leaves your site without booking sends nothing. For that, use the browser events.

Request

  • POST, Content-Type: application/json, header X-OnePath-Event with the event name. The body's event field repeats it.
  • Your URL must be http(s); use HTTPS in practice. Hosts that resolve to private, loopback or link-local addresses are rejected.
  • Redirects are not followed. Point OnePath at the final URL.
  • Requests are not signed. Put a secret in the path or query string (as in the example) and reject anything that does not carry it.
  • One request is sent per URL per event. If you list two URLs on the same event, each gets its own delivery and its own retries.

Bodies and every field are on Webhook payloads.

Delivery, timeouts, and retries

  • OnePath waits up to 10 seconds for a response (5 seconds to connect). Respond with any 2xx first, then do your work.
  • Any non-2xx response, timeout, or connection error counts as a failure. OnePath retries up to 5 attempts in total, with growing gaps, from a few seconds after the first failure to a few minutes before the last.
  • Retries keep the same notification_id and occurred_at, but data is rebuilt from the current state on each attempt. Because a slow endpoint can be retried after it eventually succeeded, make handling idempotent: skip a notification_id you have already processed.
  • After the last attempt the delivery is marked failed. OnePath emails the addresses on the Service escalation list (subject Webhook Not Receiving Notifications), at most once a week for the same URL and error.

Testing

Send test webhook on the Notifications page posts a sample payload to every URL on that row, once and right away. The body has test: true and notification_id: null. Appointment rows send a sample appointment with id: 0; call rows send a sample conversation with conversation_id: 0 and task: null.

Escalations has no test button. task.handed_to_account has the same body as a call event, so test your parser with a call row, then check the first real hand-off.

Still stuck?

Reach out in your OnePath Slack channel or email your account manager. Include the endpoint URL and the notification_id (or the time of the test send) so we can look up the delivery log fast.

Previous
Switch to Web Widgets