Contents
On this page

Create Booking - Plugixa Car Wash

POST /plugixa-carwash/v1/bookings

Book a wash on behalf of a customer. The booking is priced on the server and given a free bay or team, exactly as the staff app does.

Needs the plugixa_carwash_create capability.

Note. A staff booking is not held to the opening hours, the time grid, the minimum notice or the booking window: any date and time is accepted as long as a suitable bay or team is free then. Use Free Times for Staff to offer only the times a customer could book.

Note. customer_id is ignored. The customer is found by email: an existing customer with that address gets the booking (and any of their empty name, phone, company or address fields are filled from it), otherwise a new customer is created.

Request

POST https://your-site.example/wp-json/plugixa-carwash/v1/bookings

Request body

Content type: application/json

Field Type Required Description
location_id integer Yes A published location.
vehicle_type_id integer When any exist A published vehicle type. Required as soon as one vehicle type is published.
package_id integer No A published package. Send a package, service_ids, or both.
service_ids array No Published service ids, as an array or a comma-separated string. Staff may add any published service, add-on or not.
date string Yes Y-m-d, in the location’s time zone.
time string Yes H:i, in the location’s time zone.
resource_id integer No A bay or team at this location. Left out, the first suitable free one is chosen.
status string No pending or confirmed. Anything else, or nothing, means confirmed.
email string Yes A valid e-mail address. Picks or creates the customer.
first_name string No Cut to 100 characters.
last_name string No Cut to 100 characters.
phone string No Cut to 50 characters.
company string No Cut to 190 characters.
vehicle_make string No Cut to 120 characters. Remembered on the customer’s vehicles.
vehicle_plate string No Cut to 30 characters. Remembered on the customer’s vehicles.
address string No Cut to 255 characters.
message string No A note from the customer.
staff_notes string No Internal notes.
coupon string No A coupon code. A code that does not apply refuses the booking.
payment_method string No A payment method id such as cash or bank_transfer. Left out, the first enabled method is recorded when something is due. Not checked against the enabled methods for staff.

The price comes from the catalogue, never from the request: package or service price, the vehicle type’s fee and any per-vehicle price, the location’s tax rate, and coupons. The duration is worked out the same way, and the bay is held for it plus the location’s buffer. Pro apps such as Memberships and Fleet accounts can change the price as well.

{
  "location_id": 3,
  "vehicle_type_id": 2,
  "package_id": 4,
  "date": "2026-11-14",
  "time": "09:00",
  "first_name": "Lucas",
  "last_name": "Bernard",
  "email": "lucas@example.com",
  "phone": "+1 217 555 0199",
  "vehicle_make": "Toyota RAV4",
  "vehicle_plate": "ABC1234",
  "staff_notes": "Regular customer"
}

Responses

201 Created. data is the new booking.

{
  "success": true,
  "data": {
    "id": 42,
    "number": "CW2026-0042",
    "form_id": null,
    "location_id": 3,
    "resource_id": 5,
    "customer_id": 25,
    "customer_vehicle_id": 31,
    "vehicle_type_id": 2,
    "package_id": 4,
    "start_at": "2026-11-14 15:00:00",
    "end_at": "2026-11-14 16:00:00",
    "blocked_until": "2026-11-14 16:10:00",
    "duration": 60,
    "status": "confirmed",
    "hold_expires_at": null,
    "first_name": "Lucas",
    "last_name": "Bernard",
    "email": "lucas@example.com",
    "phone": "+1 217 555 0199",
    "company": "",
    "vehicle_make": "Toyota RAV4",
    "vehicle_plate": "ABC1234",
    "address": "",
    "message": "",
    "agreements": [],
    "currency": "USD",
    "subtotal": 49.0,
    "discount": 0.0,
    "coupon_code": "",
    "tax": 3.06,
    "total": 52.06,
    "payment_method": "cash",
    "payment_status": "unpaid",
    "source": "staff",
    "page_url": "",
    "staff_notes": "Regular customer",
    "created_by": 1,
    "modified_by": 1,
    "created_at": "2026-11-12 09:30:00",
    "modified_at": "2026-11-12 09:30:00",
    "deleted_at": null,
    "items": [
      {
        "role": "package",
        "item_id": 4,
        "name": "Deluxe",
        "price": 49.0,
        "duration": 60
      }
    ],
    "events": [
      {
        "from": "",
        "to": "confirmed",
        "note": "Booked by staff",
        "user_id": 1,
        "created_at": "2026-11-12 09:30:00"
      }
    ],
    "next": [
      "in_progress",
      "completed",
      "cancelled",
      "no_show"
    ],
    "location": {
      "id": 3,
      "name": "Riverside"
    },
    "local_date": "2026-11-14",
    "local_time": "09:00",
    "resource": {
      "id": 5,
      "name": "Bay 1",
      "color": "#0EA5E9"
    },
    "payments": []
  }
}
Field Type Meaning
data.id integer The booking’s id
data.number string The booking reference, CW + year + id, for example CW2026-0042
data.location_id integer The location
data.resource_id integer|null The bay or mobile team it is booked on
data.customer_id integer|null The customer record it belongs to
data.vehicle_type_id integer|null The vehicle type chosen
data.package_id integer|null The package chosen, null for services only
data.start_at string UTC datetime the wash starts
data.end_at string UTC datetime the wash ends
data.blocked_until string UTC datetime the bay is free again: end_at plus the location’s buffer
data.duration integer Minutes
data.status string hold, pending, confirmed, in_progress, completed, cancelled or no_show
data.hold_expires_at string|null For a hold (waiting for an online payment): when it is cancelled if still unpaid
data.agreements array The booking form’s agreements as {text, accepted}. Empty for a staff booking
data.subtotal number Sum of the lines, discounts included
data.discount number Total of the discount lines
data.coupon_code string The coupon used, or empty
data.tax number Tax, at the location’s rate
data.total number What the booking costs
data.payment_status string unpaid, paid, partially_paid or refunded
data.source string online or staff
data.staff_notes string|null Internal notes, never shown to the customer
data.modified_at string UTC datetime of the last change
data.items array The priced lines: role (package, addon, service, fee or discount), item_id, name, price, duration
data.events array Every status change: from, to, note, user_id, created_at
data.next array The statuses it can move to from here
data.location object|null id and name
data.local_date string The start date in the location’s time zone, Y-m-d
data.local_time string The start time in the location’s time zone, H:i
data.resource object|null The bay or team: id, name, color
data.payments array Payments and refunds recorded against it. See List Booking Payments

