Use this when a customer books more than one thing at once from your own website: a kayak and a paddleboard for the same morning, two boats, a rental plus a tour. Everything in the cart is booked together, paid with one card charge, and grouped as one order that you and your customer can see together.
If you call POST /coreBooking/book once per item instead, you get separate, unlinked bookings: separate confirmations, separate Next Steps pages, and two lines on your Bookings page that nothing ties together. Use the cart call below for any checkout with two or more items.
The flow
- Price each item with
POST /pricing/calculate. - Collect the card with Stripe.js and create a PaymentMethod.
- Book the cart with
POST /bundle-booking/book, sending every item and the PaymentMethod. RentalTide charges the card once and creates the bookings. - Send the customer to Next Steps, which shows the whole order.
- Optionally, read the order back with
GET /public/order/{orderId}.
All of these are public endpoints: no API key or sign-in. Calls go to https://v3.api.rentaltide.com. You need your customerId (your RentalTide account id), the locationId, and each listing's inventoryId and asset type ids. If your site already books through POST /coreBooking/book, it has all of these; otherwise ask us for them.
1. Price each item
POST /pricing/calculate
Price each line of the cart on its own, exactly as the customer picked it.
| Field | Type | Required | Description |
|---|---|---|---|
pricingModel | string | Yes | hourly, daily, guestCountTiered, category or tour |
customerId | string | Yes | Your account id |
locationId | string | Yes | The location |
inventoryId | string | Yes (not tours) | The listing |
startDate | string | Yes | YYYY-MM-DD |
startTime | string | Hourly | HH:mm, location time |
duration | number | Hourly | Hours |
endDate | string | Daily | YYYY-MM-DD |
assetTypeId | string | No | The asset type picked inside the listing (kayak, paddleboard, ...) |
quantity | number | No | Units, default 1 |
promoCode | string | No | A promo code the customer entered |
The response is { breakdown, calculationMatrix }. You will copy these into the cart in step 3:
breakdown.subtotal,breakdown.totalPrice,breakdown.taxbreakdown.depositPercentage,breakdown.depositDueNow,breakdown.remainingBalancecalculationMatrix, unchanged
Show the customer breakdown.totalPrice per item and breakdown.depositDueNow as what they pay today. Send the quote's numbers as they came back: the server checks the amounts again when you book and can refuse a cart that does not match what your location charges.
2. Collect the card
Create a card PaymentMethod in the browser with Stripe.js, using RentalTide's Stripe publishable key (ask us for it: it is the same for every RentalTide merchant). Do not pass a stripeAccount, and do not create or confirm a PaymentIntent yourself: RentalTide does that in the next step.
3. Book the cart
POST /bundle-booking/book
Request body
| Field | Type | Required | Description |
|---|---|---|---|
customerId | string | Yes | Your account id |
locationId | string | Yes | The location every item is booked at |
customerInfo | object | Yes | firstName, lastName, email, phoneNumber (E.164, e.g. +14155550123) |
items | array | Yes | One entry per line of the cart, at least one |
paymentMethodId | string | Yes | The Stripe PaymentMethod from step 2 |
paymentType | string | No | full charges each item's full total. Anything else charges each deposit |
promoCode | string | No | A promo code applied to the order |
emailRenter | bool | No | Send the customer their confirmation email |
textRenter | bool | No | Send the customer their confirmation text |
customerInfo.email is how RentalTide recognises a returning customer, so use the address they typed. Add customerInfo.dateOfBirth if your location asks for a date of birth at checkout.
Each item
| Field | Type | Required | Description |
|---|---|---|---|
inventoryId | string | Yes | The listing |
checkoutData | object | Yes | The item's details, shown below |
checkoutData
| Field | Type | Required | Description |
|---|---|---|---|
rentalDetails | object | Yes | What was booked, shown below |
rentalPricing | object | Yes | The price, shown below |
depositInformation | object | Yes | depositPercentage, depositDueNow and remainingBalance from the quote |
taxBreakdown | array | Yes | One { name, rate, amount } per tax in the quote's breakdown.tax |
checkoutData.rentalDetails
| Field | Type | Required | Description |
|---|---|---|---|
inventoryId | string | Yes | The same listing as the item |
assetTypeId | string | No | The asset type, as priced |
quantity | number | Yes | Units, as priced |
startDate | string | Yes | YYYY-MM-DD HH:mm, location time |
endDate | string | Yes | YYYY-MM-DD HH:mm, location time |
isHourlyRental | bool | Yes | true for an hourly rental |
hoursBooked | number | Hourly | Hours |
daysBooked | number | Daily | Days |
checkoutData.rentalPricing
| Field | Type | Required | Description |
|---|---|---|---|
subtotal | number | Yes | The quote's breakdown.subtotal |
totalPrice | number | Yes | The quote's breakdown.totalPrice |
tax | array | Yes | The quote's breakdown.tax |
currency | string | Yes | Your location's currency, e.g. USD |
pricingCalculation | object | Yes | The quote's calculationMatrix, unchanged |
Example: a kayak and a paddleboard, same morning
The amounts above are illustrative. Always send the numbers your own quote returned.
What happens
- RentalTide checks every item is still available, assigns the units, and charges the card once for what is due today across the whole cart.
- Items your location approves by hand are not charged yet: the card is held for them and charged when you approve the booking.
- If anything fails after the charge, the charge is refunded and nothing is booked. A cart is booked whole or not at all.
Response 201
bundleGroupIdlinks the items booked together. Items on different days are split into one group per day, each ingroups.bookingIdis the order id when your location has booking groups switched on, otherwisenull. Either id works as theorderIdbelow.bookingshas one entry per booking created, each with its ownnextStepsToken. With booking groups on, an item with a quantity above 1 is split into one booking per unit.
Errors
| Status | Meaning |
|---|---|
400 | Something in the request is missing or wrong. The body has error, usually a code, and itemIndex when one item is the problem |
402 | The card was declined: error, code, decline_code. Ask for another card |
403 | The booking is not allowed (for example the location is paused or the item is members only) |
404 | The location was not found |
409 | An item is no longer available, or is past its booking cutoff (itemIndex, inventoryId). Ask the customer to pick another time |
409 with duplicate: true | The same checkout is still being processed. Wait a few seconds and send it again |
409 with code: PAYMENT_OUTCOME_UNKNOWN | We could not confirm the charge. Send the identical request again to recover it. Never change the cart and retry |
500 | The checkout failed. Any charge was refunded |
Sending the identical request twice within a few minutes (a double click, a retry after a timeout) books it once: the second request gets the first one's answer back, or a 409 while the first is still running.
3-D Secure is not supported on this call yet: a card that needs it is declined with a 402.
4. Send the customer to Next Steps
After a 201, send the customer to:
The page opens the whole order: waivers, balance, directions and messages for every item. The same link is in their confirmation email. If the cart spans several days (more than one entry in groups), use a booking from each group.
5. Read the order back
GET /public/order/{orderId}?t={nextStepsToken}
| Name | In | Type | Required | Description |
|---|---|---|---|---|
orderId | path | string | Yes | The bookingId, bundleGroupId, or any one rentalId in the order |
t | query | string | Yes | The nextStepsToken of a booking in the order |
Returns the order with all its line items: orderId, orderType (bookingId, bundleGroupId or single), and lineItems, one per booking. Always send t: treat the token like a password, because it is what proves you may read the customer's details. An unknown order and a wrong token both answer 404.
To list just the bookings in a group (names, times, totals, status), use GET /bundle-booking/public/group/{bundleGroupId}.
Things to know
- Price, then book, with the same choices. Each item in step 3 must match what you priced in step 1: same listing, asset type, quantity and times.
- One location per cart. Book items at different locations as separate carts.
- Deposits. With a deposit, each booking keeps its remaining balance owing, shown to the customer on Next Steps.
- Test first. A sandbox location takes Stripe test cards (with RentalTide's test publishable key) and books nothing real. Ask us to set one up.
Questions about an integration: support@rentaltide.com.

