Scheduling API
Build a booking experience with GoodInbound's scheduling backend. Load an event type, show available slots, create a booking, and manage confirmation or cancellation from your own application.
Availability and booking creation are public visitor endpoints. Organizer operations use a secret project API key. You can also use the booking widget or an OAuth-authorized MCP client.
Event type → Available slots → Visitor selects a time → Create booking
├─ Confirmed
└─ Pending approval
Before you start#
Create and enable an event type, assign its availability schedule, and copy the project and event type slugs. Configure duration, buffers, booking limits, and whether organizer confirmation is required. If using Google Calendar, connect it in the dashboard and select the event type's destination and busy-check calendars.
Examples use project acme and event type consultation. Replace them with your own. A project slug is used in visitor URLs; a project ID is used in management URLs.
1. Load the event type#
GET /api/v1/event-types/:projectSlug/:eventSlug
curl 'https://goodinbound.com/api/v1/event-types/acme/consultation'
Use the returned configuration to render the meeting details and any custom booking questions. Read availability separately before offering a time.
2. Check availability#
GET /api/v1/availability/:projectSlug
| Query parameter | Required | Meaning |
|---|---|---|
date |
Yes | Visitor-local date in YYYY-MM-DD format |
eventTypeSlug |
Yes | Enabled event type's slug |
timezone |
No | Visitor's IANA timezone; defaults to UTC |
curl --get 'https://goodinbound.com/api/v1/availability/acme' \
--data-urlencode 'date=2026-10-20' \
--data-urlencode 'eventTypeSlug=consultation' \
--data-urlencode 'timezone=America/New_York'
Choose a future date within your event type's booking window. Example response:
{
"slots": [
{
"start": "2026-10-20T13:00:00.000Z",
"end": "2026-10-20T13:30:00.000Z"
}
],
"date": "2026-10-20",
"timezone": "America/New_York",
"projectSlug": "acme",
"eventTypeSlug": "consultation"
}
Slots are ISO timestamps representing absolute instants. Display them in the visitor's timezone and submit the selected start value unchanged. Do not rebuild the timestamp from a formatted clock label.
Availability accounts for schedule rules, date overrides, event duration, buffers, booking limits, notice requirements, and configured calendar busy times. An empty slots array means no times were returned; it is not an error. Check the slugs and event configuration if the result is unexpected.
3. Create the booking#
POST /api/v1/bookings
No API key is needed. Replace startTime with a slot from your latest availability response:
curl --request POST 'https://goodinbound.com/api/v1/bookings' \
--header 'Content-Type: application/json' \
--data '{
"projectSlug": "acme",
"eventTypeSlug": "consultation",
"startTime": "2026-10-20T13:00:00.000Z",
"timezone": "America/New_York",
"name": "Alex Morgan",
"email": "alex@example.com",
"notes": "We would like to discuss the team plan."
}'
| Body field | Required | Meaning |
|---|---|---|
projectSlug |
Yes | Project slug |
eventTypeSlug |
Yes | Event type slug |
startTime |
Yes | Selected slot's ISO datetime |
timezone |
Yes | Visitor's IANA timezone |
name |
Yes | Guest name, up to 200 characters |
email |
Yes | Guest email address |
notes |
No | Guest notes, up to 2,000 characters |
formFields |
No | Custom booking-form answers keyed by field ID, with string values |
metadata |
No | Additional application data |
Success returns HTTP 201 with a booking object. Example, showing selected fields:
{
"booking": {
"id": "701a159a-fbdd-4368-af52-9a320d53b64f",
"name": "Alex Morgan",
"email": "alex@example.com",
"startTime": "2026-10-20T13:00:00.000Z",
"endTime": "2026-10-20T13:30:00.000Z",
"timezone": "America/New_York",
"status": "pending"
}
}
Always read booking.status. An event type requiring approval creates a pending booking and sends a request-received email. An instantly confirmed booking follows the confirmation flow. Confirmation sends the relevant notification and creates the calendar event when a destination is configured; a pending request does not immediately create that event.
The server checks availability again when booking. If another visitor takes the time, expect 409 and refresh the available slots. Disable repeat submission while a request is in flight. There is no documented idempotency-key contract on this endpoint; after an uncertain timeout, check the booking from your backend before creating another.
Manage bookings from your server#
Create a secret key under MCP & APIs. Set GOODINBOUND_API_KEY, PROJECT_ID, and BOOKING_ID for these requests. Never expose this key in the visitor interface.
| Operation | Method and route |
|---|---|
| List bookings | GET /api/projects/:projectId/bookings |
| Read a booking | GET /api/projects/:projectId/bookings/:bookingId |
| Confirm a pending request | PATCH /api/projects/:projectId/bookings/:bookingId/confirm |
| Decline a pending request | PATCH /api/projects/:projectId/bookings/:bookingId/decline |
| Cancel a booking | PATCH /api/projects/:projectId/bookings/:bookingId/cancel |
curl --request PATCH \
"https://goodinbound.com/api/projects/$PROJECT_ID/bookings/$BOOKING_ID/cancel" \
--header "Authorization: Bearer $GOODINBOUND_API_KEY" \
--header 'Content-Type: application/json' \
--data '{"reason":"Guest requested cancellation"}'
Cancellation updates the booking and attempts removal of its linked calendar event. Confirming, declining, and cancelling must match the current booking state; read the latest booking if a transition is rejected.
For event types, schedules, date overrides, and calendar selection, see Event Types and Availability Rules. Calendar OAuth connection is completed in the dashboard. Use booking_created, booking_pending, booking_confirmed, and booking_cancelled workflow triggers for downstream automation.
MCP access#
Connect to https://goodinbound.com/api/mcp and authorize the intended project. Tools include get_available_slots, create_booking, get_booking, list_bookings, confirm_booking, decline_booking, and cancel_booking. Use the input schema advertised by your MCP client; the project boundary comes from the OAuth grant.
Limits and errors#
Bookings have no monthly quota on Free or Pro. Free includes one calendar connection; Pro includes unlimited calendar connections. Public booking creation is limited to 10 requests/minute per IP and 5 bookings per project per IP in 10 minutes. Availability checks allow 60 requests/minute per IP. Authenticated management API requests allow 120/minute per key.
| Status | Meaning and next step |
|---|---|
| 400 | Invalid request or event-type restriction. Check fields and the returned message. |
| 401 / 403 | Management credentials or project access problem. |
| 404 | Project, event type, or booking was not found. |
| 409 | The slot or requested state transition is no longer available. Refresh before asking the visitor to try again. |
| 429 | Rate limited. Public booking limits include booking_rate_limited, retryAfterSeconds, and a Retry-After header. |
| 500 or network failure | Preserve the visitor's selection and check for an existing booking before retrying an uncertain creation. |
Related: Authentication, Limits, and Errors · Booking Management · Embeddable Widgets.