API reference

The REST API lives at https://daybag.io/api/v1: send Authorization: Bearer daybag_live_… and JSON. Lists come back as { data } and errors as { "error": { "code", "message" } } with an HTTP status. Every operation is also an MCP tool of the same name, and this page is generated from the schemas behind the OpenAPI document.

Plain text

Offerings

GET/offeringsofferings_list

List offerings (classes, appointments and rentals), paused ones included

Request

kindquery
class | appointment | rental · class: scheduled sessions with seats · appointment: slots from weekly hours · rental: inventory over periods

Response 200

datarequired
object[]
data[].idrequired
string
data[].org_idrequired
string
data[].kindrequired
class | appointment | rental · class: scheduled sessions with seats · appointment: slots from weekly hours · rental: inventory over periods
data[].namerequired
string
data[].descriptionrequired
string
data[].locationrequired
string
data[].duration_minutesrequired
integer · Length of a class session or appointment, or of one rental period (1440 = a day)
data[].capacityrequired
integer · class: seats per session · appointment: parallel bookings per slot · rental: items in stock
data[].max_per_bookingrequired
integer · Most seats, party size or items in one booking
data[].price_centsrequired
integer · class: per seat · appointment: per booking · rental: per item per period
data[].slot_interval_minutesrequired
integer | null · Minutes between start times; null means back to back
data[].buffer_minutesrequired
integer
data[].min_notice_minutesrequired
integer
data[].max_advance_daysrequired
integer
data[].max_periodsrequired
integer · Rentals: the most periods one booking can span
data[].activerequired
boolean · false pauses booking: guests and agents can't book it, and it stays in your dashboard
data[].metadatarequired
any · Free-form JSON object for your own integrations
data[].created_atrequired
string · ISO 8601 timestamp (UTC)

POST/offeringsofferings_create

Create an offering. Only kind and name are required; everything else has defaults per kind. Appointments and rentals open daily 9:00–17:00 (org time) until you set hours; classes need sessions.

Request

namerequired
string · ≤ 120 chars
description
string · ≤ 2000 chars
location
string · ≤ 200 chars
duration_minutes
integer · 5–43200 · Length of a class session or appointment, or of one rental period (1440 = a day)
capacity
integer · 1–10000 · class: seats per session · appointment: parallel bookings per slot · rental: items in stock
max_per_booking
integer · 1–10000 · Most seats, party size or items in one booking
price_cents
integer · ≥ 0 · class: per seat · appointment: per booking · rental: per item per period
slot_interval_minutes
integer | null · Minutes between start times; null means back to back
buffer_minutes
integer · 0–1440 · Gap kept free around appointments and rentals
min_notice_minutes
integer · 0–43200
max_advance_days
integer · 1–730
max_periods
integer · 1–60 · Rentals: the most periods one booking can span
active
boolean · false pauses booking: guests and agents can't book it, and it stays in your dashboard
metadata
object · Free-form JSON for your own integrations
kindrequired
class | appointment | rental · class: scheduled sessions with seats · appointment: slots from weekly hours · rental: inventory over periods

Response 201

idrequired
string
org_idrequired
string
kindrequired
class | appointment | rental · class: scheduled sessions with seats · appointment: slots from weekly hours · rental: inventory over periods
namerequired
string
descriptionrequired
string
locationrequired
string
duration_minutesrequired
integer · Length of a class session or appointment, or of one rental period (1440 = a day)
capacityrequired
integer · class: seats per session · appointment: parallel bookings per slot · rental: items in stock
max_per_bookingrequired
integer · Most seats, party size or items in one booking
price_centsrequired
integer · class: per seat · appointment: per booking · rental: per item per period
slot_interval_minutesrequired
integer | null · Minutes between start times; null means back to back
buffer_minutesrequired
integer
min_notice_minutesrequired
integer
max_advance_daysrequired
integer
max_periodsrequired
integer · Rentals: the most periods one booking can span
activerequired
boolean · false pauses booking: guests and agents can't book it, and it stays in your dashboard
metadatarequired
any · Free-form JSON object for your own integrations
created_atrequired
string · ISO 8601 timestamp (UTC)

GET/offerings/{id}offerings_get

Get one offering

Request

idpathrequired
string · uuid

Response 200

idrequired
string
org_idrequired
string
kindrequired
class | appointment | rental · class: scheduled sessions with seats · appointment: slots from weekly hours · rental: inventory over periods
namerequired
string
descriptionrequired
string
locationrequired
string
duration_minutesrequired
integer · Length of a class session or appointment, or of one rental period (1440 = a day)
capacityrequired
integer · class: seats per session · appointment: parallel bookings per slot · rental: items in stock
max_per_bookingrequired
integer · Most seats, party size or items in one booking
price_centsrequired
integer · class: per seat · appointment: per booking · rental: per item per period
slot_interval_minutesrequired
integer | null · Minutes between start times; null means back to back
buffer_minutesrequired
integer
min_notice_minutesrequired
integer
max_advance_daysrequired
integer
max_periodsrequired
integer · Rentals: the most periods one booking can span
activerequired
boolean · false pauses booking: guests and agents can't book it, and it stays in your dashboard
metadatarequired
any · Free-form JSON object for your own integrations
created_atrequired
string · ISO 8601 timestamp (UTC)

PATCH/offerings/{id}offerings_update

Update an offering. Set active: false to pause booking; it stays in your dashboard.

Request

