Order & Checkout Flow (Public)

Create bookings through the public cart and checkout flow. For admin-side creation (orders/from-config), see Admin Booking Creation.

For conventions, see JSON-API Conventions. For slot search, see Availability & Booking Search.


Prerequisites

  • Resource + service configuration exists
  • Cookies are enabled (cart and order authorization are cookie/query based)
  • Optional customer auth for prefilled fields

Canonical Path Docs


Flow Overview

1. Add booking(s) to cart
2. Show recommendations in cart
3. Edit cart / voucher
4. Collect checkout data
5. Optional guest email verification
6. Submit checkout
7. Handle payment redirect
8. Fetch last succeeded orders

Step 1 — Add Booking to Cart

POST /api/v1/order/bookings

{
  "resource_id": "{resource_id}",
  "service_id": {
    "{service_id}": 1
  },
  "start_date": "2026-04-15T09:00:00+02:00",
  "end_date": "2026-04-15T10:00:00+02:00",
  "add_ons_by_service": {
    "{service_id}": [
      [
        { "add_on_id": "{add_on_id}", "quantity": 2 }
      ]
    ]
  },
  "sub_bookings_by_service": {
    "{service_id}": [
      []
    ]
  }
}

add_ons_by_service and sub_bookings_by_service are mapped by service id and booking index:

Field Type Notes
service_id string | object Object map (service_id -> quantity) is current format
add_ons_by_service object {service_id: AddOn[][]}
add_ons_by_service[service_id][booking_index][] array item {add_on_id, quantity}
sub_bookings_by_service object {service_id: SubBooking[][]}

Legacy inputs (booking_add_ons, sub_bookings) still exist but are deprecated.

Exact add-booking request fields (current request rules):

Field Type Required Notes
start_date string (atom date-time) yes
end_date string (atom date-time) yes >= start_date
service_id string | int | object yes object map recommended (service_id -> quantity)
resource_id string | int | array yes can be multi-resource
description string no nullable
customer_note string no nullable
add_ons_by_service object no nullable
sub_bookings_by_service object no nullable
recurring object no nullable
recurring.frequency enum no daily, weekly, monthly
recurring.duration int conditional required when end_date not used by recurring flow
recurring.until date no nullable
recurring.interval int no
recurring.days array no
recurring.month_day int no
recurring.week_start string no
recurring.set_pos int no
strategy enum no availability booking strategy
timezone IANA timezone no
create_sequence boolean no
timeslot_series_id int no
original_booking_id string no
book_on_behalf string no customer account uuid
account_pass string no pass code
booking_quota_grant_id string | int | array no
prevent_applying_default_quota boolean no
adhoc boolean no

Path docs: /api/v1/order/bookings in ../../paths/public/orders.yaml.

Current cart:

GET /api/v1/order

Step 2 — Recommendations in Cart (Before Checkout)

Recommendations are a cart-time feature, not a post-order step.

GET /api/v1/order/recommendations

Step 3 — Edit Cart and Voucher

Edit add-ons for one booking:

POST /api/v1/order/bookings/{booking_id}/edit-addons

{
  "addons": [
    { "add_on_id": "{add_on_id}", "quantity": 1 }
  ]
}

Remove one booking:

DELETE /api/v1/order/bookings/{booking_id}

Remove multiple bookings:

DELETE /api/v1/order/bookings/delete-multiple

{
  "filter": {
    "id": ["{booking_id_1}", "{booking_id_2}"]
  }
}

Clear cart:

GET /api/v1/order/bookings/delete-all

Apply voucher:

POST /api/v1/order/voucher

{
  "code": "SUMMER20"
}

Remove voucher:

DELETE /api/v1/order/voucher

Optional booking pre-calculation:

POST /api/v1/order/bookings/calculate

Step 4 — Collect Checkout Data

Collect the customer data, payment method, and legal document acceptances required for the current organization.

Public integrations should treat these requirements as organization-defined checkout configuration rather than depending on internal UI helper endpoints.


Step 5 — Optional Guest Email Verification

If guest email verification is enabled for the checkout flow, complete that verification before the final order submission.

The external contract is the verify_guest_email field on POST /api/v1/order. Helper endpoints used by anny-hosted UIs are internal-only and not part of the external integration surface.


Step 6 — Submit Checkout

POST /api/v1/order

{
  "customer": {
    "email": "jane@example.com",
    "first_name": "Jane",
    "last_name": "Doe"
  },
  "payment_method": "{payment_method_slug}",
  "documents": {
    "{legal_doc_uuid}": true
  },
  "verify_guest_email": {
    "state": "{email_verification_state}",
    "code": "123456"
  }
}

Validation depends on the organization's checkout configuration and selected payment method.


Step 7 — Handle Payment Redirect

If meta.payment.next_action.type = redirect, redirect to meta.payment.next_action.url.

After the payment provider redirects the user back, proceed to Step 8 to fetch the completed order.


Step 8 — Fetch Last Succeeded Orders

last-succeeded authorization is token-pair based and requires matching oids[] and oats[] arrays.

GET /api/v1/order/last-succeeded?oids[]={order_id_1}&oats[]={access_token_1}&oids[]={order_id_2}&oats[]={access_token_2}

Common Errors

Error Cause Solution
422 add-ons ignored or invalid Wrong add_ons_by_service shape Use service_id -> booking_index -> [{add_on_id, quantity}]
422 slot unavailable Race condition between selection and checkout Re-check availability and re-add booking
409 order already completed Duplicate checkout submit Block duplicate submit and refresh cart state
422 verification code invalid Wrong/expired guest email code Request a new code