DocsAppointmentsAppointments API & Webhooks

Appointments API & Webhooks

Update a lead's appointment status from a buyer's CRM or a calendar tool. Endpoints, fields, and error codes for appointment tracking in Lead Distro AI.

Last updated:

Post an appointment status from a CRM

The buyer outcome webhook accepts an appointment status alongside everything else it already handles. The buyer authenticates with their own secret, so they can only touch their own leads.

curl -X POST https://www.leaddistro.ai/api/webhooks/buyer-outcome \
  -H "X-Buyer-Secret: BUYER_WEBHOOK_SECRET" \
  -H "Content-Type: application/json" \
  -d '{
    "lead_id": "LEAD_UUID",
    "appointment_status": "showed"
  }'
FieldTypeRequiredNotes
lead_idstringYes*The lead to update. Instead of this you may match on phone or email plus campaign_id.
appointment_statusenumYes*One of booked, showed, no_show, canceled. Send this or appointment_qualified.
appointment_atISO 8601NoWhen the appointment is scheduled. Usually sent with booked. Must include a timezone offset.
appointment_qualifiedenumNoOne of qualified, unqualified. The review call on an appointment that showed up. Only accepted when the campaign tracks qualification, otherwise the call returns 403.

Send appointment_at with the booking. Without it you know an appointment exists but not when, which makes time-to-appointment and upcoming-appointment views impossible to build later.

Booking and attendance in one flow

A typical integration sends two calls. The first when the appointment is created, the second when the buyer knows whether it happened.

// 1. When the appointment is booked
{
  "lead_id": "LEAD_UUID",
  "appointment_status": "booked",
  "appointment_at": "2026-09-11T15:00:00-07:00"
}

// 2. After the appointment time passes
{
  "lead_id": "LEAD_UUID",
  "appointment_status": "showed"
}

Sending the same status twice is safe. A repeat of a status the lead already has is recognized and does not bill twice.

Reporting the review

If the buyer pays for appointments that showed up and qualified, a third call reports the review. It is a separate field, not another appointment status, so posting "appointment_status": "qualified" returns 400.

// 3. After someone reviews the appointment
{
  "lead_id": "LEAD_UUID",
  "appointment_qualified": "qualified"
}

The two marks can arrive in either order. If the review lands before the show is reported, nothing bills until the show arrives, and then it bills once. Send unqualified when the review decides the appointment was not worth paying for. If it had already been billed, the charge is reversed.

Call outcomes

If the booking comes out of a phone call rather than a calendar, post it as a call outcome instead. This needs no appointment feature enabled.

curl -X POST https://www.leaddistro.ai/api/v1/lead-update \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "lead_id": "LEAD_UUID",
    "call_outcome": "appointment_set"
  }'

Outcome stages

Both endpoints also accept a stage field carrying a custom outcome stage key, which is how you record an appointment without the billing add-on.

{
  "lead_id": "LEAD_UUID",
  "stage": "meeting_booked"
}

Error codes

CodeMeaningFix
400The appointment status is not one of the four allowed values.Send exactly booked, showed, no_show, or canceled, lowercase.
400The lead has not been accepted yet.A buyer can only set an appointment on a lead they accepted. Deliver and accept it first.
401The buyer secret is missing or wrong.Send the buyer's secret in the X-Buyer-Secret header.
403Appointment tracking is not enabled for the account.Contact support to have it turned on.
404No matching lead.Check the lead id, or that the matching phone or email belongs to a lead assigned to this buyer.

Frequently Asked Questions

How does a buyer's CRM report that an appointment showed up?
It posts to https://www.leaddistro.ai/api/webhooks/buyer-outcome with the buyer's secret in the X-Buyer-Secret header and a body containing the lead id and appointment_status. The four accepted values are booked, showed, no_show, and canceled. Add appointment_at with an ISO timestamp when reporting a booking.
Where do I find these fields in the app?
Open the destination on your campaign and choose Postback Webhook. The spec there lists the appointment fields, shows the booked then showed example, and has a Copy Share Link button so you can hand the whole page to the buyer's developer. The appointment part only appears when that destination is paid per appointment, since that is the only setup where the status changes what gets billed.
Is it safe to send the same appointment status twice?
Yes. Sending a status the lead already has is recognized as a repeat and does not bill the buyer twice, so a CRM that retries on a timeout cannot double-charge anyone.
Why am I getting a 400 saying the lead has not been accepted?
A buyer can only set an appointment on a lead they have accepted, which prevents a buyer marking appointments on leads that were never theirs. Deliver the lead and have it accepted first. Updates you make yourself from the dashboard are not restricted this way.
Why am I getting a 403 on the appointment endpoints?
Appointment tracking is not enabled for the account. It is a limited-release feature, so contact support to have it turned on. In the meantime, post a stage value instead to record the same thing through outcome stages.
Why am I getting a 403 when I post appointment_qualified?
The lead's campaign does not track qualification. Turn on Track Appointment Qualification on that campaign first. Until it is on, there is no review step for the appointment to be in, so the field is refused rather than quietly ignored.
Why does posting appointment_status of qualified return 400?
Qualification is a separate field, not a fifth appointment status. Send appointment_qualified with a value of qualified or unqualified. Keeping them apart is what lets an appointment be Showed and Unqualified at the same time, which is a real and common state.

If you have any questions, send us an email at support@leaddistro.ai