View Categories

Late Fees

5 min read

A rental that comes back after its due time can get a late fee. Staff review it, then collect it from the security deposit, the card saved at checkout or a payment link, or record it paid at the counter. This page covers the GraphQL fields for late fees: the back-office list and actions, a reservation’s late fee so far, and the customer’s own late fees with a pay link.

How late fees work, their settings and the admin screens are described in Late Fees.

Late fees are off until the store turns them on under Stores > Configuration > Sales Igniter > Rental > Late fees (website scope). While they are off no late fee is created, and the lists below are empty. Everything here is GraphQL; there is no other API for it.

Two halves #

HalfFieldsWho can call it
Storefront (customer)customerRentalLateFees
CustomerOrder.rental_late_fees
The customer token of the customer who placed the booking.
Back officerentalLateFees, rentalLateFee
RentalReservation.late_fee
acceptRentalLateFee, updateRentalLateFee, waiveRentalLateFee
sendRentalLateFeeLink, recordRentalLateFeeCounterPayment, refundRentalLateFee
An admin or integration token holding the ACL resources in the table below.

Permissions #

FieldACL resourceWhere that is in the admin role tree
rentalLateFees, rentalLateFee, late_fee on a reservationSalesIgniter_Rental::late_feeRental > Late fees: view
acceptRentalLateFee, updateRentalLateFee, waiveRentalLateFee, sendRentalLateFeeLink, recordRentalLateFeeCounterPayment, refundRentalLateFeeSalesIgniter_Rental::late_fee_manageRental > Late fees: accept, edit, waive, record payment

A token without the right resource gets a graphql-authorization error. RentalReservation.late_fee is the one exception: it returns null instead of an error, so an existing rentalReservations query keeps working for a role that cannot see late fees. A customer token never reaches the back-office fields.

Listing late fees #

rentalLateFees lists late fees newest first, like Rentals > Late Fees. Every filter is optional; queue is the screen’s tab. Dates are UTC days. rentalLateFee(number: "LF-000000042-1") returns one fee with the same fields.

query LateFeesToReview {
  rentalLateFees(filter: { queue: TO_REVIEW, created_from: "2026-10-01" }, pageSize: 20, currentPage: 1) {
    total_count
    items {
      number
      order_number
      customer_email
      status
      currency
      amount
      calculated_amount
      adjusted
      late_minutes
      due_back
      returned_at
      lines { key kind label amount calculated_amount edited late_minutes units unit }
    }
    page_info { current_page total_pages }
  }
}
{
  "data": {
    "rentalLateFees": {
      "total_count": 1,
      "items": [{
        "number": "LF-000000042-1",
        "order_number": "000000042",
        "customer_email": "[email protected]",
        "status": "TO_REVIEW",
        "currency": "USD",
        "amount": 97.2,
        "calculated_amount": null,
        "adjusted": false,
        "late_minutes": 1560,
        "due_back": "2026-10-03 17:00",
        "returned_at": "2026-10-04 19:00",
        "lines": [
          { "key": "res-311-ret-90", "kind": "late", "label": "Party tent x 1", "amount": 80, "calculated_amount": null, "edited": false, "late_minutes": 1560, "units": 2, "unit": "day" },
          { "key": "flat", "kind": "flat", "label": "Late return fee", "amount": 10, "calculated_amount": null, "edited": false, "late_minutes": null, "units": null, "unit": null }
        ]
      }],
      "page_info": { "current_page": 1, "total_pages": 1 }
    }
  }
}

Amounts are in the order currency (base_amount is the total in the base currency). Line amounts are before tax; amount on the fee includes tax. Store times (due_back, returned_at) are the booking’s store wall clock as Y-m-d H:i; the other moments are UTC.

A reservation’s late fee so far #

On rentalReservations, late_fee shows the latest late fee holding this reservation’s late time. so_far is this reservation’s lines before tax; total is the whole fee. While the rental is still out the status is ACCRUING and per_day says what one more day adds. It is null when the reservation was not late.

query Overdue {
  rentalReservations(filter: { state: { eq: "OVERDUE" } }) {
    items {
      id
      order_increment_id
      late_fee { number status so_far total per_day currency }
    }
  }
}

Acting on a late fee #

Every action takes the late fee’s number. Accepting and sending a link return a RentalLateFeeActionOutput: the fee after the action, a result (paid, link_sent, charging, needs_confirmation, failed, skipped, unavailable or emailed), the message staff would see, and the pay link when one was made. A declined card is a result, not an error.

