Skip to main content
Create bookings and orders directly from the admin API using the orders/from-config endpoint. This bypasses the public checkout flow and is designed for back-office operations. The same endpoint also edits an existing order when the config carries an order_id — see Editing an Existing Order. To change one confirmed booking in place (resource, dates, fields, add-ons, sub-bookings) without rewriting the whole order, use Admin Booking Edit. For the public checkout flow, see Order & Checkout Flow. For general conventions, see JSON-API Conventions.

Prerequisites

  • A valid Bearer token with admin access — see Authentication
  • Organization context (?o={organization_id})
  • At least one resource and service configured in the organization

For Admin UI integrations, prefer the dynamic form flow over manually assembling all custom-field and participant payloads.

Step A - Build a Dynamic Checkout Form

This returns a form object (components, validations, default) that includes:
  • customer group (customer-group)
  • customer custom fields
  • order custom fields
  • per-booking personalization groups (booking custom fields, host, participants)

Step B - Apply Submitted Form Data

The response is an enriched config that is directly compatible with POST /api/v1/orders/from-config.

Step C - Create the Order

Use the enriched payload from Step B as input for POST /api/v1/orders/from-config.

Standalone Forms for Existing Records

You can also fetch standalone admin UI forms for existing records, such as customer, order, and booking edit forms. The payload structure and persistence rules for those admin UI form endpoints are documented in Admin UI Forms, not in this booking-creation guide.

When to Use


Step 1 — Pre-Calculate Pricing (Optional)

Request path documentation:
  • paths/admin/orders.yaml for POST /api/v1/orders/calculate
Before creating the order, preview the pricing and resolve available booking quota grants:
Returns calculated totals, taxes, and per-booking pricing without persisting anything. Each booking in the response includes services_label: the concatenated service list the admin calendar already shows for sequenced services (for example 1 x Cut, 1 x Wash). For a single service it matches service.name. Each booking also includes a booking_quota_grants array with all eligible grants, their applicability, projected usage, and which one is preselected. This allows the UI to display a grant selection dropdown directly from the calculate response — no separate endpoint call needed. When the user selects a different grant, re-call calculate with booking_quota_grant_id set on the booking. Set prevent_applying_default_quota: true to deselect all grants.
orders/calculate always prices the config as a new order. It ignores order_id, so it cannot preview what an edit to an existing order would cost. Apply the config and read meta.calculation from the response instead — see Editing an Existing Order.

Step 2 — Create the Order

Request path documentation:
  • paths/admin/orders.yaml for POST /api/v1/orders/from-config

Top-Level Fields

Booking Object Fields

Response

Returns a standard JSON-API orders resource with the created bookings:

Multiple Bookings in One Order

Add multiple booking objects to create them in a single order:

Editing an Existing Order

An order that already exists can be read back as a config, edited, and posted to the very same orders/from-config endpoint. The config carries an order_id, and that is what tells the endpoint to update that order instead of creating a new one. The config is the complete desired state of the order, so one document drives updates, additions and removals in a single request. To change one confirmed booking without rewriting the order, use the per-booking actions in Admin Booking Edit instead.

Step 1 — Read the Current Config

The response is the same document orders/from-config accepts, with the order’s own order_id at the top level and the persisted booking_id on every entry in bookings. Removed and cancelled bookings are omitted, and sub-bookings and sequence members are nested inside their parent entry rather than listed on their own. check_availability and notify_customer come back as false, so posting an unchanged config straight back is a no-op.

Step 2 — Post the Edited Config Back

The body is the complete desired state, not a patch. Sending only the bookings you changed will soft-delete every booking you left out.
Updatable per booking: dates, resource, service configuration (service_id), quota grant, add-ons, sub-bookings, customer, participants and host, custom fields, custom_price, and the note fields. Order-level fields behave as on create: order_customer_id, voucher_code / discount_relative / discount_absolute, add_ons and booking_passes. The response is the updated order; meta.calculation carries the full normalized totals of the order after the update — the whole order, not the delta of the edit.

Behaviour to Know

  • Pricing follows the admin booking edit: changes apply immediately. Vouchers, credit quota, payment-method codes, and gift cards on the invoice recap to the new totals so payable stays at or above zero. While the order’s invoice is still a draft it is regenerated in place; once issued, the change produces a correction that stays an unlocked draft invoice on the order for an admin to issue.
  • Applies are serialized per order — concurrent requests queue instead of diffing against a half-updated order. They are not atomic: a step that fails part-way leaves the earlier steps applied, so re-read the config before retrying.
  • Removals are soft deletes: the bookings are priced out of the order and the rows stay recoverable.
  • notify_customer only reaches added bookings. Removals are silent — soft-deleting a booking sends the customer nothing, so tell them separately if the change warrants it.
  • Changing add_ons rewrites the standalone lines rather than patching them, so their ids change. An unchanged add_ons array is left untouched.
  • Standalone add_ons and booking_passes are both synced to the config. A pass is one model per purchased unit, so lowering a bundle’s quantity soft-deletes the surplus passes (newest first, so the oldest codes survive) along with their booking quota grants. A pass whose grants have already been used is rejected with booking_pass_in_use rather than orphaning the bookings it paid for.
  • A recurring block on an entry that carries a booking_id is rejected — an existing booking cannot be expanded into a series. Series members round-trip as individual entries.
  • An empty config is rejected rather than dissolving the order.
  • Shop checkout drafts (status=draft and manually_created=false) cannot be configured. Admin-created drafts and reserved admin carts can. The API still returns cannot_modify_reserved_booking for a customer checkout cart that is still mid-flow.
  • Without an order_id the very same document creates a new order, so dropping the key is how you duplicate an existing order.

Skipping Availability Checks

Set check_availability: false to override availability constraints. Use this for:
  • Overbooking scenarios
  • Creating bookings in the past
  • Special arrangements outside normal schedules
Warning: Skipping availability checks can create conflicting bookings. Use with care.

Re-Sending Order Notifications

If the customer didn’t receive the confirmation:
Triggers the order confirmation notification to the associated customer.

Common Errors