Errors

Status Code When
422 plugixa_carwash_not_offered No such published location, vehicle type, package or service. The message says which: “Choose a location.”, “Choose your vehicle type.”, “Choose a package.”
422 plugixa_carwash_nothing_chosen Neither a package nor a service.
422 plugixa_carwash_not_for_vehicle The package or a service is switched off for this vehicle type.
422 plugixa_carwash_invalid_time date or time is missing or not in the right format.
422 plugixa_carwash_invalid_email email is missing or not valid.
422 plugixa_carwash_invalid_resource resource_id is not a bay or team at this location.
422 plugixa_carwash_invalid_coupon The coupon code does not apply. The message says why.
409 plugixa_carwash_slot_taken The chosen bay, or every suitable bay, is booked at that time.
503 plugixa_carwash_busy Too many bookings were being made at that location at once. Try again.
500 plugixa_carwash_insert_failed The database refused the booking.

Plus the errors every endpoint can return.

Examples

curl -s -X POST "https://your-site.example/wp-json/plugixa-carwash/v1/bookings" \
  -u "admin:$WP_APP_PASSWORD" \
  -H "Content-Type: application/json" \
  -d '{"location_id":3,"vehicle_type_id":2,"package_id":4,"date":"2026-11-14","time":"09:00","first_name":"Lucas","last_name":"Bernard","email":"lucas@example.com","phone":"+1 217 555 0199","vehicle_make":"Toyota RAV4","vehicle_plate":"ABC1234","staff_notes":"Regular customer"}'
<?php
$ch = curl_init('https://your-site.example/wp-json/plugixa-carwash/v1/bookings');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST  => 'POST',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_USERPWD        => 'admin:' . getenv('WP_APP_PASSWORD'),
    CURLOPT_HTTPHEADER     => [
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS     => json_encode([
        'location_id'     => 3,
        'vehicle_type_id' => 2,
        'package_id'      => 4,
        'date'            => '2026-11-14',
        'time'            => '09:00',
        'first_name'      => 'Lucas',
        'last_name'       => 'Bernard',
        'email'           => 'lucas@example.com',
        'phone'           => '+1 217 555 0199',
        'vehicle_make'    => 'Toyota RAV4',
        'vehicle_plate'   => 'ABC1234',
        'staff_notes'     => 'Regular customer',
    ]),
]);
$response = json_decode(curl_exec($ch), true);
curl_close($ch);
const auth = Buffer.from(`admin:${process.env.WP_APP_PASSWORD}`).toString('base64');
const response = await fetch('https://your-site.example/wp-json/plugixa-carwash/v1/bookings', {
  method: 'POST',
  headers: {
    'Authorization': `Basic ${auth}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    location_id: 3,
    vehicle_type_id: 2,
    package_id: 4,
    date: '2026-11-14',
    time: '09:00',
    first_name: 'Lucas',
    last_name: 'Bernard',
    email: 'lucas@example.com',
    phone: '+1 217 555 0199',
    vehicle_make: 'Toyota RAV4',
    vehicle_plate: 'ABC1234',
    staff_notes: 'Regular customer',
  }),
});
const { data } = await response.json();

Quick Links

Share