Contents
On this page

Hold Car - Plugixa Car Rental

POST /plugixa-car-rental/v1/public/holds

Hold a car of one model for a visitor while they check out. This creates a pending booking and returns the token that opens it.

Public: no sign-in and no nonce. Needs the Booking form app on. Rate limited to 15 requests an hour per visitor address: see Public routes.

The hold lasts as long as the booking rules say (15 minutes by default), counted from now. A visitor books a model: the car is chosen for them, and vehicle_unit_id, the customer fields and notes are ignored here, as the customer’s details are given at checkout. A hold that runs out is set to expired by a scheduled task.

Keep the token. It is shown once and only its fingerprint is stored. Every later step of the flow needs it.

Request

POST https://your-site.example/wp-json/plugixa-car-rental/v1/public/holds

Request body

Content type: application/json

Field Type Required Description
pickup_location_id integer Yes A published location that allows pickups.
return_location_id integer No A published location that allows returns. Omitted or 0: the pickup location.
pickup_at string Yes Local time at the pickup location: YYYY-MM-DD HH:MM, with optional seconds, a space or a T between. No time-zone offset, and a bare date is refused.
return_at string Yes Local time at the return location, in the same form. After pickup_at.
vehicle_model_id integer Yes A published vehicle model.
extras object[] No Extras to add, as {"id": 3, "quantity": 1}. Only published extras count, and a quantity above the extra’s max_quantity is cut to it. Needs the Extras app.
coupon string No A coupon code. Needs the Coupons app.
driver_age integer No The driver’s age, 16 to 99, for the young and senior driver surcharges and each model’s minimum age. Needs Pro with the Driver age app.
delivery_address string No Deliver the car to this address. Needs Pro with the Delivery and collection app.
collection_address string No Collect the car from this address at the end. Needs Pro with the Delivery and collection app.
currency string No Price in another of your currencies, by its code. Needs Pro with the Multi-currency app. Unknown codes are ignored.
website string No A honeypot: leave it empty or leave it out.
captcha_token string No Passed to a CAPTCHA check, if your site adds one.
{
  "pickup_location_id": 1,
  "pickup_at": "2026-12-01 10:00",
  "return_at": "2026-12-04 10:00",
  "vehicle_model_id": 4,
  "extras": [
    {
      "id": 3,
      "quantity": 1
    }
  ],
  "website": ""
}

Responses

201 Created. data holds the token and the booking.

{
  "success": true,
  "data": {
    "token": "ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb",
    "booking": {
      "reference": "CR-2026-0128",
      "status": "pending",
      "vehicle_model_name": "Peugeot 3008",
      "pickup_location_name": "Paris Gare de Lyon",
      "return_location_name": "Paris Gare de Lyon",
      "pickup_local": "2026-12-01 10:00 CET",
      "return_local": "2026-12-04 10:00 CET",
      "days": 3,
      "hold_expires_at": "2026-11-12T09:45:00Z",
      "customer_name": "",
      "customer_email": "",
      "payment_method": "",
      "currency": "EUR",
      "line_items": [
        {
          "type": "rental",
          "label": "Peugeot 3008, 3 days",
          "quantity": 3.0,
          "unit_price": 65.0,
          "total": 195.0
        },
        {
          "type": "extra",
          "label": "Child seat",
          "quantity": 1.0,
          "unit_price": 24.0,
          "total": 24.0
        }
      ],
      "subtotal": 219.0,
      "discount_total": 0.0,
      "tax_total": 0.0,
      "total": 219.0,
      "deposit": 800.0,
      "amount_paid": 0.0,
      "payment_status": "unpaid",
      "payment_options": [
        {
          "type": "full",
          "amount": 219.0,
          "label": ""
        }
      ]
    }
  }
}
Field Type Meaning
data.token string 64 hexadecimal characters. Opens the booking in the next steps
data.booking.reference string Booking reference
data.booking.status string Booking status
data.booking.hold_expires_at string|null When the hold runs out, ISO 8601 in UTC with a Z, or null
data.booking.pickup_local string Pickup on the pickup location’s clock
data.booking.return_local string Return on the return location’s clock
data.booking.days integer Days charged
data.booking.line_items object[] Price lines: type, label, quantity, unit_price, total
data.booking.total number What the customer pays
data.booking.deposit number Held at the desk, not part of total
data.booking.amount_paid number Paid so far
data.booking.payment_status string unpaid, partially_paid, paid or refunded
data.booking.payment_options object[] What may be paid online now: type (full, balance, or part with Pro’s Pay part now app), amount, label. Empty when nothing is owed

Errors

Status Code When
422 plugixa_car_rental_unknown_location A location is missing, unpublished or in the trash. data.field names it.
422 plugixa_car_rental_location_not_allowed The pickup location takes no pickups, or the return location takes no returns.
422 plugixa_car_rental_invalid_datetime pickup_at or return_at is missing, a bare date, not a date, or a time skipped by a clock change at that location.
422 plugixa_car_rental_return_before_pickup return_at is not after pickup_at.
422 plugixa_car_rental_location_closed The location is closed on that day.
422 plugixa_car_rental_outside_hours The time is outside the location’s opening hours and it charges no after-hours fee.
422 plugixa_car_rental_too_short The rental is shorter than the shortest rental in the booking rules.
422 plugixa_car_rental_too_long The rental is longer than the longest rental in the booking rules. data.field is return_at.
422 plugixa_car_rental_too_soon The pickup is sooner than the shortest notice, or already past.
422 plugixa_car_rental_too_far The pickup is further ahead than the booking horizon.
422 plugixa_car_rental_unknown_model vehicle_model_id is missing, unpublished or not a model.
422 plugixa_car_rental_not_priced No published rate covers a rental of this length for the model.
422 plugixa_car_rental_refused A module refused this car for this request, for example a driver younger than the model allows.
422 plugixa_car_rental_driver_age_missing With Pro and the Driver age app: driver_age is missing or not 16 to 99.
409 plugixa_car_rental_sold_out No car of the model is free for those dates.
409 plugixa_car_rental_busy Another booking for the same model was being made at that moment. Try again.
400 plugixa_car_rental_rejected The hidden website field was filled in.

Plus the errors every endpoint can return.

Examples

curl -s -X POST "https://your-site.example/wp-json/plugixa-car-rental/v1/public/holds" \
  -H "Content-Type: application/json" \
  -d '{"pickup_location_id":1,"pickup_at":"2026-12-01 10:00","return_at":"2026-12-04 10:00","vehicle_model_id":4,"extras":[{"id":3,"quantity":1}],"website":""}'
<?php
$ch = curl_init('https://your-site.example/wp-json/plugixa-car-rental/v1/public/holds');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST  => 'POST',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER     => [
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS     => json_encode([
        'pickup_location_id' => 1,
        'pickup_at'          => '2026-12-01 10:00',
        'return_at'          => '2026-12-04 10:00',
        'vehicle_model_id'   => 4,
        'extras'             => [
            [
                'id'       => 3,
                'quantity' => 1,
            ],
        ],
        'website'            => '',
    ]),
]);
$response = json_decode(curl_exec($ch), true);
curl_close($ch);
const response = await fetch('https://your-site.example/wp-json/plugixa-car-rental/v1/public/holds', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    pickup_location_id: 1,
    pickup_at: '2026-12-01 10:00',
    return_at: '2026-12-04 10:00',
    vehicle_model_id: 4,
    extras: [{ id: 3, quantity: 1 }],
    website: '',
  }),
});
const { data } = await response.json();

Quick Links

Share