The late fee endpoints of the Rentals & Bookings REST API v1. When late fees are on (Settings › Late fees, see Late fees), a late check-in creates a late fee for the order. Staff review it, then it is collected by a payment link on the order, at the counter, or from a held refundable deposit. These endpoints do the same as the Late fees page in the app. The rest of the core REST API is in REST API reference: bookings and availability and REST API reference: warehouse, stock and settings. Keys, limits, pagination and the error format are in the API overview. The same operations are in GraphQL: GraphQL API reference: Late fees.
Every endpoint on this page needs the Rentals & Bookings app. GET needs a read key; everything else needs a key with Allow changes (write). A read key gets 403 rentals_rest_forbidden on a change. The Free plan’s API can read only: a change answers 403 rentals_rest_plan_required with data.plan: "free" and data.required_plan: "regular". The examples use two shell variables:
API="https://YOUR-API-ADDRESS/api/v1" # the REST address from Settings › API
KEY="sirb_your_secret_key"
Ids in the examples are made up: late fee 12, order 5550001 (#1042), bookings 42 and 43.
The late fee #
One late fee per order, numbered LF-<order number>-<n>. A later late return on the same order adds lines while the fee is accruing or to_review.
| Field | Notes |
|---|---|
id, number | The fee’s id and its number, LF-1042-1. |
order_id, order_name, customer_id | The Shopify order and customer (numbers). |
status | Where the fee stands (below). |
amount, currency | Before the fee is accepted: the amount in the store currency, before tax. Once it is on the order: what the order owes for it, in the order’s currency, tax included. |
amount_shop, shop_currency | The amount in the store currency, before tax, at every stage. |
calculated | What the calculation gave, before any change by staff. |
adjusted | Staff changed an amount or added a line. |
tax | The tax on the fee, once known. |
so_far, per_day | Only while stock is still out: the fee so far, and what each further day adds. |
long_overdue | The rental is long overdue. |
due_back, returned_at | The earliest due moment and the latest check-in, Y-m-d H:i in the store’s time zone. |
location_id | The Shopify location of the check-in. |
route | Once accepted: link, counter or deposit. |
method | Once on Shopify: edit (on the order) or invoice (a separate invoice). |
paid_via, paid_amount, paid_at | Once paid: link, counter, shopify or deposit; the amount; when (ISO 8601). |
counter_method | For a counter payment: cash, terminal, bank or other. |
refunded | The amount refunded so far. |
note_customer | The note shown to the customer in the emails. |
reason_staff, waive_reason | Staff’s reason for a change, and the reason it was waived. |
last_error | Why charging failed (status failed). |
reviewed_at, created_at | ISO 8601. |
lines | The lines (below). |
booking_ids | The bookings the fee is for. |
payment_url | Only in GET /late-fees/{id}, and only for a write key: the payment link (Shopify’s page for the order, or the invoice). Anyone with it can pay: keep it private. |
Amounts are decimal strings ("25.00").
status | Meaning |
|---|---|
accruing | Stock is still out: the fee grows each day. |
to_review | Waiting for staff to accept, change or waive it. |
charging | Being charged (from the deposit, or added to the order). |
pay_link_sent | On the order; the customer has the payment link. |
paid | Paid. |
failed | Charging failed: last_error says why. |
needs_confirmation | Shopify’s answer was unclear: check the order. |
waived | Waived by staff. |
cancelled | Nothing was late after all (a corrected return time), or the order was cancelled. |
refunded, part_refunded | Refunded in full or in part. |
A line is one late rental item, the fixed late return fee, or a line staff added:
| Field | Notes |
|---|---|
key | Stable key: change a line’s amount with it (flat is the fixed late return fee, x1, x2… the lines staff added). |
title, quantity | What the line is for. |
amount, calculated | The amount (store currency, before tax) and what the calculation gave. |
edited | Staff changed the amount. |
extra | A line staff added (cleaning, a lost part). |
accruing | The item is still out. |
booking_id, due_back, returned_at, late_minutes | The booking, when it was due, when it came back (null while out) and how late it was. |
Bookings carry their late fee too: late_fee on a booking (see Bookings) is {id, number, status, amount, currency, so_far, per_day, long_overdue} or null.
Endpoints #
GET /api/v1/late-fees #
Late fees, newest first. Paged with page and per_page; the totals are in the X-Total and X-Total-Pages headers.
| Parameter | Notes |
|---|---|
status | all (default), to_review (to review and failed), unpaid (payment link sent, needs confirmation, charging), accruing (largest first), paid (paid, refunded, part refunded; last paid first) or waived (last waived first). |
order_id | Only this order’s fees. |
search | A fee number, order name, customer name or email. |
curl -s "$API/late-fees?status=to_review" -H "Authorization: Bearer $KEY"
# 200, X-Total: 1
[{"id": 12, "number": "LF-1042-1", "order_id": 5550001, "order_name": "#1042", "customer_id": 7001234,
"status": "to_review", "amount": "36.00", "currency": "USD", "amount_shop": "36.00", "shop_currency": "USD",
"calculated": "36.00", "adjusted": false, "tax": null, "so_far": null, "per_day": null, "long_overdue": false,
"due_back": "2026-11-18 17:00", "returned_at": "2026-11-20 10:15", "location_id": 801,
"route": null, "method": null, "paid_via": null, "paid_amount": null, "counter_method": null, "paid_at": null,
"refunded": null, "note_customer": null, "reason_staff": null, "waive_reason": null, "last_error": null,
"reviewed_at": null, "created_at": "2026-11-20T15:15:02+00:00",
"lines": [{"key": "b42-m9101", "title": "Touring kayak", "quantity": 1, "amount": "36.00", "calculated": "36.00",
"edited": false, "extra": false, "accruing": false, "booking_id": 42,
"due_back": "2026-11-18 17:00", "returned_at": "2026-11-20 10:15", "late_minutes": 2475}],
"booking_ids": [42]}]
GET /api/v1/late-fees/{id} #
One late fee. With a write key it also has payment_url. An unknown id is 404 rentals_rest_not_found.
curl -s "$API/late-fees/12" -H "Authorization: Bearer $KEY"
PUT or PATCH /api/v1/late-fees/{id} #
Change a fee that is waiting for review (to_review). Only the fields you send change. Answers the fee.
| Field | Notes |
|---|---|
lines | New amounts by line key: {"b42-m9101": "30.00"}. An item still out can’t be changed. |
extra | The lines staff added, as [{"title": "Cleaning", "amount": "15.00"}], up to 10. It replaces the extra lines; [] removes them. |
note_customer | The note to the customer in the emails. |
reason_staff | Why it was changed (for staff). |
curl -s -X PATCH "$API/late-fees/12" -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
-d '{"lines": {"b42-m9101": "30.00"}, "extra": [{"title": "Cleaning", "amount": "15.00"}], "reason_staff": "One day forgiven, mud inside"}'
409 rentals_rest_not_reviewable when the fee isn’t waiting for review any more; 400 rentals_rest_invalid_param with data.field for an amount below 0, a line without a title or more than 10 extra lines.
POST /api/v1/late-fees/{id}/accept #
Accept a fee waiting for review: it is collected the way route says. Answers the fee.
| Field | Notes |
|---|---|
route | auto (default): the store’s first way to collect that can work, as set in Settings › Late fees. link: on the order, and the customer gets the payment link. counter: paid at the counter. deposit: kept from the order’s refundable deposit (Refundable Security Deposits app); the rest of that deposit is refunded. |
method | For counter: cash (default), terminal, bank or other. |
to | For link: send the payment link to this email address instead of the customer’s. |
curl -s -X POST "$API/late-fees/12/accept" -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" -d '{"route": "link"}'
409 rentals_rest_not_reviewable when it isn’t waiting for review; 400 rentals_rest_no_lines when there is nothing to charge; 400 rentals_rest_no_deposit when no refundable deposit on the order covers the whole fee; 400 rentals_rest_deposit_failed when Shopify refused the deposit refund (the fee stays to review); 400 rentals_rest_no_order when the booking has no Shopify order to add the fee to. Accepting a fee a second time answers it as it is.
POST /api/v1/late-fees/{id}/waive #
Waive the fee. The customer gets no email; lines already on the order are taken off.
| Field | Notes |
|---|---|
reason | Required: why it is waived. |
curl -s -X POST "$API/late-fees/12/waive" -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" -d '{"reason": "Storm closed the road"}'
400 rentals_rest_reason_required without a reason; 409 rentals_rest_paid for a paid fee (it can only be refunded); 409 rentals_rest_not_waivable when it can no longer be waived.
POST /api/v1/late-fees/{id}/send-link #
Email the payment link again, to the customer or to to.
| Field | Notes |
|---|---|
to | Optional: an email address. |
409 rentals_rest_not_unpaid when the fee isn’t waiting for payment; 404 rentals_rest_no_link when there is no payment link yet.
POST /api/v1/late-fees/{id}/counter-payment #
Record a payment taken at the counter. A fee waiting for review is accepted at the counter (it goes on the order and is marked paid); a fee waiting for its payment link is marked paid.
| Field | Notes |
|---|---|
method | cash (default), terminal, bank or other. |
curl -s -X POST "$API/late-fees/12/counter-payment" -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" -d '{"method": "terminal"}'
409 rentals_rest_outstanding_differs (with data.outstanding) when the order owes more than the fee: record the payment on the order in Shopify instead. 502 rentals_rest_shopify_error when Shopify can’t be reached.
Errors #
Errors have the shape described in the API overview. The codes these endpoints add:
| Status | Code | When |
|---|---|---|
| 404 | rentals_rest_not_found | No late fee with that id. |
| 409 | rentals_rest_not_reviewable | The fee isn’t waiting for review any more. |
| 409 | rentals_rest_busy | Someone is working on this fee right now: try again in a moment. |
| 409 | rentals_rest_paid | The fee is paid: it can only be refunded. |
| 409 | rentals_rest_not_waivable | The fee can no longer be waived. |
| 409 | rentals_rest_not_unpaid | Only an unpaid fee can be sent a link or marked paid. |
| 409 | rentals_rest_outstanding_differs | The order owes more than the fee (data.outstanding). |
| 400 | rentals_rest_no_lines | There is nothing to charge. |
| 400 | rentals_rest_no_deposit | No refundable deposit on the order covers the whole fee. |
| 400 | rentals_rest_deposit_failed | The fee couldn’t be taken from the deposit. |
| 400 | rentals_rest_no_order | The booking has no Shopify order to add the fee to. |
| 400 | rentals_rest_reason_required | Waiving needs a reason. |
| 400 | rentals_rest_invalid_param | A value is wrong: data.field or data.params names it. |
| 404 | rentals_rest_no_link | There is no payment link yet. |
| 502 | rentals_rest_shopify_error | Shopify couldn’t be reached. |