mutation Accept {
  acceptRentalLateFee(input: { number: "LF-000000042-1" }) {
    result
    message
    emailed
    pay_url
    late_fee { number status route paid_via paid_at charge_order_number }
  }
}
MutationWhat it does
acceptRentalLateFee(input: {number, route})Accepts a fee To review and collects it with the first route that works, in the store’s order (security deposit, saved card, pay link). With route (DEPOSIT, CARD, LINK) it uses that one, also on a fee already sent a link, declined or waiting for confirmation. An Accruing fee cannot be accepted until the rental is back.
updateRentalLateFee(input: {number, lines, add_lines, note_customer, reason, recalculate})New line amounts ({key, amount}), staff lines ({label, amount}), the note shown in the customer’s emails. A reason is required when an amount changes; the calculated amount is kept beside it. recalculate: true works the fee out again from the rules and drops staff changes. Only before any payment.
waiveRentalLateFee(input: {number, reason})Waives a fee that is not paid; its pay links stop working. The customer is not emailed.
sendRentalLateFeeLink(number)Emails a new signed payment link (valid 14 days) for an accepted, unpaid fee.
recordRentalLateFeeCounterPayment(input: {number, method, reference})Records a fee paid at the counter (CASH, CARD terminal, BANK transfer, OTHER): places the late-fee order with the offline method and marks the fee Paid. The customer gets the receipt email.
refundRentalLateFee(input: {number, amount, reason})Refunds a paid fee in full (leave out amount) or in part: a credit memo on the late-fee order, online when the gateway can, or back through the security deposit when it was kept from it.

updateRentalLateFee, waiveRentalLateFee, recordRentalLateFeeCounterPayment and refundRentalLateFee return the updated RentalLateFee. A business-rule refusal (the fee is paid already, a payment is running, the reason is missing, and so on) is a graphql-input error with a plain sentence in message.

The customer’s own late fees #

With a customer token, customerRentalLateFees lists the signed-in customer’s late fees, newest first, and rental_late_fees on a CustomerOrder lists one booking’s. Fees staff have not reviewed yet, and cancelled ones, are not shown. can_pay is true for a fee sent a pay link, declined on the saved card, or waiting for a 3-D Secure confirmation; pay_url is then a signed link to the store’s own payment page (the link already sent while it works, else a new one), and null otherwise.

query MyLateFees {
  customerRentalLateFees {
    number
    order_number
    status
    status_label
    total { value currency }
    so_far
    lines { label amount { value currency } }
    due_back
    returned_at
    paid_at
    can_pay
    pay_url
  }
}
{
  "data": {
    "customerRentalLateFees": [{
      "number": "LF-000000042-1",
      "order_number": "000000042",
      "status": "PAY_LINK_SENT",
      "status_label": "To pay",
      "total": { "value": 97.2, "currency": "USD" },
      "so_far": false,
      "lines": [
        { "label": "Party tent x 1", "amount": { "value": 80, "currency": "USD" } },
        { "label": "Late return fee", "amount": { "value": 10, "currency": "USD" } }
      ],
      "due_back": "2026-10-03 17:00",
      "returned_at": "2026-10-04 19:00",
      "paid_at": null,
      "can_pay": true,
      "pay_url": "https://your-store.com/salesigniter_rental/latefee/pay/?t=..."
    }]
  }
}

Without a customer token customerRentalLateFees is a graphql-authorization error; rental_late_fees is empty for anyone but the customer who placed the order.

Enumerations #

RentalLateFeeStatus #

ValueMeaning
ACCRUINGStill out: the total grows until the rental is back.
TO_REVIEWBack, waiting for staff.
CHARGINGA payment is running or waiting for the gateway.
PAY_LINK_SENTThe customer was emailed a payment link.
FAILEDThe saved card was declined; see next_attempt_at.
NEEDS_CONFIRMATIONThe bank asked the customer to confirm the payment (3-D Secure).
PAID, WAIVED, CANCELLED, REFUNDED, PART_REFUNDEDClosed one way or another.

RentalLateFeeQueue #

The tabs of Rentals > Late Fees; each fee is in exactly one: TO_REVIEW, UNPAID (accepted, not paid yet), ACCRUING, PAID, WAIVED, CLOSED (cancelled, refunded or part refunded).

Errors #

CategoryWhen
graphql-authorizationThe token lacks the ACL resource, or there is no customer token where one is needed.
graphql-inputA missing number, an unknown queue, status or date, or a fee that cannot take the action.
graphql-no-such-entityNo late fee has that number.

For tokens, dates, paging and error shapes shared by every field, see GraphQL API Overview & Authentication.