Contents
Book a Space - Plugixa Car Parking
POST /plugixa-car-parking/v1/booking
Create a booking the way the booking form does: the selection is checked, priced and held in one step, and the booking’s payment key comes back for Start Payment.
Anyone may call it, signed in or not, with the public nonce the plugin’s pages print (see Public routes). It counts against the booking rate limit: 10 an hour per visitor address.
Note. The booking belongs to whoever is signed in when the request is made, or to nobody for a guest. A
user_idin the body is ignored. A booking made withoutcustomer_emailcannot be found later through List Customer Bookings by a guest, because that lookup matches the e-mail.
Request
POST https://your-site.example/wp-json/plugixa-car-parking/v1/booking
Request body
Content type: application/json. Send the nonce as security here or in the X-Plugixa-Carparking-Nonce header.
| Field | Type | Required | Description |
|---|---|---|---|
location_id |
integer |
Yes | An active location on the booking form. |
space_type_id |
integer |
Yes | A space type stocked at the location, active, on the form and priced there. |
entry |
string |
Yes | Entry date and time, car park local time, YYYY-MM-DD HH:MM. |
exit |
string |
Yes | Exit date and time. Must be after entry. |
quantity |
integer |
No | Number of spaces. Defaults to 1. A location with numbered spaces PRO takes one space per booking. |
space_id |
integer |
No | PRO A numbered space to hold. Without it, a free one is chosen. |
coupon |
string |
No | A coupon code, applied under the same rules as Price a Stay. An invalid code is ignored. |
extras |
array |
No | PRO Extras, each { "id": 3, "quantity": 1 }. |
form_id |
integer |
No | The booking form. Defaults to the default form. booking_form_id is accepted as well. |
customer_name |
string |
No | The customer’s name. |
customer_email |
string |
No | The customer’s e-mail. |
customer_phone |
string |
No | The customer’s phone number. |
license_plate |
string |
No | The vehicle’s licence plate. |
vehicle |
object |
No | Vehicle details, stored as sent. |
billing |
object |
No | Billing details, stored as sent. |
notes |
string |
No | A note from the customer. |
meta |
object |
No | Answers to the form’s own fields, by field key. Required fields must be answered, e-mail fields must hold an e-mail, and select fields one of their options. Keys the form does not have are dropped. |
gateway |
string |
No | The payment method the customer picked, stored on the booking. Defaults to offline. |
security |
string |
Yes | The public nonce, unless sent in the header. |
The price is always worked out on the server. The billing unit is the location’s own: a billing_type in the body is dropped. The new booking takes the status set in the settings (by default pending), with payment_status unpaid. When the settings hold pending bookings for a limited time, hold_expires_at says until when.
The hidden field pcp_hp is a spam trap: leave it out.
{
"location_id": 2,
"space_type_id": 1,
"entry": "2026-11-20 08:00",
"exit": "2026-11-23 18:00",
"quantity": 1,
"customer_name": "Lucas Bernard",
"customer_email": "lucas@example.com",
"customer_phone": "+33 6 12 34 56 78",
"license_plate": "AB-123-CD",
"gateway": "offline"
}
Responses
200 OK. data is the new booking.
{
"success": true,
"message": "Your booking has been created.",
"data": {
"id": "57",
"booking_ref": "PKG-3F9A2C",
"language_code": null,
"location_id": "2",
"space_type_id": "1",
"space_id": null,
"booking_form_id": "1",
"user_id": null,
"status": "pending",
"billing_type": "day",
"entry_datetime": "2026-11-20 08:00:00",
"exit_datetime": "2026-11-23 18:00:00",
"quantity": "1",
"hold_expires_at": null,
"license_plate": "AB-123-CD",
"vehicle": null,
"customer_name": "Lucas Bernard",
"customer_email": "lucas@example.com",
"customer_phone": "+33 6 12 34 56 78",
"billing": null,
"currency": "EUR",
"subtotal": "48.0000",
"discount_total": "0.0000",
"tax_total": "0.0000",
"deposit_amount": "0.0000",
"total": "48.0000",
"amount_paid": "0.0000",
"coupon_id": null,
"payment_method": "offline",
"payment_status": "unpaid",
"notes": null,
"meta": null,
"created_by": "0",
"modified_by": "0",
"created_at": "2026-11-12 09:30:00",
"updated_at": null,
"modified_at": "2026-11-12 09:30:00",
"deleted_at": null,
"summary_url": "https://your-site.example/booking-summary/?plugixa_carparking_ref=PKG-3F9A2C&plugixa_carparking_token=9c1e5b2a7d",
"payment_key": "4f0c2a9e1b7d3c5a8e6f0b2d4c6a8e1f"
}
}
Note. This route returns the stored row as the database gives it back: ids, quantities and amounts are strings (
"48.0000"), not numbers. Convert them before you compute with them.
| Field | Type | Meaning |
|---|---|---|
data.id |
string |
The booking’s id |
data.booking_ref |
string |
The reference shown to the customer: the prefix from the settings, by default PKG-, then six characters |
data.status |
string |
The status set in the settings, by default pending |
data.entry_datetime, data.exit_datetime |
string |
Car park local time |
data.hold_expires_at |
string|null |
When an unpaid pending booking stops holding its space, local time, or null |
data.total |
string |
What the booking costs |
data.deposit_amount |
string |
What is due now when the location takes a deposit PRO |
data.meta |
object|null |
The form answers, by key, with their labels under _labels |
data.created_at |
string |
UTC datetime |
data.summary_url |
string |
The booking summary page with its access token. Present only when a summary page is set in the settings |
data.payment_key |
string |
The key Start Payment needs as booking_key. Keep it: it is not shown anywhere else |
Errors
| Status | Code | When |
|---|---|---|
400 |
plugixa_carparking_rejected |
The pcp_hp spam trap was filled in. |
403 |
rest_error |
The nonce is missing or not valid: “Your session expired. Please refresh and try again.” |
410 |
form_unavailable |
form_id is not an active booking form. |
422 |
location_unavailable |
The location does not exist, is not active, or is not on the form. |
422 |
type_unavailable |
The space type is not stocked here, not active, or not on the form. |
422 |
no_price |
The space type has no price for the location’s billing unit. |
422 |
invalid_field |
An answer in meta is missing or not valid. data.field names the field. |
422 |
missing_fields |
location_id, space_type_id, entry or exit is missing. |
422 |
invalid_range |
exit is not after entry. |
422 |
too_soon |
entry is in the past or inside the minimum notice. |
422 |
too_far |
entry is further ahead than bookings are taken. |
422 |
location_closed |
The car park is closed on the entry or exit date. |
422 |
outside_hours |
The entry or exit time is outside opening hours. |
409 |
no_availability |
Not enough free spaces for the window, or the numbered space asked for is taken. |
409 |
busy |
Another booking at the same location was being made at that moment. Try again. |
500 |
create_failed |
The booking could not be saved. |
Plus the errors every endpoint can return.
Examples
curl -s -X POST "https://your-site.example/wp-json/plugixa-car-parking/v1/booking" \
-H "Content-Type: application/json" \
-H "X-Plugixa-Carparking-Nonce: $PCP_NONCE" \
-d '{"location_id":2,"space_type_id":1,"entry":"2026-11-20 08:00","exit":"2026-11-23 18:00","quantity":1,"customer_name":"Lucas Bernard","customer_email":"lucas@example.com","customer_phone":"+33 6 12 34 56 78","license_plate":"AB-123-CD","gateway":"offline"}'
<?php
$ch = curl_init('https://your-site.example/wp-json/plugixa-car-parking/v1/booking');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Content-Type: application/json',
'X-Plugixa-Carparking-Nonce: ' . getenv('PCP_NONCE'),
],
CURLOPT_POSTFIELDS => json_encode([
'location_id' => 2,
'space_type_id' => 1,
'entry' => '2026-11-20 08:00',
'exit' => '2026-11-23 18:00',
'quantity' => 1,
'customer_name' => 'Lucas Bernard',
'customer_email' => 'lucas@example.com',
'customer_phone' => '+33 6 12 34 56 78',
'license_plate' => 'AB-123-CD',
'gateway' => 'offline',
]),
]);
$response = json_decode(curl_exec($ch), true);
curl_close($ch);
const response = await fetch('https://your-site.example/wp-json/plugixa-car-parking/v1/booking', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Plugixa-Carparking-Nonce': PCP_NONCE,
},
body: JSON.stringify({
location_id: 2,
space_type_id: 1,
entry: '2026-11-20 08:00',
exit: '2026-11-23 18:00',
quantity: 1,
customer_name: 'Lucas Bernard',
customer_email: 'lucas@example.com',
customer_phone: '+33 6 12 34 56 78',
license_plate: 'AB-123-CD',
gateway: 'offline',
}),
});
const { data } = await response.json();
Quick Links
Share