Skip to main content
All webhook payloads share a common envelope:
deliveredAt is regenerated on each retry attempt; eventId is stable across retries — use it for idempotency.

voice_call.completed

Fires after a call ends and has been classified. transcript and recordingUrl are included only when enabled on the webhook configuration.
Key fields:
  • receivingPhoneNumber — Avoca number that directly received the call.
  • originalDialedNumber — inbound destination from linked ServiceTitan records for the original call. Transferred legs use their linked original call regardless of the leg’s own direction. Returns null when the original call is outbound, records are unsupported or missing, or destinations conflict. Earlier forwarding hops may not be preserved. This is a snapshot when the payload is built; a later Calls API read may have data synced afterward. See Report on dialed numbers.
  • bookingOutcome — booked | declined | transferred | unknown
  • agentHandledBy — chloe (AI) | human | unknown
  • isEmergency — emergency classification from the AI or booking-window flag
  • serviceTitanJobId / customerId — CRM linkage when a booking was made

lead.created

Fires when a new lead is recorded. Includes the raw inbound webhook body (when the lead arrived via webhook intake) under rawWebhook.

lead.booking_created

Fires when a booking is created for a lead — once per distinct CRM job. Multiple appointments booked in one conversation emit multiple events. For native-channel bookings (Google LSA, Yelp, web chat), campaign is null.
  • booking.bookedBy — ai | human | self_service | unknown
  • booking.crmJobId can be null when the event fires before the CRM job ID is recorded

lead.completed

Fires once per lead when it reaches the true end of its lifecycle — either its campaign finished, or it terminated at intake without ever entering a campaign.
  • outcome — booked | unbooked | opted_out | failed
  • bookingsCount — currently reports 0 or 1; derive exact counts from lead.booking_created events
  • errorMessage — set only when outcome is failed
  • notEnrolledReason — set only when the lead never entered a campaign

customer.communication_preference_changed

Fires when a customer opts out (STOP) or back in (START) of SMS. Currently SMS-only; email and voice channels are reserved for future use.