idpathrequired
string · uuid
name
string · ≤ 120 chars
description
string · ≤ 2000 chars
location
string · ≤ 200 chars
duration_minutes
integer · 5–43200 · Length of a class session or appointment, or of one rental period (1440 = a day)
capacity
integer · 1–10000 · class: seats per session · appointment: parallel bookings per slot · rental: items in stock
max_per_booking
integer · 1–10000 · Most seats, party size or items in one booking
price_cents
integer · ≥ 0 · class: per seat · appointment: per booking · rental: per item per period
slot_interval_minutes
integer | null · Minutes between start times; null means back to back
buffer_minutes
integer · 0–1440 · Gap kept free around appointments and rentals
min_notice_minutes
integer · 0–43200
max_advance_days
integer · 1–730
max_periods
integer · 1–60 · Rentals: the most periods one booking can span
active
boolean · false pauses booking: guests and agents can't book it, and it stays in your dashboard
metadata
object · Free-form JSON for your own integrations

Response 200

idrequired
string
org_idrequired
string
kindrequired
class | appointment | rental · class: scheduled sessions with seats · appointment: slots from weekly hours · rental: inventory over periods
namerequired
string
descriptionrequired
string
locationrequired
string
duration_minutesrequired
integer · Length of a class session or appointment, or of one rental period (1440 = a day)
capacityrequired
integer · class: seats per session · appointment: parallel bookings per slot · rental: items in stock
max_per_bookingrequired
integer · Most seats, party size or items in one booking
price_centsrequired
integer · class: per seat · appointment: per booking · rental: per item per period
slot_interval_minutesrequired
integer | null · Minutes between start times; null means back to back
buffer_minutesrequired
integer
min_notice_minutesrequired
integer
max_advance_daysrequired
integer
max_periodsrequired
integer · Rentals: the most periods one booking can span
activerequired
boolean · false pauses booking: guests and agents can't book it, and it stays in your dashboard
metadatarequired
any · Free-form JSON object for your own integrations
created_atrequired
string · ISO 8601 timestamp (UTC)

DELETE/offerings/{id}offerings_delete

Delete an offering. With upcoming bookings, pass cancel_bookings: true: they're cancelled (guests emailed, online payments refunded in full) and past bookings stay on record. Returns { cancelled, refunded }.

Request

idpathrequired
string · uuid
cancel_bookingsquery
boolean · Required when the offering has upcoming bookings or live holds; otherwise the delete answers 409 with what it would cancel

Response 200

cancelledrequired
integer · Upcoming bookings and holds cancelled
refundedrequired
integer · Of those, paid online and refunded in full

GET/offerings/{id}/hoursofferings_get_hours

Weekly opening hours of an appointment or rental, in the org's local time

Request

idpathrequired
string · uuid

Response 200

datarequired
object[]
data[].weekdayrequired
integer · 0 = Sunday … 6 = Saturday
data[].start_timerequired
string · Local wall-clock time, HH:MM:SS
data[].end_timerequired
string · Local wall-clock time, HH:MM:SS

PUT/offerings/{id}/hoursofferings_set_hours

Replace weekly opening hours, e.g. [{ weekday: 6, start_time: '08:00', end_time: '16:00' }]

Request

idpathrequired
string · uuid
hoursrequired
object[] · ≤ 50 items
hours[].weekdayrequired
integer · 0–6 · 0 = Sunday … 6 = Saturday
hours[].start_timerequired
string
hours[].end_timerequired
string

Response 200

datarequired
object[]
data[].weekdayrequired
integer · 0 = Sunday … 6 = Saturday
data[].start_timerequired
string · Local wall-clock time, HH:MM:SS
data[].end_timerequired
string · Local wall-clock time, HH:MM:SS

Availability

GET/offerings/{id}/availabilityavailability_get

Bookable slots with remaining capacity between two local dates (default: the next 14 days)

Request

idpathrequired
string · uuid
fromquery
string · date · Local calendar date (YYYY-MM-DD) in the org's time zone
toquery
string · date · Local calendar date (YYYY-MM-DD) in the org's time zone

Response 200

timezonerequired
string · The org's time zone; from and to are local dates in it
datarequired
object[]
data[].starts_atrequired
string · ISO 8601 timestamp (UTC)
data[].ends_atrequired
string · ISO 8601 timestamp (UTC)
data[].capacityrequired
integer
data[].remainingrequired
integer · What's left to book: seats, parallel slots or items
data[].session_id
string · Classes only: pass it to bookings_create

Sessions

GET/sessionssessions_list

List class sessions with the number of seats booked

Request

offering_idquery
string · uuid
fromquery
string · ISO 8601 instant, e.g. 2026-10-03T15:00:00Z
toquery
string · ISO 8601 instant, e.g. 2026-10-03T15:00:00Z
statusquery
scheduled | cancelled

Response 200

datarequired
object[]
data[].idrequired
string
data[].org_idrequired
string
data[].offering_idrequired
string
data[].starts_atrequired
string · ISO 8601 timestamp (UTC)
data[].ends_atrequired
string · ISO 8601 timestamp (UTC)
data[].capacityrequired
integer | null · Seats for this session; null means the class's capacity
data[].statusrequired
scheduled | cancelled
data[].created_atrequired
string · ISO 8601 timestamp (UTC)
data[].bookedrequired
integer · Seats booked

POST/sessionssessions_create

Schedule a class session; repeat_weeks repeats it weekly at the same local time

Request

offering_idrequired
string · uuid
starts_atrequired
string · ISO 8601 instant, e.g. 2026-10-03T15:00:00Z
repeat_weeks
integer · 1–52
capacity
integer | null · Override the class's seats

Response 201

