Skip to main content

Booking API

All endpoints accept the API key. organization_id, space_id, and space_group_id are always required on create.

6.1 Create a Booking — POST /api/bookings​

Use this on every new event in your calendar.

Field Reference​

FieldTypeRequiredNotes
organization_idUUIDyes
space_idUUIDyesMust be in third_party mode with an approved connection.
space_group_idUUIDyesMust match the space’s group.
titlestringyesMax 255 chars.
descriptionstringnoFree-form.
start_timeISO-8601yesUTC.
end_timeISO-8601yesMust be after start_time.
attendeesarrayyesPass [] if none. Convention: { name, email }.
total_amountnumber ≥ 0yesPass 0 if payment handled outside ZenSpace.
deposit_amountnumber ≥ 0yesPass 0 for third_party.
organizer_emailemailoptional*Optional in third_party mode; required in zenspace/hybrid.
booking_sourceenumnoRecommended: external.
metadata.external_event_idstringstrongly rec.Your own event ID for dedupe.

Key Behaviors for third_party Mode​

  • Immediately confirmed and paid. No Stripe payment intent is created. Payment is handled by your system.

  • Organizer emails are opt-in per meeting space via the email_notification flag on the space (defaults to false).

  • Scheduler forwarding and booking-access credential generation proceed normally. Credentials (magic link / lock PIN / wifi voucher) are always generated at T-15 if a physical-space mapping exists.

  • No webhook is fired back to you for this creation (it came from you).

Precondition Errors​

ConditionHTTPMessage
No connection exists for the space400Cannot create booking: No third-party connection found...
No approved connection400Cannot create booking: No approved third-party connection found...
Any pending/suspended connection exists400Cannot create booking: Third-party connection(s) are not in approved state...
Time overlap with another non-cancelled booking400Time slot already booked
Voucher applied without organizer_email400organizer_email is required when applying a voucher

6.2 Update a Booking — PUT /api/bookings/{id}​

  • Only send fields you want to change.

  • Time changes are validated against overlaps and business hours the same way as on create.

  • Do not use update to cancel — use POST /:id/cancel.

6.3 Cancel a Booking — POST /api/bookings/{id}/cancel​

  • Idempotent against already-cancelled bookings: returns 400 if cancelled again.

  • Scheduler forwarding is cleaned up automatically.

  • Organizer cancellation email is sent if organizer_email is set.

  • Refunds: third_party bookings have no ZenSpace payment. Process refunds in the originating system.

6.4 Get a Single Booking — GET /api/bookings/{id}​

Returns the full booking object. Useful for reconciling state after a webhook or checking whether a booking still exists.

6.5 Bulk Create — POST /api/bookings/bulk​

For importing an existing calendar during initial sync. Accepts an array of bookings and processes them sequentially.

Use sparingly. Failures per-row don’t stop the batch; inspect the failed array.

6.6 List Bookings — GET /api/bookings​

This endpoint requires JWT auth (read:bookings permission), not an API key. Your bridge cannot call it directly. Reconciliation from the bridge side is done via stored (external_event_id, zenspace_booking_id) mappings and GET /api/bookings/{id}.