Use this endpoint to book an appointment using one of your Apptoto Booking Pages.
| Time | Status | User Agent | |
|---|---|---|---|
Retrieving recent requests… | |||
Here is an example request body.
{
booking_page: "bookwithfred",
time: "2025-06-21T08:00:00",
appointment_type_token: "default",
name: "George Smith",
phone_number: "650-898-1212",
email_address: "[email protected]",
field_data: {
zip: 97701
}
}The fields are defined as:
| Field | Type | Required | Description |
|---|---|---|---|
| booking_page | string or number | Yes | Pass the id of the booking page or the "token". The token is the url prefix. E.g. if your booking page is https://bookwithfred.apptoto.com/, then the "token" is "bookwithfred" |
| time | string | Yes | The time to book the appointment |
| appointment_type_token | string | No | Only needed for multi appointment type booking pages. Will default to the first appointment type if nothing provided. |
| name | string | Maybe | The name of the person booking. Required if the booking page requires it. |
| phone_number | string | Maybe | The phone number of the person booking. Required if the booking page requires it. |
| email_address | String | Maybe | The email_address of the person booking. Required if the booking page requires it. |
| field_data | Object | Maybe | Should be an object with key/value pairs for the fields that the Booking Page accepts. Note that if any of the fields are marked as required, then field_data is required. |
| opted_into_text_messaging | boolean | Maybe | If the Booking Page has the 'Obtain consent to send text messages about appointments' option turned on, then this field is required. |
| opted_into_text_messaging_for_marketing | boolean | Maybe | If the Booking Page has the 'Obtain consent to send marketing text messages' option turned on, then this field is required. |
If the booking succeeds, you will get back a response that resembles:
{
"success": true,
"booking": {
"id": 12345678,
"state": "complete",
"booking_page": "abc123def456",
"appointment_type_token": "consultation",
"username": "[email protected]",
"created_at": "2025-08-21T14:30:00Z",
"start_time": "2025-08-22T10:00:00Z",
"end_time": "2025-08-22T11:00:00Z",
"name": "John Doe",
"phone": "+15551234567",
"email": "[email protected]",
"authenticated_phone": false,
"authenticated_email": false,
"rescheduled_at": null,
"previous_time": null,
"client_ip_address": "192.168.1.100",
"field_data": {
"notes": "First time visitor",
"zip": "90210",
"custom_field_1": "Some value"
},
"participant": {
"id": 987654321,
"name": "John Doe",
"phone": "+15551234567",
"email": "[email protected]",
"event": {
"id": 555666777,
"calendar_id": 1111,
"calendar_name": "Sales Appointments",
"title": "Consultation - John Doe",
"start_time": "2025-08-22T10:00:00Z",
"end_time": "2025-08-22T11:00:00Z"
}
}
}
}If the Booking Page is backed by a remote "device" (e.g. a SQL calendar, or Exchange Connector), then it's possible that the "state" of the booking_request will be "pending_device_update" or "pending_device_update_for_contact". If that is the case then you will need to fetch the "booking" using the /v1/bookings API to get the final result.
If the booking fails, the endpoint will respond with a 400 HTTP error code and provide more details in the body. E.g.
{
"success": false,
"error": "Time not available",
"booking": { ... }
}
The attempted "booking" may or may not be included depending on the error, but the state of the booking will be "failed".
OAuth scope
Calls authenticated with an OAuth 2.0 bearer token must include the bookings:write scope. A token without it receives a 403 insufficient_scope response. HTTP Basic auth is not scope-gated.