datarequired
object[]
data[].idrequired
string
data[].org_idrequired
string
data[].offering_idrequired
string
data[].starts_atrequired
string · ISO 8601 timestamp (UTC)
data[].ends_atrequired
string · ISO 8601 timestamp (UTC)
data[].capacityrequired
integer | null · Seats for this session; null means the class's capacity
data[].statusrequired
scheduled | cancelled
data[].created_atrequired
string · ISO 8601 timestamp (UTC)

POST/sessions/{id}/cancelsessions_cancel

Cancel a class session and every booking in it

Request

idpathrequired
string · uuid

Response 200

idrequired
string
org_idrequired
string
offering_idrequired
string
starts_atrequired
string · ISO 8601 timestamp (UTC)
ends_atrequired
string · ISO 8601 timestamp (UTC)
capacityrequired
integer | null · Seats for this session; null means the class's capacity
statusrequired
scheduled | cancelled
created_atrequired
string · ISO 8601 timestamp (UTC)

Bookings

GET/bookingsbookings_list

List bookings filtered by time range, status, offering, customer or session (order=desc for newest first)

Request

fromquery
string · ISO 8601 instant, e.g. 2026-10-03T15:00:00Z
toquery
string · ISO 8601 instant, e.g. 2026-10-03T15:00:00Z
statusquery
held | confirmed | cancelled
offering_idquery
string · uuid
customer_idquery
string · uuid
session_idquery
string · uuid
orderquery
asc | desc
limitquery
integer · 1–500

Response 200

datarequired
object[]
data[].idrequired
string
data[].org_idrequired
string
data[].offering_idrequired
string
data[].session_idrequired
string | null · Classes only
data[].customer_idrequired
string
data[].starts_atrequired
string · ISO 8601 timestamp (UTC)
data[].ends_atrequired
string · ISO 8601 timestamp (UTC)
data[].quantityrequired
integer · class: seats · appointment: party size · rental: items
data[].total_centsrequired
integer · In the org's currency
data[].referencerequired
string · Short code the guest sees, e.g. 0GWYRZ2V
data[].statusrequired
held | confirmed | cancelled · held, confirmed or cancelled; a hold keeps its place until expires_at
data[].sourcerequired
string · Where it was made: dashboard, api, mcp or widget
data[].notesrequired
string
data[].metadatarequired
any · Free-form JSON object for your own integrations
data[].cancelled_atrequired
string | null · ISO 8601 timestamp (UTC)
data[].created_atrequired
string · ISO 8601 timestamp (UTC)
data[].expires_atrequired
string | null · Held bookings: when the hold stops keeping its place
data[].handlerequired
string · The guest's own page for the booking: /b/{handle}
data[].checkout_urlrequired
string | null · Stripe Checkout for a hold being paid online
data[].paid_atrequired
string | null · When it was paid online
data[].payment_intent_idrequired
string | null · The Stripe payment, when paid online
data[].previous
object · bookings.move: where the booking was
data[].previous.starts_atrequired
string · ISO 8601 timestamp (UTC)
data[].previous.ends_atrequired
string · ISO 8601 timestamp (UTC)
data[].previous.session_idrequired
string | null
data[].offeringrequired
object
data[].offering.idrequired
string
data[].offering.namerequired
string
data[].offering.kindrequired
class | appointment | rental · class: scheduled sessions with seats · appointment: slots from weekly hours · rental: inventory over periods
data[].customerrequired
object
data[].customer.idrequired
string
data[].customer.namerequired
string
data[].customer.emailrequired
string
data[].customer.phonerequired
string

GET/bookings/{id}bookings_get

Get one booking with its offering and customer

Request

idpathrequired
string · uuid

Response 200

idrequired
string
org_idrequired
string
offering_idrequired
string
session_idrequired
string | null · Classes only
customer_idrequired
string
starts_atrequired
string · ISO 8601 timestamp (UTC)
ends_atrequired
string · ISO 8601 timestamp (UTC)
quantityrequired
integer · class: seats · appointment: party size · rental: items
total_centsrequired
integer · In the org's currency
referencerequired
string · Short code the guest sees, e.g. 0GWYRZ2V
statusrequired
held | confirmed | cancelled · held, confirmed or cancelled; a hold keeps its place until expires_at
sourcerequired
string · Where it was made: dashboard, api, mcp or widget
notesrequired
string
metadatarequired
any · Free-form JSON object for your own integrations
cancelled_atrequired
string | null · ISO 8601 timestamp (UTC)
created_atrequired
string · ISO 8601 timestamp (UTC)
expires_atrequired
string | null · Held bookings: when the hold stops keeping its place
handlerequired
string · The guest's own page for the booking: /b/{handle}
checkout_urlrequired
string | null · Stripe Checkout for a hold being paid online
paid_atrequired
string | null · When it was paid online
payment_intent_idrequired
string | null · The Stripe payment, when paid online
previous
object · bookings.move: where the booking was
previous.starts_atrequired
string · ISO 8601 timestamp (UTC)
previous.ends_atrequired
string · ISO 8601 timestamp (UTC)
previous.session_idrequired
string | null
offeringrequired
object
offering.idrequired
string
offering.namerequired
string
offering.kindrequired
class | appointment | rental · class: scheduled sessions with seats · appointment: slots from weekly hours · rental: inventory over periods
customerrequired
object
customer.idrequired
string
customer.namerequired
string
customer.emailrequired
string
customer.phonerequired
string

POST/bookingsbookings_create

Book a slot from availability.get (classes need session_id; appointments and rentals need starts_at). Pass hold_minutes to hold it instead, and idempotency_key so retries never book twice.

Request

