Contents
On this page

Create Booking (Public) - Plugixa Car Wash

POST /plugixa-carwash/v1/public/bookings

Book a wash for a customer, the way the booking form does: priced, checked against the form and the free times, and given a bay under a lock so two people cannot take the same one.

Open to anyone: no sign-in. Rate-limited per visitor address to 10 bookings an hour (bucket carwash_book), with a honeypot field and a CAPTCHA hook. See Public routes.

Note. The server never takes the browser’s word for a price or a time. It prices the booking again, and refuses a time that is not one of the available times.

Request

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

Request body

Content type: application/json

Field Type Required Description
form_id integer Yes A published booking form. Every choice must be one it offers.
location_id integer Yes One of the form’s locations.
vehicle_type_id integer When any exist One of the form’s vehicle types.
package_id integer Unless services form One of the form’s packages.
service_ids array No As for Get Price Quote.
date string Yes Y-m-d, in the location’s time zone.
time string Yes H:i, one of the available times.
email string Yes A valid address: the confirmation goes there. Signed in with X-PCW-Session, the account’s address is used instead.
first_name string Per form And last_name, phone, company, vehicle_make, vehicle_plate, address, message: required when the form marks them required. Over-long values are cut, not refused.
address string Mobile Required at a mobile location, whatever the form says.
agreements array Per form One boolean per agreement on the form, in its order. Every required one must be true.
coupon string No A coupon code, or with Pro a gift card code.
payment_method string Per form One of the form’s payment_methods. Required when more than one is enabled and something is due.
page_url string No The page the customer booked on, so e-mails can link back to it. Only an address on your own site is kept.
website string No The honeypot. Leave it out or empty: anything in it refuses the request.
captcha_token string No Handed to the plugixa_carwash_public_request_captcha filter, if you hook one.

The status is chosen for you: confirmed when Settings auto-confirm bookings (the default), pending otherwise, and hold when the customer pays online with Pro Stripe, until the payment arrives. A bay is never chosen by the visitor: resource_id is ignored. The customer record is found or created by e-mail.

{
  "form_id": 1,
  "location_id": 3,
  "vehicle_type_id": 2,
  "package_id": 4,
  "date": "2026-11-14",
  "time": "09:00",
  "first_name": "Emma",
  "last_name": "Stone",
  "email": "emma@example.com",
  "phone": "+1 217 555 0123",
  "vehicle_make": "Honda CR-V",
  "coupon": "SPRING10",
  "payment_method": "cash",
  "agreements": [
    true
  ],
  "website": ""
}

Responses

201 Created. data is the booking as the customer sees it.

{
  "success": true,
  "data": {
    "number": "CW2026-0043",
    "token": "9f1c2e7a5b3d4c6e8f0a1b2c3d4e5f60",
    "status": "confirmed",
    "location": "Riverside",
    "date": "2026-11-14",
    "time": "09:00",
    "start_at": "2026-11-14 15:00:00",
    "end_at": "2026-11-14 16:00:00",
    "duration": 60,
    "items": [
      {
        "name": "Deluxe",
        "price": 49.0,
        "role": "package"
      },
      {
        "name": "Coupon SPRING10",
        "price": -4.9,
        "role": "discount"
      }
    ],
    "subtotal": 44.1,
    "tax": 2.76,
    "total": 46.86,
    "currency": "USD",
    "first_name": "Emma",
    "email": "emma@example.com",
    "payment_status": "unpaid",
    "payment_method": "cash",
    "discount": 4.9,
    "paid": 0.0,
    "due": 46.86,
    "can_cancel": true
  }
}
Field Type Meaning
data.number string The booking reference
data.token string The booking’s private 32-character key. Whoever has it can read and cancel the booking: treat it like a password
data.status string hold (waiting for an online payment), pending, confirmed, in_progress, completed, cancelled or no_show
data.location string The location’s name
data.date string Local date, Y-m-d
data.time string Local start time, H:i
data.start_at string UTC start
data.duration integer Minutes
data.items array The priced lines: name, price, role
data.total number What the booking costs
data.paid number Paid so far, less refunds
data.due number Still to pay
data.can_cancel boolean Whether Cancel Booking would be accepted now: the booking is hold, pending or confirmed and the cancellation cut-off has not passed
data.payment object Only when an online payment is to be made: redirect_url to send the customer to, or error

