Admin Booking Creation

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.

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

POST /api/v1/ui/admin/checkout-form?o={org_id}

{
  "booking_config": {
    "order_customer_id": null,
    "bookings": [
      {
        "customer_id": null,
        "service_id": { "{service_uuid}": 1 },
        "resource_id": "{resource_uuid}",
        "start_date": "2026-04-15T09:00:00+02:00",
        "end_date": "2026-04-15T10:00:00+02:00"
      },
      {
        "customer_id": "{optional_existing_customer_uuid}",
        "service_id": { "{service_uuid}": 1 },
        "resource_id": "{resource_uuid}",
        "start_date": "2026-04-15T10:00:00+02:00",
        "end_date": "2026-04-15T11:00:00+02:00"
      }
    ]
  }
}

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

POST /api/v1/ui/admin/checkout-form/apply?o={org_id}

{
  "form_data": {
    "customer": {
      "email": "newcustomer@example.com",
      "given_name": "Test",
      "family_name": "Customer"
    },
    "bookings_data": {
      "b_205": {
        "service_custom_fields": {
          "{custom_field_uuid}": "Wheelchair access"
        },
        "participants": [
          {
            "email": "participant@example.com",
            "given_name": "Alex",
            "family_name": "Example"
          }
        ]
      }
    }
  },
  "booking_config": {
    "bookings": [
      {
        "_booking_id": 205,
        "resource_id": "{resource_uuid}",
        "service_id": { "{service_uuid}": 1 },
        "start_date": "2026-04-15T09:00:00+02:00",
        "end_date": "2026-04-15T10:00:00+02:00"
      }
    ]
  }
}

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

Scenario Use
Customer books through the website Public Checkout
Admin creates a booking on behalf of a customer This guide
Bulk/batch booking creation This guide
Booking without availability check (override) This guide

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:

POST /api/v1/orders/calculate?o={org_id}

{
  "bookings": [
    {
      "resource_id": "{resource_uuid}",
      "service_id": { "{service_uuid}": 1 },
      "start_date": "2026-04-15T09:00:00+02:00",
      "end_date": "2026-04-15T10:00:00+02:00"
    }
  ],
  "voucher_code": "SUMMER20"
}

Returns calculated totals, taxes, and per-booking pricing without persisting anything.


Step 2 — Create the Order

Request path documentation:

  • paths/admin/orders.yaml for POST /api/v1/orders/from-config
POST /api/v1/orders/from-config?o={org_id}

{
  "order_customer_id": "{customer_uuid}",
  "bookings": [
    {
      "resource_id": "{resource_uuid}",
      "service_id": { "{service_uuid}": 1 },
      "start_date": "2026-04-15T09:00:00+02:00",
      "end_date": "2026-04-15T10:00:00+02:00",
      "quantity": 1,
      "description": "Team meeting",
      "booking_add_ons": [
        { "add_on_id": "{add_on_uuid}", "quantity": 2 }
      ]
    }
  ],
  "notify_customer": true,
  "complete_order": true,
  "check_availability": true,
  "timezone": "Europe/Berlin"
}

Top-Level Fields

Field Type Required Default Description
order_customer_id string No Customer UUID for the entire order
bookings array Yes Array of booking configurations
voucher_code string No Discount voucher code
notify_customer boolean No true Send confirmation email to customer
complete_order boolean No true false creates a draft order
check_availability boolean No true false skips availability validation
timezone string No Timezone for date interpretation

Booking Object Fields

Field Type Required Description
resource_id string/array Yes Resource UUID(s). Array for multi-resource bookings.
service_id object Yes Map of service_uuid → quantity (e.g. {"uuid": 1})
start_date string Yes Booking start (Atom format)
end_date string Yes Booking end (Atom format)
customer_id string No Per-booking customer (overrides order_customer_id)
quantity integer No Number of slots/participants
description string No Internal description
note string No Admin-visible note
customer_note string No Customer-visible note
booking_add_ons array No Array of { add_on_id, quantity }
sub_bookings array No Array of { service_id, resource_id, quantity } for linked sub-bookings
service_custom_fields object No Custom field values (UUID → value)
order_custom_fields object No Order-level custom field values
recurring object No Recurring rules (frequency, interval, until, count)
timeslot_series_id string No Link to a specific timeslot series

Response

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

{
  "data": {
    "type": "orders",
    "id": "order-uuid",
    "attributes": {
      "status": "completed",
      "manually_created": true,
      "total": 5000,
      "currency": "EUR"
    },
    "relationships": {
      "bookings": {
        "data": [{ "type": "bookings", "id": "b1" }]
      },
      "customer": {
        "data": { "type": "customers", "id": "c1" }
      }
    }
  }
}

Multiple Bookings in One Order

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

{
  "order_customer_id": "{customer_uuid}",
  "bookings": [
    {
      "resource_id": "{room_uuid}",
      "service_id": { "{meeting_service}": 1 },
      "start_date": "2026-04-15T09:00:00+02:00",
      "end_date": "2026-04-15T10:00:00+02:00"
    },
    {
      "resource_id": "{desk_uuid}",
      "service_id": { "{desk_service}": 1 },
      "start_date": "2026-04-15T10:00:00+02:00",
      "end_date": "2026-04-15T17:00:00+02:00"
    }
  ]
}

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:

GET /api/v1/orders/{order_id}/send-notification?o={org_id}

Triggers the order confirmation notification to the associated customer.


Common Errors

Error Cause Solution
422 — resource_id required Missing resource in booking object Include resource_id for each booking
422 — service_id required Missing service mapping Provide service_id as { "uuid": quantity }
422 — slot unavailable Time conflict with existing booking Set check_availability: false to override, or pick a different time
422 — customer not found Invalid order_customer_id Verify the customer UUID exists in the organization
403 — unauthorized Insufficient permissions Requires order creation permission for the organization