offering_idrequired
string · uuid
session_id
string · uuid
starts_at
string · ISO 8601 instant, e.g. 2026-10-03T15:00:00Z
quantity
integer · 1–10000 · class: seats · appointment: party size · rental: items
periods
integer · 1–60 · Rentals: how many periods (e.g. days)
customer_id
string · uuid
customer
object · Matched by email; created if new
customer.emailrequired
string · email
customer.name
string · ≤ 120 chars
customer.phone
string · ≤ 40 chars
notes
string · ≤ 2000 chars
hold_minutes
integer · 5–1440 · Hold the place this many minutes (status held) instead of confirming; then call bookings.confirm
idempotency_key
string · uuid · A UUID you generate per booking: retrying with it returns the same booking instead of booking twice

Response 201

idrequired
string
org_idrequired
string
offering_idrequired
string
session_idrequired
string | null · Classes only
customer_idrequired
string
starts_atrequired
string · ISO 8601 timestamp (UTC)
ends_atrequired
string · ISO 8601 timestamp (UTC)
quantityrequired
integer · class: seats · appointment: party size · rental: items
total_centsrequired
integer · In the org's currency
referencerequired
string · Short code the guest sees, e.g. 0GWYRZ2V
statusrequired
held | confirmed | cancelled · held, confirmed or cancelled; a hold keeps its place until expires_at
sourcerequired
string · Where it was made: dashboard, api, mcp or widget
notesrequired
string
metadatarequired
any · Free-form JSON object for your own integrations
cancelled_atrequired
string | null · ISO 8601 timestamp (UTC)
created_atrequired
string · ISO 8601 timestamp (UTC)
expires_atrequired
string | null · Held bookings: when the hold stops keeping its place
handlerequired
string · The guest's own page for the booking: /b/{handle}
checkout_urlrequired
string | null · Stripe Checkout for a hold being paid online
paid_atrequired
string | null · When it was paid online
payment_intent_idrequired
string | null · The Stripe payment, when paid online
previous
object · bookings.move: where the booking was
previous.starts_atrequired
string · ISO 8601 timestamp (UTC)
previous.ends_atrequired
string · ISO 8601 timestamp (UTC)
previous.session_idrequired
string | null
offeringrequired
object
offering.idrequired
string
offering.namerequired
string
offering.kindrequired
class | appointment | rental · class: scheduled sessions with seats · appointment: slots from weekly hours · rental: inventory over periods
customerrequired
object
customer.idrequired
string
customer.namerequired
string
customer.emailrequired
string
customer.phonerequired
string

POST/bookings/{id}/cancelbookings_cancel

Cancel a booking or a hold and free its capacity (safe to repeat)

Request

idpathrequired
string · uuid

Response 200

idrequired
string
org_idrequired
string
offering_idrequired
string
session_idrequired
string | null · Classes only
customer_idrequired
string
starts_atrequired
string · ISO 8601 timestamp (UTC)
ends_atrequired
string · ISO 8601 timestamp (UTC)
quantityrequired
integer · class: seats · appointment: party size · rental: items
total_centsrequired
integer · In the org's currency
referencerequired
string · Short code the guest sees, e.g. 0GWYRZ2V
statusrequired
held | confirmed | cancelled · held, confirmed or cancelled; a hold keeps its place until expires_at
sourcerequired
string · Where it was made: dashboard, api, mcp or widget
notesrequired
string
metadatarequired
any · Free-form JSON object for your own integrations
cancelled_atrequired
string | null · ISO 8601 timestamp (UTC)
created_atrequired
string · ISO 8601 timestamp (UTC)
expires_atrequired
string | null · Held bookings: when the hold stops keeping its place
handlerequired
string · The guest's own page for the booking: /b/{handle}
checkout_urlrequired
string | null · Stripe Checkout for a hold being paid online
paid_atrequired
string | null · When it was paid online
payment_intent_idrequired
string | null · The Stripe payment, when paid online
previous
object · bookings.move: where the booking was
previous.starts_atrequired
string · ISO 8601 timestamp (UTC)
previous.ends_atrequired
string · ISO 8601 timestamp (UTC)
previous.session_idrequired
string | null
offeringrequired
object
offering.idrequired
string
offering.namerequired
string
offering.kindrequired
class | appointment | rental · class: scheduled sessions with seats · appointment: slots from weekly hours · rental: inventory over periods
customerrequired
object
customer.idrequired
string
customer.namerequired
string
customer.emailrequired
string
customer.phonerequired
string

POST/bookings/{id}/confirmbookings_confirm

Confirm a held booking (safe to repeat). A hold past its expires_at confirms only if its place is still free.

Request

idpathrequired
string · uuid

Response 200

idrequired
string
org_idrequired
string
offering_idrequired
string
session_idrequired
string | null · Classes only
customer_idrequired
string
starts_atrequired
string · ISO 8601 timestamp (UTC)
ends_atrequired
string · ISO 8601 timestamp (UTC)
quantityrequired
integer · class: seats · appointment: party size · rental: items
total_centsrequired
integer · In the org's currency
referencerequired
string · Short code the guest sees, e.g. 0GWYRZ2V
statusrequired
held | confirmed | cancelled · held, confirmed or cancelled; a hold keeps its place until expires_at
sourcerequired
string · Where it was made: dashboard, api, mcp or widget
notesrequired
string
metadatarequired
any · Free-form JSON object for your own integrations
cancelled_atrequired
string | null · ISO 8601 timestamp (UTC)
created_atrequired
string · ISO 8601 timestamp (UTC)
expires_atrequired
string | null · Held bookings: when the hold stops keeping its place
handlerequired
string · The guest's own page for the booking: /b/{handle}
checkout_urlrequired
string | null · Stripe Checkout for a hold being paid online
paid_atrequired
string | null · When it was paid online
payment_intent_idrequired
string | null · The Stripe payment, when paid online
previous
object · bookings.move: where the booking was
previous.starts_atrequired
string · ISO 8601 timestamp (UTC)
previous.ends_atrequired
string · ISO 8601 timestamp (UTC)
previous.session_idrequired
string | null
offeringrequired
object
offering.idrequired
string
offering.namerequired
string
offering.kindrequired
class | appointment | rental · class: scheduled sessions with seats · appointment: slots from weekly hours · rental: inventory over periods
customerrequired
object
customer.idrequired
string
customer.namerequired
string
customer.emailrequired
string
customer.phonerequired
string