Errors

Status Code When
429 plugixa_carwash_rate_limited This address has used up its requests for the hour.
400 plugixa_carwash_rejected The website honeypot is filled in.
403 plugixa_carwash_captcha_failed Your CAPTCHA hook refused the request.
404 plugixa_carwash_form_not_found form_id is missing, or the form does not exist or is not published: “This booking form is not available.”
422 plugixa_carwash_not_offered The location, vehicle type, package or an extra is not one this form offers, or it is not published. The message says which, for example “Choose your vehicle type.” or “One of the chosen extras is not available with this 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_time_not_offered The time is not one the form offers: outside the hours or the grid, too soon, or too far ahead.
422 plugixa_carwash_invalid_email email is missing or not valid. data.field is email.
422 plugixa_carwash_missing_{field} A field the form requires is empty. data.field names it.
422 plugixa_carwash_missing_address No address for a mobile location.
422 plugixa_carwash_agreement_required A required agreement is not accepted.
422 plugixa_carwash_invalid_payment_method No payment method, or one that is not enabled.
422 plugixa_carwash_invalid_coupon The code does not apply. The message says why.
409 plugixa_carwash_slot_taken The time was just taken: “Sorry, that time was just taken. Please choose another.”
503 plugixa_carwash_busy Too many bookings at that location at once. Try again.
500 plugixa_carwash_insert_failed The database refused the booking.

Refusals about one field carry it in data.field, so a form can point at it. Pro apps can add their own checks.

Plus the errors every endpoint can return.

Examples

curl -s -X POST "https://your-site.example/wp-json/plugixa-carwash/v1/public/bookings" \
  -H "Content-Type: application/json" \
  -d '{"form_id":1,"location_id":3,"vehicle_type_id":2,"package_id":4,"date":"2026-11-14","time":"09:00","first_name":"Emma","last_name":"Stone","email":"emma@example.com","phone":"+1 217 555 0123","vehicle_make":"Honda CR-V","coupon":"SPRING10","payment_method":"cash","agreements":[true],"website":""}'
<?php
$ch = curl_init('https://your-site.example/wp-json/plugixa-carwash/v1/public/bookings');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST  => 'POST',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER     => [
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS     => json_encode([
        'form_id'         => 1,
        'location_id'     => 3,
        'vehicle_type_id' => 2,
        'package_id'      => 4,
        'date'            => '2026-11-14',
        'time'            => '09:00',
        'first_name'      => 'Emma',
        'last_name'       => 'Stone',
        'email'           => 'emma@example.com',
        'phone'           => '+1 217 555 0123',
        'vehicle_make'    => 'Honda CR-V',
        'coupon'          => 'SPRING10',
        'payment_method'  => 'cash',
        'agreements'      => [true],
        'website'         => '',
    ]),
]);
$response = json_decode(curl_exec($ch), true);
curl_close($ch);
const response = await fetch('https://your-site.example/wp-json/plugixa-carwash/v1/public/bookings', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    form_id: 1,
    location_id: 3,
    vehicle_type_id: 2,
    package_id: 4,
    date: '2026-11-14',
    time: '09:00',
    first_name: 'Emma',
    last_name: 'Stone',
    email: 'emma@example.com',
    phone: '+1 217 555 0123',
    vehicle_make: 'Honda CR-V',
    coupon: 'SPRING10',
    payment_method: 'cash',
    agreements: [true],
    website: '',
  }),
});
const { data } = await response.json();

Quick Links

Share