Carpool Services
Carpool is Cartrack's shared vehicle booking system: drivers request a pool vehicle for a scheduled time window, a manager approves or declines the request, and the vehicle's actual pickup and return are tracked against that window. This page explains the Carpool endpoints, with a focus on the booking lifecycle, the booking_status values on GET /carpool/bookings, and the rules POST /carpool/bookings applies when it creates a booking. It also explains how to enrol vehicles and drivers in Carpool and change the account's booking rules, in Setting Up Vehicles, Drivers and Booking Rules.
Which Endpoint Should I Use?
Use this mapping based on what you want to accomplish:
| Goal | Endpoint |
|---|---|
| Search or list bookings by vehicle, driver, date range, or status | Get All Carpool Bookings |
| Get full detail for a single booking | Get Carpool Booking by Booking ID |
| List vehicles enabled for carpool use, their category, and setup completeness | Get All Carpool Enabled Vehicles |
| List the vehicle categories available for booking | Get All Carpool Vehicle Categories |
| List drivers registered for carpool use and their booking eligibility | Get All Registered Carpool Drivers |
| Create a booking for a driver | Create a Carpool Booking |
| Change a booking that is waiting for approval | Update a Carpool Booking |
| Approve a booking that is waiting for approval | Approve a Carpool Booking |
| Decline a booking that is waiting for approval | Decline a Carpool Booking |
| List the booking purposes, and the vehicle categories each one allows | Get All Carpool Booking Purposes |
| List the pickup locations vehicles are based at | Get All Carpool Locations |
| Get the account's booking form and its element IDs | Get the Carpool Booking Form |
| Check whether a vehicle, or the vehicle Carpool would pick from a category, can be booked for a window | Check Carpool Vehicle Availability |
| Cancel a booking | Cancel a Carpool Booking |
| Hand the vehicle of an approved booking to its driver | Check Out a Carpool Booking |
| Record the vehicle of a booking in use as returned | Check In a Carpool Booking |
| End a booking whose vehicle is in use | Force Terminate a Carpool Booking |
| List the reasons a booking can be cancelled with | Get All Carpool Cancel Reasons |
| Add a fleet vehicle to Carpool and set it up | Enrol a Vehicle in Carpool |
| Change a vehicle's Carpool configuration, or send it to maintenance | Update a Carpool Vehicle |
| Take a vehicle out of Carpool | Remove a Vehicle from Carpool |
| Give a fleet driver Carpool access | Enrol a Driver in Carpool |
| Change a driver's department, booking permissions or licences | Update a Carpool Driver |
| Take a driver's Carpool access away | Remove Carpool Access from a Driver |
| List the booking rules the API can change, and their current setting | Get All Carpool Booking Rules |
| Switch a booking rule on or off, or set an advance booking or maximum duration limit | Update a Carpool Booking Rule |
Booking Status Values
booking_status on a booking record is not something the requester or approver sets directly for most of its values. Most transitions are computed automatically by a backend process that re-evaluates every booking every couple of minutes against the current time and the vehicle's telemetry (ignition state, geofence entry/exit). A few values are set manually by a fleet manager acting in Fleetweb, or by the main account through the API, not by that automatic process.
| Value | Meaning |
|---|---|
BOOKING_STATUS_FREE | Reserved value in the schema. No booking record returned by GET /carpool/bookings carries this status — it does not represent a state a real booking passes through. |
BOOKING_STATUS_REQUESTED | A driver has submitted a booking request. Awaiting a manager's approval or decline decision. |
BOOKING_STATUS_APPROVED | The booking is confirmed for its scheduled window — every department required to sign off has approved. This includes bookings approved automatically under a client's "Automatically approve new request" carpool setting: is_approved is true in that case too, but approved_by stays null because no manager actually took an approval action. |
BOOKING_STATUS_DECLINED | A manager declined the request. Unlike approval, decline doesn't need consensus — a single department manager declining is enough to move the whole booking to DECLINED, even if other departments haven't responded yet. |
BOOKING_STATUS_CANCELLED | The booking was cancelled — manually by the driver (only while still REQUESTED or APPROVED, not once picked up) or a manager (from any status), or automatically because the vehicle was never picked up. A REQUESTED, EXPIRING_APPROVAL, or APPROVED booking that passes its start_ts without being picked up is auto-cancelled once its client-configured grace period elapses (30 minutes after start_ts by default; some clients configure this relative to end_ts instead). |
BOOKING_STATUS_ACTIVE | The vehicle has been picked up and the booking is in progress, before its scheduled end_ts. What counts as "picked up" is configurable per client — ignition on, leaving a pickup geofence, key collection from a smart locker, or a manual check-out in Fleetweb or with Check Out a Carpool Booking. |
BOOKING_STATUS_ACTIVE_ALMOST_LATE | An early-warning state for an in-progress booking whose scheduled end_ts is approaching. Sits between ACTIVE and ACTIVE_LATE in the lifecycle — handle it as a valid value, but don't assume every booking passes through it before going late. |
BOOKING_STATUS_ACTIVE_LATE | The scheduled end_ts has passed and the vehicle has not yet been returned. |
BOOKING_STATUS_RETURNED | The vehicle was returned at or before the scheduled end_ts. |
BOOKING_STATUS_RETURNED_LATE | The vehicle was returned after the scheduled end_ts. |
BOOKING_STATUS_EXPIRING_APPROVAL | The booking is still awaiting a manager's decision (REQUESTED) and its scheduled start_ts is now less than one hour away. If no decision is made before start_ts, the booking is auto-cancelled. |
BOOKING_STATUS_FORCE_TERMINATED | A fleet manager manually ended the booking, from Fleetweb or with Force Terminate a Carpool Booking — only possible while the booking is ACTIVE, ACTIVE_ALMOST_LATE, or ACTIVE_LATE (the vehicle must currently be checked out). This is not an automatic transition; Fleetweb's own confirmation prompt frames it for cases like an accident, breakdown, or the vehicle being towed, not routine returns. |
Developer Considerations
- The
ACTIVE→ACTIVE_ALMOST_LATE→ACTIVE_LATEprogression is graduated, not guaranteed — don't treat a booking going straight fromACTIVEtoACTIVE_LATEas unexpected or an error. - Don't recompute lateness yourself by comparing
returned_attoend_ts. The API'sreturned_atprefers a site-location (geofence) timestamp over the ignition timestamp when both exist, and it can differ slightly from the timestamp actually used to decideRETURNEDvsRETURNED_LATE. Trust thebooking_statusvalue for that determination.
Setup Status: Vehicles and Drivers
Both GET /carpool/vehicles and GET /carpool/drivers return a setup_status field, but the two use different enums (SETUP_INCOMPLETE / READY for vehicles, SETUP_INCOMPLETE / ACTIVE_CARPOOL for drivers) and different completeness rules — don't assume they're interchangeable.
For vehicles, SETUP_INCOMPLETE means the vehicle is missing a department, category, default location, or license class. Which of those four are actually required is configurable per client: an account may not require all of them, so a vehicle can be READY without, for example, a department assigned, if that client hasn't turned department scoping on.
For drivers, ACTIVE_CARPOOL requires the driver to be enabled for carpool booking (can_book_carpool) and to have at least one of allow_system_auto_booking or allow_specific_vehicle_booking enabled, plus any department/license requirements the client has turned on. A driver with can_book_carpool: true but both booking methods disabled still shows as SETUP_INCOMPLETE.
To complete a vehicle's or a driver's setup through the API, see Setting Up Vehicles, Drivers and Booking Rules.
Approval Fields: is_approved, approved_by, declined_by
approved_by and declined_by are null whenever no manager has taken an approval action on the booking — including auto-approved bookings. Use is_approved and booking_status to determine the booking's approval state; use approved_by/declined_by only to find out whether a manager was the one who decided it.
A decision made by the main account through the API is not a manager's decision. After Approve a Carpool Booking both fields are null, because the main account decides for every department and replaces what managers recorded. After Decline a Carpool Booking, declined_by stays null and approved_by still names a manager who approved before the decline, so a DECLINED booking with approved_by set is valid.
Creating a Booking
Create a Carpool Booking (POST /carpool/bookings) creates a booking for a driver. It is available to the main account only; a subuser gets 403. Before anything is written, the request is checked against vehicle availability, the account's Carpool settings and the driver's other bookings, the way the Carpool booking screen in Fleetweb checks it.
Building the Request
Every booking is made for a driver, and every ID in the request comes from one of the Carpool reads:
| Field | Where it comes from | Notes |
|---|---|---|
request_driver_id | Get All Registered Carpool Drivers | Required. The driver must be active, allowed by the account's booking rules to make this kind of booking, and free in the requested window. |
vehicle_id | Get All Carpool Enabled Vehicles | Book this exact vehicle. Send either vehicle_id or category_id, not both. |
category_id | Get All Carpool Vehicle Categories | Let Carpool pick a vehicle from this category. With vehicle categories switched off and no vehicle_id, Carpool picks from the whole pool. |
booking_purpose_id | Get All Carpool Booking Purposes | The only way to set the booking's purpose. |
pickup_site_location_id | Get All Carpool Locations | The return location is derived from it and cannot be set separately. |
booking_form | Get the Carpool Booking Form | Answers to the account's booking form. See Booking Form. |
request_description | Free text | An optional note of up to 256 characters, the "Request description" field of the Carpool booking form. It is returned as booking_purpose_description and never sets or creates a booking purpose. |
vehicle_id and category_id are exclusive by value: both are nullable, so sending one of them explicitly as null alongside the other is fine.
For example, a request that lets Carpool pick a vehicle from a category. Replace {baseUrl} with your regional base URL (see Base URLs) and your_encoded_credentials with your Basic authentication value (see Authentication). The other examples on this page use the same placeholders. The Idempotency-Key is a UUID version 4 generated for this booking, and booking_form is only sent when the account has a booking form:
curl --location '{baseUrl}/rest/carpool/bookings' \
--header 'Accept: application/json' \
--header 'Content-Type: application/json' \
--header 'Authorization: Basic your_encoded_credentials' \
--header 'Idempotency-Key: 0f6d9d1e-8a52-4a1b-9c5f-3c7a1d2e4b60' \
--data '{
"request_driver_id": "bc8150fb-5b1b-4a9c-9589-c2bed5eec897",
"category_id": 43,
"booking_purpose_id": 12,
"pickup_site_location_id": 305,
"start_ts": "2026-10-12 08:00:00",
"end_ts": "2026-10-12 17:00:00",
"request_description": "Client meeting at head office",
"booking_form": [
{ "element_id": "cost_centre", "value": "CC-100" }
]
}'
Booking Window
start_tsandend_tsuse theYYYY-MM-DD HH:MM:SSformat and the same timezone as the timestampsGET /carpool/bookingsreturns.end_tsmust be later thanstart_ts.- A start up to 10 minutes in the past is accepted, so a request sent as the window opens is not refused. A start further in the past needs the account to allow back-dated booking, and then a
vehicle_id: Carpool does not pick a vehicle for a window that has already started. - The start may be no further ahead than the account's advance booking limit (for example 13 months), whether or not back-dated booking is allowed.
- The window may be no longer than the account's maximum booking duration (for example 30 days).
- A limit of zero means the account has none set.
A window outside these limits returns CARPOOL_BOOKING_WINDOW_NOT_ALLOWED.
Carpool Settings That Apply
These account settings apply to an API booking exactly as they apply on the Carpool booking screen. A vehicle is only booked when it is set up for every setting that is on, whether it was named by vehicle_id or picked from a category_id. A setting the account has never saved counts as on, as it does in Carpool's own validation.
| Setting | When it is on |
|---|---|
| Vehicle location | pickup_site_location_id is required, and at least one vehicle must be based at that location. The booked vehicle must be based there; a vehicle with no location cannot be booked. |
| Vehicle categories and booking purposes | booking_purpose_id is required. The vehicle must have a category, and the category must be one of the purpose's allowed_category_ids (an empty list allows every category). category_id is required unless a vehicle_id is sent. |
| Booking permissions by departments | The driver must belong to a department, and the vehicle must be in the driver's department or in the common pool. A driver with no department cannot book any vehicle, the common pool included. A refusal returns CARPOOL_DEPARTMENT_MISMATCH. |
| Advance booking and maximum duration | The limits described in Booking Window. |
The vehicle must also be free for the window. When the account has a cooldown between bookings, the vehicle is checked against the window padded by that cooldown, while the booking is stored with the window as requested. The driver must hold the licence the vehicle requires, and the vehicle must not be in maintenance.
Booking Form
When the account has a booking form configured in Carpool, send its answers in booking_form, one item per element, with element_id from Get the Carpool Booking Form:
"booking_form": [
{ "element_id": "cost_centre", "value": "CC-100" }
]
- Every required element must be answered, and an answer may not be longer than the element's maximum length.
- Each
element_idmay appear once. An element left out is stored as blank. - When the account has no booking form,
booking_formmust not be sent.
Returned Status and Notifications
The account's Carpool approval setting decides the status of the new booking:
| Approval setting | Returned booking_status | Notifications |
|---|---|---|
| New requests are approved automatically, including the option that excludes cross-department vehicles | BOOKING_STATUS_APPROVED | The account's configured approval notifications, by email and SMS. |
| Approved automatically, and the whole window is already in the past while the account allows back-dated booking | BOOKING_STATUS_RETURNED | Same as approved. |
| Requests must be approved manually | BOOKING_STATUS_REQUESTED | The account's configured approval request notifications, by email and SMS, to the approvers of the driver's department, the fleet managers and the driver. The booking waits for approval in Carpool. |
The response is the created booking, in the same shape as Get Carpool Booking by Booking ID. From there it follows the lifecycle in Booking Status Values.
A successful create returns 200 with the booking in data. This example is trimmed to the main fields, and its IDs and timestamps are illustrative:
{
"data": {
"booking_id": 4366,
"vehicle_id": 5017,
"request_driver_id": "bc8150fb-5b1b-4a9c-9589-c2bed5eec897",
"start_ts": "2026-10-12 08:00:00",
"end_ts": "2026-10-12 17:00:00",
"booking_status": "BOOKING_STATUS_REQUESTED",
"is_approved": false
}
}
Idempotency
Every request must carry an Idempotency-Key header: a UUID version 4 the client generates, one per booking it intends to create. A retry after a timeout or a lost response then cannot create the same booking twice. A key belongs to the calling account, is compared without regard to letter case, and is remembered for 24 hours after the booking it created.
| Within 24 hours of a successful create | Result |
|---|---|
| Same key, same body | 200 with the original booking. No second booking is created and no notification is sent again. |
| Same key, different body | 422 with CARPOOL_IDEMPOTENCY_PAYLOAD_MISMATCH. A key identifies one booking request, so a changed request needs a new key. |
| Same key while the first request is still running | 409 with CARPOOL_IDEMPOTENCY_IN_PROGRESS. Retry after a few seconds; the key is held for at most 5 minutes. |
- Only a successful create is remembered. When a request is refused or fails, the key is released at once, and the corrected request can reuse it.
- If the booking was created but could not be read back for the response, the request returns an error and the key still records the booking. Retrying with the same key and body never creates another booking: it returns that booking with
200, as it is at the time of the retry, once it can be read, and the same error until then. - After 24 hours the key is forgotten, and sending it again creates a new booking.
- Two bodies count as the same when they carry the same values, whatever the key order. An omitted optional field is the same as that field sent as
null.
Errors
A refusal carries a reason_code in error.data, so a client can act on it without parsing the message:
{
"data": null,
"error": {
"code": 409,
"message": "The driver has another booking in the requested window.",
"data": { "reason_code": "CARPOOL_DRIVER_SCHEDULE_CONFLICT" }
}
}
reason_code | HTTP | Meaning |
|---|---|---|
CARPOOL_DRIVER_SCHEDULE_CONFLICT | 409 | The driver already has a booking that overlaps the requested window. |
CARPOOL_IDEMPOTENCY_IN_PROGRESS | 409 | A request with the same Idempotency-Key is still running. Retry after a few seconds. |
CARPOOL_INVALID_IDEMPOTENCY_KEY | 422 | The Idempotency-Key header is missing or is not a UUID version 4. |
CARPOOL_IDEMPOTENCY_PAYLOAD_MISMATCH | 422 | The key was already used with a different body. Send the changed request with a new key. |
CARPOOL_BOOKING_WINDOW_NOT_ALLOWED | 422 | The window starts too far in the past or ahead, or is longer than the account allows. See Booking Window. |
CARPOOL_NO_AVAILABLE_VEHICLE | 422 | No vehicle in the requested category is free and eligible for the window. |
CARPOOL_VEHICLE_SCHEDULE_CONFLICT | 422 | The named vehicle already has a booking in the window. |
CARPOOL_VEHICLE_IN_MAINTENANCE | 422 | The named vehicle is not available for Carpool booking. |
CARPOOL_DRIVER_NOT_ELIGIBLE | 422 | The driver is not active, is not permitted to make this booking or drive this vehicle, or does not hold the licence or special licence the vehicle requires. |
CARPOOL_DEPARTMENT_MISMATCH | 422 | The account books by department, and the driver has no department or the vehicle is outside the driver's department and the common pool. |
CARPOOL_BOOKING_VALIDATION_FAILED | 422 | The request breaks another Carpool rule: for example both vehicle_id and category_id, an unknown category or location, no vehicle based at the pickup location, or a booking form answer that is missing or too long. The message names the rule. |
Without a vehicle_id, Carpool picks the vehicle, and when it can pick none the 422 names the reason, for example CARPOOL_DEPARTMENT_MISMATCH, CARPOOL_VEHICLE_IN_MAINTENANCE or CARPOOL_DRIVER_NOT_ELIGIBLE. Checking Availability gives the same reason for the same request.
A request that fails plain field validation (a missing start_ts, a malformed UUID) returns 422 with the field errors in error.data instead of a reason_code.
Integration Notes
- Generate a new
Idempotency-Keyfor each booking, store it with your request, and reuse it only to retry that same request. - Call Check Carpool Vehicle Availability first when you want to offer only vehicles that can be booked, then create the booking. See Checking Availability.
- Read the purposes, categories, locations and booking form before building a request: which fields are required depends on the account's settings, and those reads reflect them.
- A
REQUESTEDbooking is not confirmed. Poll Get Carpool Booking by Booking ID for the approval decision rather than assuming one, or decide it with Approve or Decline.
Checking Availability
Check Carpool Vehicle Availability (GET /carpool/vehicles/availability) answers, before you create a booking, whether the booking would be accepted for a vehicle and window. It runs the same checks as Creating a Booking, through the same code, so the two cannot drift apart.
Send exactly one of filter[vehicle_id] and filter[category_id], plus filter[start_ts] and filter[end_ts] in the same format and timezone as on create, and optionally filter[pickup_site_location_id]:
| Selection | filter[request_driver_id] | Result |
|---|---|---|
filter[category_id] | Required, because Carpool picks the vehicle for a driver. | The one vehicle Carpool would assign, or 422 with the reason none can be assigned. |
filter[vehicle_id] | Optional. Leave it out when the driver is not chosen yet. | The vehicle, or 422 with the reason it cannot be booked. A vehicle that is not an active Carpool vehicle of the account returns an empty list. |
A request with filter[category_id] and no filter[request_driver_id] is refused with 422. Carpool picks the vehicle for a driver, so it cannot choose one without knowing who the booking is for. Only a request with filter[vehicle_id] may leave the driver out.
For example, a request by category that carries the driver:
curl --get '{baseUrl}/rest/carpool/vehicles/availability' \
--header 'Accept: application/json' \
--header 'Authorization: Basic your_encoded_credentials' \
--data-urlencode 'filter[category_id]=43' \
--data-urlencode 'filter[request_driver_id]=bc8150fb-5b1b-4a9c-9589-c2bed5eec897' \
--data-urlencode 'filter[start_ts]=2026-10-12 08:00:00' \
--data-urlencode 'filter[end_ts]=2026-10-12 17:00:00'
The checks run in the order create runs them:
| Checks | When they run |
|---|---|
| References: the driver and the pickup location exist on the account and are not deleted. | Always, first. |
| Window: the category exists, the advance booking and maximum duration limits, back-dating, a back-dated category selection (a back-dated booking must name its vehicle), and vehicles based at the pickup location. See Booking Window. | Always, before any vehicle is checked. |
| Vehicle: the account's location, category and department settings, the vehicle's licence type, its schedule (with the account's cooldown) and its key management link. | Always. |
Driver: an overlapping booking (409 with CARPOOL_DRIVER_SCHEDULE_CONFLICT), booking permission, the right to drive the vehicle, licences and department. | When filter[request_driver_id] is sent. |
A refusal carries the same reason_code create returns for the same cause, listed in Errors. available_start_ts and available_end_ts on the result carry the window Carpool's schedule check reports for the request, or null when it reports none.
Keep in mind:
- The booking purpose and the booking form are not parameters here, so only create checks the fields the account requires, whether the purpose allows the category, and the form answers.
- The answer is true at the time of the call. Another booking can take the vehicle before yours is created, and create checks everything again.
- A subuser sees only the vehicles and drivers it sees on
GET /carpool/vehiclesandGET /carpool/drivers. Any other driver returns422withCARPOOL_DRIVER_NOT_ELIGIBLE, and any other named vehicle returns an empty list. Carpool picks a category's vehicle from the whole account, so when it picks one the subuser does not see, the answer is422withCARPOOL_NO_AVAILABLE_VEHICLE.
Updating a Booking
Update a Carpool Booking (PATCH /carpool/bookings/{booking_id}) changes a booking that is still REQUESTED. It is available to the main account only, and returns the booking as it is after the change. Any other status, EXPIRING_APPROVAL and APPROVED included, returns 409 with CARPOOL_BOOKING_STATE_CONFLICT and nothing is changed. To change an approved booking, cancel it and create a new one.
Send only the fields to change, from the fields create takes. A field left out keeps its current value, and the booking that results is checked as a whole, as Creating a Booking checks a new one: the booking window, the Carpool settings, the driver's other bookings and the booking form. The booking is left out of its own driver's and vehicle's schedule, so moving it within its current slot does not conflict with itself. A refusal returns the reason_code create returns for the same cause, listed in Errors.
| Field | On update |
|---|---|
vehicle_id | The booking moves to that vehicle, checked as a named vehicle. Cannot be null or an empty string. |
category_id | Carpool picks a vehicle from the category again, as on create. It does not pick the vehicle the booking holds now when the new window overlaps the current one. Cannot be null or an empty string. |
| Neither of the two | The booking keeps its vehicle, checked again against the new values. |
request_driver_id | Cannot be null or an empty string. The booking's requestor name is not changed with it. |
booking_purpose_id, request_description, pickup_site_location_id | Send null to clear one. The account's settings may then refuse the booking, for example when a purpose is required. |
start_ts, end_ts | Either can be sent alone, and the resulting end_ts must still be later than start_ts. Cannot be an empty string. |
booking_form | Replaces all stored answers. Left out or null, the stored answers are kept. |
The account's approval setting is applied again after every successful update:
| Approval setting | Returned booking_status | Notifications |
|---|---|---|
| New requests are approved automatically | BOOKING_STATUS_APPROVED, or BOOKING_STATUS_RETURNED when the whole window is in the past and the account allows back-dated booking | The account's approval notifications. |
| Requests must be approved manually | BOOKING_STATUS_REQUESTED. Every approval or rejection a department manager recorded is removed, and the approvers of the driver's department are asked again. | The account's approval request notifications, sent again. |
| Response | When |
|---|---|
200 | The booking was changed. |
404 | The booking does not exist on the account, or GET /carpool/bookings/{booking_id} cannot return it. Nothing is changed. |
409 with CARPOOL_BOOKING_STATE_CONFLICT | The booking is no longer REQUESTED. Nothing is changed. |
409 with CARPOOL_DRIVER_SCHEDULE_CONFLICT | The driver has another booking that overlaps the new window. Nothing is changed. |
422 | The body is invalid, or the changed booking breaks a Carpool rule. See Errors. |
Keep in mind:
- Every successful update sends the notifications above and uses SMS credits, even when a single field changed.
- The update takes no
Idempotency-Key. A retry after a lost response can apply the change and send the notifications a second time, so read Get Carpool Booking by Booking ID first to see whether the change is already there.
Approving, Declining, Checking Out and Checking In
These four actions move a booking through approval, handover and return, the way the actions on the Carpool booking screen in Fleetweb do. Each is a POST with no body, is available to the main account only, and returns the booking as it is after the change.
| Approve a Carpool Booking | Decline a Carpool Booking | |
|---|---|---|
| Endpoint | POST /carpool/bookings/{booking_id}/approve | POST /carpool/bookings/{booking_id}/decline |
| Allowed from | REQUESTED, EXPIRING_APPROVAL | REQUESTED, EXPIRING_APPROVAL |
| New status | BOOKING_STATUS_APPROVED | BOOKING_STATUS_DECLINED |
| Department managers | The main account decides for every department, so any approval or rejection a manager recorded is replaced. See Approval Fields. | Managers who have not decided are no longer asked. An approval a manager already recorded is kept. |
| Notifications | The account's approval notifications, the same ones sent when a booking is approved on creation. | None. |
For example, to approve a booking. The call takes no body:
curl --location --request POST '{baseUrl}/rest/carpool/bookings/4366/approve' \
--header 'Accept: application/json' \
--header 'Authorization: Basic your_encoded_credentials'
| Check Out a Carpool Booking | Check In a Carpool Booking | |
|---|---|---|
| Endpoint | POST /carpool/bookings/{booking_id}/check-out | POST /carpool/bookings/{booking_id}/check-in |
| Allowed from | APPROVED | ACTIVE, ACTIVE_ALMOST_LATE, ACTIVE_LATE |
| New status | BOOKING_STATUS_ACTIVE, starting now | BOOKING_STATUS_RETURNED, or BOOKING_STATUS_RETURNED_LATE when called after end_ts. The vehicle is recorded as returned now, by the booking's driver. |
| Refused when | The vehicle starts its bookings when the key is collected, and the account uses key collection. | The vehicle ends its bookings on its own, because its start and stop method is the driver checklist, a geofence, MiKey, or key collection and return. |
| Notifications | None. | None. |
The start and stop method is set per vehicle in the account's Carpool settings. A method the account has switched off does not count, so a vehicle linked only to a switched-off method is checked out and in manually. Check-out does not require a completed pre-trip checklist. A booking its method should have ended but did not can be ended with Force Terminate a Carpool Booking.
| Response | When |
|---|---|
200 | The booking was changed. |
404 | The booking does not exist on the account, or GET /carpool/bookings/{booking_id} cannot return it, for example because it has no vehicle or its vehicle no longer has an active contract. Nothing is changed. |
409 with CARPOOL_BOOKING_STATE_CONFLICT | The booking's current status does not allow the action. Nothing is changed. |
409 with CARPOOL_BOOKING_METHOD_CONFLICT | Check-out or check-in only: the vehicle's start and stop method handles this step, as described above. Nothing is changed. |
Concurrent requests and retries behave as they do for Cancelling and Force Terminating: one of two simultaneous actions on a booking wins and the other gets 409, and none of these actions takes an Idempotency-Key, so a 409 on a retry usually means the first request already went through.
Cancelling and Force Terminating
Both actions are available to the main account only, and both return the booking as it is after the change.
| Cancel a Carpool Booking | Force Terminate a Carpool Booking | |
|---|---|---|
| Endpoint | POST /carpool/bookings/{booking_id}/cancel | POST /carpool/bookings/{booking_id}/force-terminate |
| Allowed from | REQUESTED, APPROVED, EXPIRING_APPROVAL, ACTIVE, ACTIVE_ALMOST_LATE, ACTIVE_LATE | ACTIVE, ACTIVE_ALMOST_LATE, ACTIVE_LATE (the vehicle is checked out) |
| New status | BOOKING_STATUS_CANCELLED | BOOKING_STATUS_FORCE_TERMINATED, with the vehicle recorded as returned now |
| Body | booking_cancel_reason_id (required), booking_cancel_notes (optional, up to 256 characters) | None |
| Notifications | The account's configured cancellation SMS and email to the driver, as when a booking is cancelled in Fleetweb. | None. |
The cancellation reason comes from Get All Carpool Cancel Reasons, and must be an active reason of the account.
For example, to cancel a booking with a reason and a note:
curl --location '{baseUrl}/rest/carpool/bookings/4366/cancel' \
--header 'Accept: application/json' \
--header 'Content-Type: application/json' \
--header 'Authorization: Basic your_encoded_credentials' \
--data '{
"booking_cancel_reason_id": 7,
"booking_cancel_notes": "Meeting moved to next week"
}'
| Response | When |
|---|---|
200 | The booking was changed. |
404 | The booking does not exist on the account, or GET /carpool/bookings/{booking_id} cannot return it, for example because its vehicle no longer has an active contract. Nothing is changed. |
409 with CARPOOL_BOOKING_STATE_CONFLICT | The booking's current status does not allow the action. Nothing is changed. |
422 | The body is invalid, for example an unknown booking_cancel_reason_id. |
Keep in mind:
- When two requests act on the same booking at once, for example a cancel and a force terminate, one of them wins and the other gets
409. The booking is never changed twice. - Neither action takes an
Idempotency-Key. A retry after a lost response gets409, because the booking has already moved on, so read Get Carpool Booking by Booking ID to confirm the outcome instead of treating that409as a failure. - Force terminate is for a booking that has to end now, for example after an accident or a breakdown. A routine return is detected from the vehicle and ends the booking as
RETURNEDorRETURNED_LATEon its own, or is recorded with Check In a Carpool Booking.
Setting Up Vehicles, Drivers and Booking Rules
These endpoints put existing fleet vehicles and drivers into Carpool, keep their Carpool configuration up to date, and change the account's booking rules, the way the Carpool settings in Fleetweb do. Every write is available to the main account only, and a subuser gets 403. A subuser may call Get All Carpool Booking Rules.
Enrolment never creates or deletes a vehicle or a driver. The vehicle or driver must already exist in the fleet and be visible to the caller, otherwise the answer is 404. Removing one from Carpool leaves it in the fleet.
Enrolling a Vehicle
Enrol a Vehicle in Carpool (POST /carpool/vehicles) takes the vehicle's vehicle_id and, optionally, its Carpool configuration, so one call can enrol the vehicle and set it up:
| Field | Meaning |
|---|---|
vehicle_id | Required. A vehicle that is already enrolled returns 409 with CARPOOL_VEHICLE_ALREADY_ENROLLED. |
category_id | A category from Get All Carpool Vehicle Categories. |
class_id | The driving licence class needed to drive the vehicle. It is a license_type_id from license_types on Get All Registered Carpool Drivers. |
location_id | The default pickup and return location, from Get All Carpool Locations. |
common_pool | true lets any driver book the vehicle, whatever their department. |
department_ids | The departments the vehicle belongs to. |
special_license_ids | The special licence types needed to drive the vehicle. The list is shown by GET /carpool/vehicles, but it is not yet checked when a booking is created, which is how Fleetweb behaves today. |
collection_detail | Free text of up to 255 characters telling the driver where and how to collect the vehicle. |
Every configuration ID must exist on the account, otherwise the answer is 422. A field left out keeps any value the vehicle already has, for example from an earlier enrolment that was removed, or from Fleetweb. To clear one, send null for category_id, class_id, location_id or collection_detail, or an empty list for department_ids or special_license_ids. common_pool cannot be null, so send false instead. setup_status in the response tells you whether the account's Carpool settings still need something, as described in Setup Status. The response is the vehicle in the same shape as Get All Carpool Enabled Vehicles.
curl --location '{baseUrl}/rest/carpool/vehicles' \
--header 'Accept: application/json' \
--header 'Content-Type: application/json' \
--header 'Authorization: Basic your_encoded_credentials' \
--data '{
"vehicle_id": 3797104,
"category_id": 43,
"department_ids": [12],
"location_id": 77,
"common_pool": false
}'
Updating a Vehicle
Update a Carpool Vehicle (PATCH /carpool/vehicles/{vehicle_id}) takes the same configuration fields as enrolment, plus is_maintenance and force. Send at least one field other than force.
- A field left out keeps its stored value.
nullclearscategory_id,class_id,location_idorcollection_detail. An empty list clearsdepartment_idsorspecial_license_ids, and a list that is sent replaces the stored one.- A vehicle that is not enrolled returns
404. The one exception is{"is_maintenance": false}, described in Maintenance.
The response is the vehicle, plus affected_bookings, which lists what happened to each booking the change affected and is empty when none was.
Changes That Affect Bookings
Some changes can leave a vehicle's existing bookings impossible to fulfil:
- changing
location_id - setting
common_poolfromtruetofalse - setting
is_maintenancetotrue - removing the vehicle from Carpool
For these changes, an affected booking is a REQUESTED, EXPIRING_APPROVAL or APPROVED booking of the vehicle over the next two years. When the vehicle has one, the request is refused with 409 and CARPOOL_VEHICLE_HAS_FUTURE_BOOKINGS, and nothing is written. The answer counts the bookings and lists their IDs so they can be reviewed. requested_bookings includes the EXPIRING_APPROVAL bookings, and approved_bookings counts the APPROVED ones:
{
"data": null,
"error": {
"code": 409,
"message": "This will affect all 2 approved & 1 requested Carpool bookings",
"data": {
"reason_code": "CARPOOL_VEHICLE_HAS_FUTURE_BOOKINGS",
"approved_bookings": 2,
"requested_bookings": 1,
"booking_ids": [4366, 4371, 4380]
}
}
}
To go ahead, repeat the request with force set to true: in the body of the PATCH, or as the query parameter ?force=true of the DELETE. The change is saved and every affected booking is handled in the same request, the way Fleetweb handles it:
| Change | What happens to each affected booking |
|---|---|
location_id, common_pool, or removal | It moves to another vehicle Carpool can assign it to, or is cancelled when there is none. |
is_maintenance: true | It is cancelled, and not moved. |
A driver whose booking is cancelled is notified under the account's notification settings. A booking that moves to another vehicle sends no notification, as in Fleetweb.
curl --location --request PATCH '{baseUrl}/rest/carpool/vehicles/3797104' \
--header 'Accept: application/json' \
--header 'Content-Type: application/json' \
--header 'Authorization: Basic your_encoded_credentials' \
--data '{
"location_id": 78,
"force": true
}'
Each entry in affected_bookings reports one booking's outcome:
"affected_bookings": [
{ "booking_id": 4366, "outcome": "REASSIGNED", "new_vehicle_id": 3797110 },
{ "booking_id": 4371, "outcome": "CANCELLED", "new_vehicle_id": null }
]
Keep in mind:
forceaccepts onlytrueandfalse. Any other value returns422, andfalseis never read astrue.force: trueis harmless on a change that affects no booking.affected_bookingsis then empty.- The forced request handles the affected bookings as they are when it runs, which can differ from the list in an earlier
409.
Maintenance
is_maintenance: true sends the vehicle to maintenance. It also switches the vehicle's Carpool enrolment off, cancels its open maintenance records (pending, in maintenance and under inspection) and opens an immediate one with no end date. Completed records are kept as they are. The vehicle then no longer appears in GET /carpool/vehicles, so the vehicle part of the response carries only its vehicle_id, registration and setup_status NON_CARPOOL, followed by affected_bookings. That list is the only place that shows which bookings the change cancelled.
is_maintenance: false cancels the vehicle's open maintenance records. It does not enrol the vehicle again, so call Enrol a Vehicle in Carpool once the vehicle is ready. It is the only change accepted for a vehicle that is not enrolled.
Removing a Vehicle
Remove a Vehicle from Carpool (DELETE /carpool/vehicles/{vehicle_id}) switches the vehicle's Carpool enrolment off. The vehicle stays in the fleet. A vehicle with affected bookings needs ?force=true, as described in Changes That Affect Bookings.
curl --location --request DELETE '{baseUrl}/rest/carpool/vehicles/3797104?force=true' \
--header 'Accept: application/json' \
--header 'Authorization: Basic your_encoded_credentials'
The response carries the vehicle ID and the outcome of each affected booking in data, and a message in meta that counts how many were reassigned and how many were cancelled:
{
"data": {
"vehicle_id": 3797104,
"affected_bookings": [
{ "booking_id": 4366, "outcome": "REASSIGNED", "new_vehicle_id": 3797110 }
]
},
"meta": {
"message": "Removed the vehicle from Carpool. Affected bookings: 1, reassigned to another vehicle: 1, cancelled: 0."
}
}
Enrolling and Updating a Driver
Enrol a Driver in Carpool (POST /carpool/drivers) gives an active fleet driver Carpool access. It takes the driver_id, an optional department_id, and three booking flags, all required, at least one of which must be true. A driver that is already enrolled returns 409 with CARPOOL_DRIVER_ALREADY_ENROLLED. The driver record itself is not changed.
Each flag belongs to an account setting in the Carpool booking settings in Fleetweb:
| Flag | Carpool setting | Lets the driver |
|---|---|---|
can_book_carpool | Drivers can book carpool | Book Carpool vehicles at all. |
allow_system_auto_booking | Drivers can auto booking | Have Carpool pick a vehicle for the booking. |
allow_specific_vehicle_booking | Drivers can book specific vehicles | Book a named vehicle. |
A flag only takes effect while its setting is on for the account. Setting a flag to true therefore switches that setting on for the account if it was off, the same as in Fleetweb. These three settings are not listed or changed by the booking rules endpoints, so the API cannot switch one back off. If the account had turned one off on purpose, switch it off again in Fleetweb.
curl --location '{baseUrl}/rest/carpool/drivers' \
--header 'Accept: application/json' \
--header 'Content-Type: application/json' \
--header 'Authorization: Basic your_encoded_credentials' \
--data '{
"driver_id": "bc8150fb-5b1b-4a9c-9589-c2bed5eec897",
"department_id": 12,
"can_book_carpool": true,
"allow_system_auto_booking": true,
"allow_specific_vehicle_booking": false
}'
Update a Carpool Driver (PATCH /carpool/drivers/{driver_id}) changes an enrolled driver's department_id, booking flags, and licences. Licences are only set here, not on enrolment. Send at least one field, and a field left out keeps its stored value.
license_type_ids(the licence classes the driver holds) andspecial_licensesreplace the stored lists as a whole, so send the complete list the driver should hold.- Setting a flag to
falseleaves the account's setting as it is, and does not touch the driver's bookings. - The three flags cannot all become
false, because that would remove the driver. The answer is422withCARPOOL_DRIVER_USE_DELETE_TO_REMOVE. Use Remove Carpool Access from a Driver instead. - A driver who is deactivated in the fleet returns
404and nothing is written, becauseGET /carpool/driversdoes not list it.
Both calls return the driver in the same shape as Get All Registered Carpool Drivers.
Removing a Driver
Remove Carpool Access from a Driver (DELETE /carpool/drivers/{driver_id}) clears the driver's three booking flags. The driver record in the fleet is not touched, and a deactivated driver can still be removed.
When the driver is the requesting driver of a REQUESTED, EXPIRING_APPROVAL or APPROVED booking over the next two years, the request is refused with 409 and CARPOOL_DRIVER_HAS_FUTURE_BOOKINGS, carrying the same counts and booking IDs as for a vehicle. With ?force=true the access is removed and the bookings are left as they are. Unlike a vehicle removal, nothing is moved or cancelled, because Fleetweb has no booking handling for a driver. Review those bookings and cancel any that should not go ahead with Cancel a Carpool Booking.
The response carries the driver_id in data, and a message in meta that counts the affected bookings left unchanged.
Booking Rules
Get All Carpool Booking Rules (GET /carpool/rules) lists the account's booking rules that the API can change, each combining the rule's default with the account's own setting. The list is small and not paginated.
| Field | Meaning |
|---|---|
booking_rule_id | The rule's ID, used in the path of the update. |
booking_rule_key | A readable name for the rule, for example BOOKING_RULE_ADVANCE_BOOKING. It is informational and is not accepted in the path. |
booking_rule_name | The rule's name as Carpool shows it. |
is_enabled | Whether the rule is on for the account. |
value | The setting, read according to value_type. |
value_type | BOOL for a switch, or the unit of a duration rule. |
The list covers the settings Fleetweb changes one at a time: booking permissions, vehicle management, start and stop methods, active booking extension, the notifications, and the advance booking and maximum duration limits. Settings Fleetweb changes together, such as the approval settings and the three driver settings in Enrolling and Updating a Driver, are not listed and are changed in Fleetweb.
Update a Carpool Booking Rule (PATCH /carpool/rules/{booking_rule_id}) changes one listed rule. Any other booking_rule_id returns 404, like an ID that does not exist. The rule's value_type decides which body to send, and the two bodies cannot be mixed:
value_type | Rules | Send | In the answer |
|---|---|---|---|
BOOL | The switches | is_enabled only, as the JSON true or false | value repeats is_enabled as the text "true" or "false". |
A unit, such as MONTHS | 101 advance booking and 102 maximum duration | value, unit or both | is_enabled is true while value is at least 1. |
For example, to switch a notification rule on:
curl --location --request PATCH '{baseUrl}/rest/carpool/rules/105' \
--header 'Accept: application/json' \
--header 'Content-Type: application/json' \
--header 'Authorization: Basic your_encoded_credentials' \
--data '{ "is_enabled": true }'
A duration rule cannot be switched off, as on the Carpool settings screen. Its value is a whole number of at least 1, sent as text without a leading zero, and must not be larger than the largest value of its unit:
unit | Largest value |
|---|---|
MINUTES | 50000 |
HOURS | 2000 |
DAYS | 365 |
WEEKS | 52 |
MONTHS | 60 |
The check uses the value and unit that result from the request, the ones sent or else the stored ones. Sending only unit therefore checks the stored value against the new unit, so send value together with unit when moving to a smaller unit. For example, to allow bookings up to 3 weeks ahead:
curl --location --request PATCH '{baseUrl}/rest/carpool/rules/101' \
--header 'Accept: application/json' \
--header 'Content-Type: application/json' \
--header 'Authorization: Basic your_encoded_credentials' \
--data '{ "unit": "WEEKS", "value": "3" }'
The answer is the rule as it is now. A rule change is not applied to existing bookings: relaxing a rule does not approve a booking that was refused, and tightening one does not invalidate a booking that was already accepted. It applies to bookings made after it.
Setup Errors
The setup endpoints return these reason_code values in error.data, in the same error shape as Errors:
reason_code | HTTP | Meaning |
|---|---|---|
CARPOOL_VEHICLE_ALREADY_ENROLLED | 409 | The vehicle is already enrolled. Use Update a Carpool Vehicle to change it. |
CARPOOL_DRIVER_ALREADY_ENROLLED | 409 | The driver is already enrolled. Use Update a Carpool Driver to change it. |
CARPOOL_VEHICLE_HAS_FUTURE_BOOKINGS | 409 | The vehicle change affects bookings and force was not true. Nothing was written. See Changes That Affect Bookings. |
CARPOOL_DRIVER_HAS_FUTURE_BOOKINGS | 409 | The driver is the requesting driver of affected bookings and force was not true. Nothing was written. See Removing a Driver. |
CARPOOL_DRIVER_USE_DELETE_TO_REMOVE | 422 | The update would set all three booking flags to false. Remove the driver instead. |
CARPOOL_RULE_VALUE_NOT_ALLOWED | 422 | The body does not fit the rule: is_enabled for a duration rule, value for a switch, unit for a rule other than 101 and 102, or a value outside the range of its unit. |
A request that fails plain field validation returns 422 with the field errors in error.data instead of a reason_code. That covers an unknown field, a null or blank value where one is not allowed (only collection_detail may be blank), an ID that does not exist on the account, and a force that is not true or false.