POST/bookings/{id}/movebookings_move

Move a booking or a hold to another time of the same offering (classes: session_id; appointments and rentals: starts_at from availability.get). It keeps its reference, price and payment, the guest gets one email, and moving it to its current time changes nothing.

Request

idpathrequired
string · uuid
session_id
string · uuid · Classes: the session to move to
starts_at
string · Appointments and rentals: the new start; the booking keeps its length

Response 200

idrequired
string
org_idrequired
string
offering_idrequired
string
session_idrequired
string | null · Classes only
customer_idrequired
string
starts_atrequired
string · ISO 8601 timestamp (UTC)
ends_atrequired
string · ISO 8601 timestamp (UTC)
quantityrequired
integer · class: seats · appointment: party size · rental: items
total_centsrequired
integer · In the org's currency
referencerequired
string · Short code the guest sees, e.g. 0GWYRZ2V
statusrequired
held | confirmed | cancelled · held, confirmed or cancelled; a hold keeps its place until expires_at
sourcerequired
string · Where it was made: dashboard, api, mcp or widget
notesrequired
string
metadatarequired
any · Free-form JSON object for your own integrations
cancelled_atrequired
string | null · ISO 8601 timestamp (UTC)
created_atrequired
string · ISO 8601 timestamp (UTC)
expires_atrequired
string | null · Held bookings: when the hold stops keeping its place
handlerequired
string · The guest's own page for the booking: /b/{handle}
checkout_urlrequired
string | null · Stripe Checkout for a hold being paid online
paid_atrequired
string | null · When it was paid online
payment_intent_idrequired
string | null · The Stripe payment, when paid online
previous
object · bookings.move: where the booking was
previous.starts_atrequired
string · ISO 8601 timestamp (UTC)
previous.ends_atrequired
string · ISO 8601 timestamp (UTC)
previous.session_idrequired
string | null
offeringrequired
object
offering.idrequired
string
offering.namerequired
string
offering.kindrequired
class | appointment | rental · class: scheduled sessions with seats · appointment: slots from weekly hours · rental: inventory over periods
customerrequired
object
customer.idrequired
string
customer.namerequired
string
customer.emailrequired
string
customer.phonerequired
string

POST/bookings/{id}/resendbookings_resend

Email the guest their booking confirmation again, at most once a day; not for held or cancelled bookings

Request

idpathrequired
string · uuid

Response 200

okrequired
true

Conversations

GET/conversationsconversations_list

