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