Charge for Missing Parts
When a product tracks its contents and parts come back unticked at return, the unticked parts that carry a replacement cost are "missing". This endpoint sums those costs and adds them to the booking's bill as a single itemised custom charge โ raising the booking's total and amount due โ so the missing parts are then collected through the normal payment flow (terminal, card, cash, bank transfer, or a payment link), exactly like the rest of the booking.
There is one amount due: whatever settles it (a payment link or an in-store payment) settles it once. The endpoint never charges the customer automatically โ it only adds the line to the bill; you take payment with the existing Add Payment endpoint.
POST /api/v1/mobile/bookings/{id}/missing-parts-charge
Authenticationโ
Mobile-authenticated endpoint. The user's role must include both the bookings.fulfillment and bookings.payments permissions. The booking must belong to the requesting supplier.
Path Parametersโ
| Parameter | Type | Description |
|---|---|---|
id | integer | Booking ID |
Request Bodyโ
| Field | Type | Default | Description |
|---|---|---|---|
send | boolean | true | false returns a preview (the itemised summary only, nothing written). true adds the missing-parts line to the booking's bill. |
What counts as "missing"โ
A return-checklist part is included only when all of these hold:
- It was not ticked back in at return (
is_completed = false). - It carries a replacement cost (unpriced parts are tracked but never billed).
- If the product's contents were checked at pickup, the part was ticked out then โ a part never handed over can't be missing.
Responseโ
200 OK. summary is always returned; custom_charge is the line that was added (or null in preview mode).
{
"data": {
"summary": {
"lines": [
{
"line_id": 64,
"product_name": "4-Person Tent",
"items": [
{ "label": "Footprint", "quantity": 1, "unit_cents": 4000, "line_cents": 4000 },
{ "label": "Stakes", "quantity": 8, "unit_cents": 200, "line_cents": 1600 }
],
"total_cents": 5600
}
],
"total_cents": 5600
},
"custom_charge": {
"id": 812,
"description": "Missing parts: Footprint, Stakes ร8",
"amount": 56.00
}
},
"meta": { "request_id": "...", "timestamp": "..." }
}
| Field | Type | Description |
|---|---|---|
summary.lines[] | array | One entry per booking line that has missing priced parts. |
summary.lines[].items[] | array | label, quantity, unit_cents, line_cents (unit_cents ร quantity). |
summary.parts_cents | integer | What the missing parts cost across the booking, in cents. |
summary.deposit_cents | integer | How much of that a deposit kept at return already paid. |
summary.total_cents | integer | What is left to charge: parts_cents less deposit_cents, in cents. |
custom_charge | object|null | The bill line that was added. null in preview mode (send: false) and when nothing new was added (see Idempotency). |
custom_charge.amount | number | Charge amount in the booking's currency (dollars). |
After a successful call the amount appears as a Missing parts line in the booking's custom charges, and the booking's total / amount due rise by summary.total_cents / 100. The charge is added untaxed (it's a replacement-cost recovery, not a sale).
Idempotencyโ
A return never marks the missing parts as returned, so they stay "missing". To prevent double-billing, the endpoint adds at most one missing-parts charge per booking: if a Missing parts: custom charge already exists, the call is a safe no-op โ it returns 200 with the current summary but custom_charge: null. Check custom_charge !== null to know whether a new line was written.
Errorsโ
| Status | Code | When |
|---|---|---|
403 | forbidden | The booking belongs to another supplier, or the user lacks bookings.payments. |
404 | not_found | No booking with that id. |
422 | nothing_to_charge | No priced parts are missing, or a deposit kept at return already paid for them (the message says which). |
Notesโ
- This replaces the earlier behaviour where the endpoint emailed a standalone payment link. The charge now folds into the booking's bill, so it's collected the same way as everything else and there is never a separate balance to reconcile.
- To preview the total before committing, call with
{ "send": false }first. - When a return keeps part of the deposit (
deposit: keep), that money pays for the missing parts first. Only the rest is charged, and the line's description names what the deposit paid.