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
Recommended Flow (Admin UI Forms)
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.yamlforPOST /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.yamlforPOST /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 |