What Apptoto sends to a webhook URL, and how deliveries are retried.
Each time a webhook's event happens, Apptoto sends an HTTP POST to the webhook's URL with a Content-Type: application/json body. Webhooks can be created with /v1/webhooks or in Settings > Integrations > Webhooks.
Delivery
- Respond with any
2xxstatus to acknowledge the delivery. The response body is ignored. - Respond within 10 seconds. Slower responses are treated as failures.
- A
5xxresponse is retried with growing delays (about 5 seconds, 25 seconds, 2 minutes, then 10 minutes), up to 5 attempts in total. - A
4xxresponse is not retried. - Deliveries are not signed. To make sure a request came from your webhook, put a long random token in the URL (for example
https://example.com/apptoto?token=...) and check it on every request. - Each delivery attempt carries a new
apptoto_id, so it cannot be used to spot a retried delivery. Use the id of the object in the payload instead.
The delivery log for each webhook, including the payload and the response your server sent back, is in Settings > Integrations > Webhooks. A failed delivery can be retried from there.
Payload by event type
Every payload is a JSON object with one top-level key for the object the event is about, plus apptoto_id.
| event_type | Top-level key |
|---|---|
event_created, event_updated, event_deleted | event |
participant_* | participant (with its event), plus message when the event came from a message |
booking_request_made, booking_request_rescheduled | booking_request |
booking_page_viewed | booking_page |
message_sent, message_received, message_failed | message |
phone_added_to_stoplist | phone |
email_added_to_stoplist | email |
payment_processed, payment_refunded | payment |
Events
event has the same fields as an event returned by /v1/events.
{
event: {
id: 123,
calendar_id: 45,
calendar_name: "Dr. Smith",
external_id: "[email protected]",
start_time: "2026-10-14T09:00:00-07:00",
end_time: "2026-10-14T09:30:00-07:00",
created_on_calendar: "2026-10-12T15:04:11-07:00",
updated_on_calendar: "2026-10-12T15:04:11-07:00",
all_day: false,
title: "Cleaning - Fred Smith",
tags: null,
location: "Main office",
content: null,
participants: null,
custom_data: null,
is_deleted: false
},
apptoto_id: "3_k2j4h5g6f7d8"
}Participants
participant has the same fields as a participant returned by /v1/participants, with the participant's event nested inside. For participant_replied_to_message, the reply is included as message.
{
participant: {
id: 789,
event_id: 123,
display_name: "Fred Smith",
name: "Fred Smith",
phone: "650-555-1212",
normalized_phone: "+16505551212",
email: "[email protected]",
state: "confirmed",
check_in_state: "",
link: "https://www.apptoto.com/p/abc123",
reschedule_link: "https://www.apptoto.com/r/abc123",
direct_reschedule_link: "https://www.apptoto.com/r/abc123?direct=1",
cancel_link: "https://www.apptoto.com/c/abc123",
contact_id: 456,
contact_external_id: "EXT-456",
tags: "#vip",
event: {
id: 123,
calendar_id: 45,
title: "Cleaning - Fred Smith",
start_time: "2026-10-14T09:00:00-07:00",
end_time: "2026-10-14T09:30:00-07:00"
}
},
apptoto_id: "3_k2j4h5g6f7d8"
}Booking requests
booking_request describes the completed (or rescheduled) booking, including what the person entered, the booking_page it came through, and the participant it created.
{
booking_request: {
token: "Xy7Qp2",
state: "complete",
start_time: "2026-10-14T09:00:00-07:00",
end_time: "2026-10-14T09:30:00-07:00",
timezone: "Pacific Time (US & Canada)",
appointment_type_token: "new_patient",
selected_calendar_id: 45,
contact_info: {
name: "Fred Smith",
phone: "+16505551212",
email: "[email protected]",
zip: "94025",
notes: null
},
field_data: {},
paid: false,
reschedule_count: 0,
booking_page: {
id: 12,
name: "Book with Dr. Smith",
url: "https://www.apptoto.com/book/drsmith"
},
participant: {
id: 789,
event_id: 123,
name: "Fred Smith"
}
},
apptoto_id: "3_k2j4h5g6f7d8"
}Booking page views
{
booking_page: {
id: 12,
name: "Book with Dr. Smith",
url: "https://www.apptoto.com/book/drsmith"
},
apptoto_id: "3_k2j4h5g6f7d8"
}Messages
message has the same fields as a message returned by /v1/conversation_messages, with the conversation and its participant nested inside.
{
message: {
id: 9911,
at: "2026-10-12T15:20:03-07:00",
event_type: "replied",
content: "Yes, see you then!",
subject: null,
from: "+16505551212",
to: "+14155550100",
delivery_state: null,
delivery_error: null,
delivery_failed: false,
send_failed: false,
conversation: {
id: 5521,
comm_type: "sms",
participant: {
id: 789,
event_id: 123,
name: "Fred Smith"
}
}
},
apptoto_id: "3_k2j4h5g6f7d8"
}Stoplist
{
phone: "+16505551212",
apptoto_id: "3_k2j4h5g6f7d8"
}{
email: "[email protected]",
apptoto_id: "3_k2j4h5g6f7d8"
}Payments
payment_data is the payment processor's record of the charge or refund, with card details removed.
{
payment: {
id: 3381,
at: "2026-10-12T15:30:00-07:00",
event_type: "payment_processed",
amount: 5000,
payment_data: {}
},
apptoto_id: "3_k2j4h5g6f7d8"
}