List conversations with guests, the ones waiting on a reply first, each with its guest, last message and booking chip (filter by status, unread, a search q, or customer_id for one guest's)

Request

statusquery
open | done
unreadquery
boolean
qquery
string · ≤ 200 chars · Matches the guest's name or email, or words in the messages
customer_idquery
string · uuid
limitquery
integer · 1–500

Response 200

datarequired
object[]
data[].idrequired
string
data[].statusrequired
open | done
data[].last_message_atrequired
string · ISO 8601 timestamp (UTC)
data[].outfitter_read_atrequired
string | null · ISO 8601 timestamp (UTC)
data[].guest_read_atrequired
string | null · ISO 8601 timestamp (UTC)
data[].snoozed_untilrequired
string | null · ISO 8601 timestamp (UTC)
data[].created_atrequired
string · ISO 8601 timestamp (UTC)
data[].unreadrequired
boolean · A guest message is newer than outfitter_read_at
data[].needs_replyrequired
boolean · The guest wrote last
data[].customerrequired
object | null · Null on a pre-sale question
data[].last_messagerequired
object | null
data[].bookingrequired
object | null · The guest's next upcoming booking, else their latest

GET/conversations/{id}conversations_get

Get a conversation with its thread oldest first: messages, notes, and the guest's booking events as system rows

Request

idpathrequired
string · uuid

Response 200

idrequired
string
statusrequired
open | done
last_message_atrequired
string · ISO 8601 timestamp (UTC)
outfitter_read_atrequired
string | null · ISO 8601 timestamp (UTC)
guest_read_atrequired
string | null · ISO 8601 timestamp (UTC)
snoozed_untilrequired
string | null · ISO 8601 timestamp (UTC)
created_atrequired
string · ISO 8601 timestamp (UTC)
unreadrequired
boolean · A guest message is newer than outfitter_read_at
needs_replyrequired
boolean · The guest wrote last
customerrequired
object | null · Null on a pre-sale question
last_messagerequired
object | null
bookingrequired
object | null · The guest's next upcoming booking, else their latest
threadrequired
object | object[]

PATCH/conversations/{id}conversations_update

Mark a conversation done or open again; read: true once the guest's messages have been seen

Request

idpathrequired
string · uuid
status
open | done
read
boolean

Response 200

idrequired
string
statusrequired
open | done
last_message_atrequired
string · ISO 8601 timestamp (UTC)
outfitter_read_atrequired
string | null · ISO 8601 timestamp (UTC)
guest_read_atrequired
string | null · ISO 8601 timestamp (UTC)
snoozed_untilrequired
string | null · ISO 8601 timestamp (UTC)
created_atrequired
string · ISO 8601 timestamp (UTC)
unreadrequired
boolean · A guest message is newer than outfitter_read_at
needs_replyrequired
boolean · The guest wrote last
customerrequired
object | null · Null on a pre-sale question
last_messagerequired
object | null
bookingrequired
object | null · The guest's next upcoming booking, else their latest

Messages

GET/messagesmessages_list

List messages with guests, both ways and oldest first: a conversation's, a booking's (booking_id) or a guest's (customer_id)

Request

conversation_idquery
string · uuid
booking_idquery
string · uuid
customer_idquery
string · uuid
limitquery
integer · 1–500

Response 200

datarequired
object[]
data[].idrequired
string
data[].org_idrequired
string
data[].conversation_idrequired
string | null
data[].booking_idrequired
string | null · The booking it's about, shown as its chip; null when about the guest in general
data[].customer_idrequired
string | null · Null on a pre-sale question
data[].directionrequired
to_guest | to_outfitter · to_guest: the outfitter wrote · to_outfitter: the guest wrote from their booking page or replied by email
data[].subjectrequired
string · Empty on guest messages
data[].bodyrequired
string
data[].sent_byrequired
dashboard | api | mcp | guest
data[].channelrequired
string · How it travelled: page (typed in daybag), email, api or system
data[].kindrequired
message | note · A note is the outfitter's own, never sent to the guest
data[].read_atrequired
string | null · When the other side read it
data[].attachmentsrequired
object[] · Files on it, each opened at /api/attachments/{id}
data[].attachments[].idrequired
string
data[].attachments[].namerequired
string
data[].attachments[].sizerequired
integer
data[].attachments[].typerequired
string
data[].delivered_atrequired
string | null · Messages to guests: when the guest's mail server took the email
data[].failed_atrequired
string | null · Messages to guests: when the email bounced or was marked as spam
data[].from_namerequired
string | null · Guest messages: the name they gave
data[].from_emailrequired
string | null · Guest messages: the email they gave, where replies go
data[].created_atrequired
string · ISO 8601 timestamp (UTC)
data[].bookingrequired
object | null

POST/messagesmessages_send

Write to a guest by conversation_id, booking_id or customer_id (not about a held booking); they get it by email and their reply reaches the outfitter. kind note keeps an internal note instead

Request

conversation_id
string · uuid
booking_id
string · uuid · The booking it's about; it shows as the message's chip
customer_id
string · uuid
subject
string · ≤ 200 chars
bodyrequired
string · ≤ 5000 chars
kind
message | note · note: for the outfitter's team, never sent
attachments
object[] · ≤ 5 items · Files uploaded with the attachment picker ({ id, name }), up to 5: photos (JPEG, PNG, WebP, HEIC) or PDFs, 10 MB each
attachments[].idrequired
string
attachments[].namerequired
string · ≤ 1000 chars

Response 201

idrequired
string
org_idrequired
string
conversation_idrequired
string | null
booking_idrequired
string | null · The booking it's about, shown as its chip; null when about the guest in general
customer_idrequired
string | null · Null on a pre-sale question
directionrequired
to_guest | to_outfitter · to_guest: the outfitter wrote · to_outfitter: the guest wrote from their booking page or replied by email
subjectrequired
string · Empty on guest messages
bodyrequired
string
sent_byrequired
dashboard | api | mcp | guest
channelrequired
string · How it travelled: page (typed in daybag), email, api or system
kindrequired
message | note · A note is the outfitter's own, never sent to the guest
read_atrequired
string | null · When the other side read it
attachmentsrequired
object[] · Files on it, each opened at /api/attachments/{id}
attachments[].idrequired
string
attachments[].namerequired
string
attachments[].sizerequired
integer
attachments[].typerequired
string
delivered_atrequired
string | null · Messages to guests: when the guest's mail server took the email
failed_atrequired
string | null · Messages to guests: when the email bounced or was marked as spam
from_namerequired
string | null · Guest messages: the name they gave
from_emailrequired
string | null · Guest messages: the email they gave, where replies go
created_atrequired
string · ISO 8601 timestamp (UTC)

POST/messages/broadcastmessages_broadcast

Write to many guests, once each: everyone confirmed in a class session (target.session_id), starting on a local date across offerings (target.date), or booked ahead on an offering (target.offering_id). Returns how many were sent, skipped (erased guests) and failed

Request

targetrequired
object | object | object · { session_id }, { date } or { offering_id }
subject
string · ≤ 200 chars
bodyrequired
string · ≤ 5000 chars

Response 200

sentrequired
integer
skippedrequired
integer
failedrequired
integer

POST/messages/draftmessages_draft

Draft a reply in a conversation for the outfitter to edit and send; nothing is sent. Written from the last 10 messages and the guest's latest booking. 409 drafts_unavailable when drafting is off; 60 drafts per org in any 24 hours

Request

conversation_idrequired
string · uuid · The conversation to draft a reply in

Response 200

textrequired
string · The drafted reply, plain text, to review and edit before sending

Saved replies

GET/saved_repliessaved_replies_list

List the outfitter's saved replies by title. With booking_id, or conversation_id (its guest and their booking under way or next), each comes with text: its body filled in, ready to send with messages_send

Request

booking_idquery
string · uuid · Fill the replies in for this booking and its guest
conversation_idquery
string · uuid · Or for this conversation's guest and their booking under way or next

Response 200

datarequired
object[]
data[].idrequired
string
data[].org_idrequired
string
data[].titlerequired
string · What the outfitter picks it by
data[].bodyrequired
string · The message as saved, with its {variables}
data[].created_atrequired
string · ISO 8601 timestamp (UTC)
data[].updated_atrequired
string · ISO 8601 timestamp (UTC)
data[].textrequired
string · The body filled in for booking_id or conversation_id, ready for messages_send; without them only {org} is filled in

POST/saved_repliessaved_replies_create

Save a reply the outfitter can reuse. Its body can use {first_name}, {start_time}, {offering}, {meeting_point}, {org}, {booking_link}, which saved_replies_list fills in for a guest

Request

titlerequired
string · ≤ 80 chars · What it's picked by, such as Directions
bodyrequired
string · ≤ 5000 chars · The message. {first_name}, {start_time}, {offering}, {meeting_point}, {org}, {booking_link} are filled in for a guest when it's used

Response 201

idrequired
string
org_idrequired
string
titlerequired
string · What the outfitter picks it by
bodyrequired
string · The message as saved, with its {variables}
created_atrequired
string · ISO 8601 timestamp (UTC)
updated_atrequired
string · ISO 8601 timestamp (UTC)

PATCH/saved_replies/{id}saved_replies_update

Change a saved reply's title or body

Request

idpathrequired
string · uuid
title
string · ≤ 80 chars · What it's picked by, such as Directions
body
string · ≤ 5000 chars · The message. {first_name}, {start_time}, {offering}, {meeting_point}, {org}, {booking_link} are filled in for a guest when it's used

Response 200

idrequired
string
org_idrequired
string
titlerequired
string · What the outfitter picks it by
bodyrequired
string · The message as saved, with its {variables}
created_atrequired
string · ISO 8601 timestamp (UTC)
updated_atrequired
string · ISO 8601 timestamp (UTC)

DELETE/saved_replies/{id}saved_replies_delete

Delete a saved reply

Request

idpathrequired
string · uuid

Response 200

okrequired
true

Customers

GET/customerscustomers_list

List customers, newest first; q searches name, email and phone

Request

qquery
string · ≤ 100 chars
limitquery
integer · 1–500

Response 200

datarequired
object[]
data[].idrequired
string
data[].org_idrequired
string
data[].emailrequired
string · Lowercase; unique within the org
data[].namerequired
string
data[].phonerequired
string
data[].notesrequired
string
data[].metadatarequired
any · Free-form JSON object for your own integrations
data[].created_atrequired
string · ISO 8601 timestamp (UTC)

GET/customers/{id}customers_get

Get a customer with their bookings

Request

idpathrequired
string · uuid

Response 200

idrequired
string
org_idrequired
string
emailrequired
string · Lowercase; unique within the org
namerequired
string
phonerequired
string
notesrequired
string
metadatarequired
any · Free-form JSON object for your own integrations
created_atrequired
string · ISO 8601 timestamp (UTC)
bookingsrequired
object[]
bookings[].idrequired
string
bookings[].org_idrequired
string
bookings[].offering_idrequired
string
bookings[].session_idrequired
string | null · Classes only
bookings[].customer_idrequired
string
bookings[].starts_atrequired
string · ISO 8601 timestamp (UTC)
bookings[].ends_atrequired
string · ISO 8601 timestamp (UTC)
bookings[].quantityrequired
integer · class: seats · appointment: party size · rental: items
bookings[].total_centsrequired
integer · In the org's currency
bookings[].referencerequired
string · Short code the guest sees, e.g. 0GWYRZ2V
bookings[].statusrequired
held | confirmed | cancelled · held, confirmed or cancelled; a hold keeps its place until expires_at
bookings[].sourcerequired
string · Where it was made: dashboard, api, mcp or widget
bookings[].notesrequired
string
bookings[].metadatarequired
any · Free-form JSON object for your own integrations
bookings[].cancelled_atrequired
string | null · ISO 8601 timestamp (UTC)
bookings[].created_atrequired
string · ISO 8601 timestamp (UTC)
bookings[].expires_atrequired
string | null · Held bookings: when the hold stops keeping its place
bookings[].handlerequired
string · The guest's own page for the booking: /b/{handle}
bookings[].checkout_urlrequired
string | null · Stripe Checkout for a hold being paid online
bookings[].paid_atrequired
string | null · When it was paid online
bookings[].payment_intent_idrequired
string | null · The Stripe payment, when paid online
bookings[].previous
object · bookings.move: where the booking was
bookings[].previous.starts_atrequired
string · ISO 8601 timestamp (UTC)
bookings[].previous.ends_atrequired
string · ISO 8601 timestamp (UTC)
bookings[].previous.session_idrequired
string | null
bookings[].offeringrequired
object
bookings[].offering.idrequired
string
bookings[].offering.namerequired
string
bookings[].offering.kindrequired
class | appointment | rental · class: scheduled sessions with seats · appointment: slots from weekly hours · rental: inventory over periods
bookings[].customerrequired
object
bookings[].customer.idrequired
string
bookings[].customer.namerequired
string
bookings[].customer.emailrequired
string
bookings[].customer.phonerequired
string

POST/customerscustomers_upsert

Create a customer, or update the given fields when the email already exists

Request

name
string · ≤ 120 chars
phone
string · ≤ 40 chars
notes
string · ≤ 5000 chars
metadata
object
emailrequired
string · email

Response 200

idrequired
string
org_idrequired
string
emailrequired
string · Lowercase; unique within the org
namerequired
string
phonerequired
string
notesrequired
string
metadatarequired
any · Free-form JSON object for your own integrations
created_atrequired
string · ISO 8601 timestamp (UTC)

PATCH/customers/{id}customers_update

Update a customer's name, phone, notes or metadata

Request

idpathrequired
string · uuid
name
string · ≤ 120 chars
phone
string · ≤ 40 chars
notes
string · ≤ 5000 chars
metadata
object

Response 200

idrequired
string
org_idrequired
string
emailrequired
string · Lowercase; unique within the org
namerequired
string
phonerequired
string
notesrequired
string
metadatarequired
any · Free-form JSON object for your own integrations
created_atrequired
string · ISO 8601 timestamp (UTC)

DELETE/customers/{id}customers_delete

Erase a customer's personal data (name, email, phone, notes) on request; their bookings stay, anonymized

Request

idpathrequired
string · uuid

Response 200

okrequired
true

Org

GET/orgorg_get

Your organization: name, slug (booking page /book/{slug}), time zone, currency and how guest messages are answered

Response 200

idrequired
string
namerequired
string
slugrequired
string · Booking page: /book/{slug}
timezonerequired
string · IANA time zone, e.g. America/Denver. Weekly hours and dates are local to it.
currencyrequired
string · ISO 4217 code in lowercase, e.g. usd
reply_windowrequired
string | null · When guests can expect a reply, e.g. "We reply by 9 AM"; part of the acknowledgement
auto_ackrequired
boolean · Emails a guest who writes "Thanks, we got your message", at most once a conversation a day
away_noticerequired
string | null · While set: shown on the booking page and sent with the acknowledgement
created_atrequired
string · ISO 8601 timestamp (UTC)

PATCH/orgorg_update

Rename the organization, change its time zone (IANA, e.g. America/Denver) or currency, or set the reply window, auto-acknowledge and away notice guests see when they write

Request

name
string · ≤ 80 chars
timezone
string · ≤ 64 chars
currency
string
reply_window
string | null · e.g. "We reply by 9 AM"; null or "" clears it
auto_ack
boolean · Email guests who write "Thanks, we got your message", at most once a conversation a day
away_notice
string | null · Shown on the booking page and sent with the acknowledgement while set; null or "" clears it

Response 200

idrequired
string
namerequired
string
slugrequired
string · Booking page: /book/{slug}
timezonerequired
string · IANA time zone, e.g. America/Denver. Weekly hours and dates are local to it.
currencyrequired
string · ISO 4217 code in lowercase, e.g. usd
reply_windowrequired
string | null · When guests can expect a reply, e.g. "We reply by 9 AM"; part of the acknowledgement
auto_ackrequired
boolean · Emails a guest who writes "Thanks, we got your message", at most once a conversation a day
away_noticerequired
string | null · While set: shown on the booking page and sent with the acknowledgement
created_atrequired
string · ISO 8601 timestamp (UTC)

GET/org/exportorg_export

Export all your data as JSON: org, offerings, hours, sessions, customers, bookings, conversations, messages, saved replies, webhooks and the last 1000 events

Response 200The org, offerings, hours, sessions, customers, bookings, conversations, messages, saved replies, webhooks (no secrets) and the last 1000 events

Events

GET/eventsevents_list

Everything that happened, oldest first. Poll with after=<next_after> to follow along.

Request

afterquery
integer · ≥ 0
typequery
string · ≤ 60 chars · e.g. booking.confirmed
limitquery
integer · 1–500

Response 200

datarequired
object[]
data[].idrequired
integer · Increasing; poll with after=<id>
data[].typerequired
string · e.g. booking.confirmed, offering.updated
data[].datarequired
any · The resource after the change: the booking, session, offering, customer or org
data[].created_atrequired
string · ISO 8601 timestamp (UTC)
next_afterrequired
integer · Pass as after= to get what happened next

Webhooks

GET/webhookswebhooks_list

List webhook endpoints and their last delivery status

Response 200

datarequired
object[]
data[].idrequired
string
data[].urlrequired
string
data[].eventsrequired
string[] · Event types it receives; ["*"] means all
data[].activerequired
boolean
data[].last_statusrequired
integer | null · HTTP status of the last delivery; 0 = unreachable
data[].last_attempt_atrequired
string | null · ISO 8601 timestamp (UTC)
data[].created_atrequired
string · ISO 8601 timestamp (UTC)

POST/webhookswebhooks_create

Send events to an HTTPS URL, signed with HMAC-SHA256. Returns the signing secret once.

Request

urlrequired
string · uri
events
string[] · ≤ 30 items · Event types, or ["*"] for all (default)

Response 201

idrequired
string
urlrequired
string
eventsrequired
string[] · Event types it receives; ["*"] means all
activerequired
boolean
last_statusrequired
integer | null · HTTP status of the last delivery; 0 = unreachable
last_attempt_atrequired
string | null · ISO 8601 timestamp (UTC)
created_atrequired
string · ISO 8601 timestamp (UTC)
secretrequired
string · Verifies the Daybag-Signature header. Shown once.

DELETE/webhooks/{id}webhooks_delete

Stop sending events to a webhook endpoint

Request

idpathrequired
string · uuid

Response 200

okrequired
true

Billing

GET/billingbilling_get

Your plan (free or pro) and this month's confirmed bookings against the free plan's soft cap of 25

Response 200

planrequired
free | pro · pro: payment at booking, no daybag mark, no booking cap
usagerequired
object
usage.usedrequired
integer · Confirmed bookings created this UTC month
usage.caprequired
integer · The free plan's soft cap. Bookings keep confirming past it.
usage.pctrequired
integer · used as a percentage of cap; keeps climbing past 100