Rental Agreements
A Rental Agreement tracks the full paid-rental lifecycle — from draft through reservation, pickup, return, and final close-out — and generates a Customer Invoice with the actual duration, late fees, and any damage charges when you close it.
A Rental Agreement is the central record for a paid equipment rental. It ties a customer to one or more pieces of equipment for a date range, tracks the deposit and billing terms, and drives the status transitions that move equipment from your shelf to the customer and back. When you close the agreement a Customer Invoice is generated automatically, priced against the actual rental duration — not just the planned one.
Rental Agreements cover paid rentals billed to a customer. If you need to lend equipment at no charge, use a Loan Agreement instead.
Creating a rental agreement #
New agreements are created from Rentals → Rental Agreements → New Rental Agreement. Every agreement starts in Draft status, which lets you fill in details and add line units before committing to anything.
- Customer — the customer being billed. Required; drives the contact list and is used to resolve customer-specific rental rates.
- Contact — an optional contact from the selected customer for the person picking up the equipment.
- Location — which inventory location the equipment comes from. Used for location-scoped rate lookups.
- Start date / Expected return — the planned rental window. Both are required. The expected return date is used for overdue detection and for availability checks.
- Security deposit — an amount (in dollars in the UI) held from the customer, then refunded as a credit memo when you close the agreement. Stored in cents internally.
- Late fee % — a surcharge percentage applied to overdue days on top of the normal rate. The billing service converts this to a dollar line on the final invoice.
- Damage charge — any equipment damage amount to deduct from the deposit refund and bill on close. Entered in dollars; stored in cents.
- Billing cycle — Bill at close only, Weekly, or Monthly. Long-term rentals
can be billed periodically; the
billed_through_dateadvances after each cycle run. - Tax rate — an optional tax rate applied when the invoice is generated.
- Notes — free-text visible on the agreement and invoice.
The agreement number is auto-generated in the format RA-0001, RA-0002, etc.
Rental Agreement Items #
Line items are added from the Items tab on the agreement's view page. Each line represents one type or unit of equipment being rented.
- Rentable — what is being rented. A line can point to a Product (a class of equipment, e.g. "Lift, 40ft"), a specific Unit (a serialized unit), or a Kit (a bundle). Product-based lines use quantity; unit-based lines check out the exact unit.
- Quantity — how many units (relevant for Product-based lines).
- Rate period — Daily, Weekly, or Monthly. Determines the billing unit.
- Rate amount — the price per period, in dollars in the UI (cents in the API). If you leave this blank when reserving, the system snapshots the matching Rental Rate automatically.
- Notes — per-line notes that carry through to the invoice description.
The agreement's subtotal is the sum of all line totals. Tax and any fees are added when the invoice is generated at close.
The rental lifecycle #
A rental agreement moves through a fixed set of statuses. Each transition is a distinct action in the UI and an API sub-action:
| Status | What it means |
|---|---|
| Draft | Being built — no holds placed, nothing committed. |
| Reserved | Availability confirmed; equipment is held for this date range. Rates are snapshotted. |
| Picked Up | Equipment has left the building; individual units are checked out and marked unavailable. |
| Partially Returned | Some units are back in stock; the rest are still out. The agreement stays here until the last unit returns. |
| Returned | Equipment is back and checked in to a bin; not yet invoiced. |
| Closed | Invoice generated, deposit refunded as a credit memo. Terminal. |
| Cancelled | Agreement ended without completion. Cannot cancel while status is Picked Up or Partially Returned — return the equipment first. |
Reserve checks availability across the full date range and confirms each line can be fulfilled. If any piece of equipment is already booked, the reserve action fails with a clear message rather than double-booking silently.
Pickup re-checks availability at the moment of departure and checks out specific inventory units for every line — Knowledge tracks the life of each individual unit, so a Product line of quantity 3 allocates three real units and a kit checks out each of its component units. Every checkout is linked back to its line. The units become Checked Out in inventory and are no longer available to others.
Return requires a destination bin, and lets you choose which units are coming back (all of them by default). Return everything and the agreement moves to Returned; return only some and it becomes Partially Returned, with the returned units back in stock and available again while the rest stay out. A Partially Returned agreement can be returned again later to bring in the remainder.
Close generates the Customer Invoice priced by the actual rental duration. Each unit is billed per its own time out — a unit returned early stops accruing on its return date while units still out keep billing through the end of the window — so a partial return is reflected automatically. Close is available from Picked Up, Partially Returned, and Returned. Late fees (computed per unit on the days each was held past the due date) and damage charges are added as separate invoice lines. If a deposit was collected, a credit memo is issued automatically for the deposit net of any damage charge. The invoice starts in Draft status.
Picked Up and Reserved statuses block availability. Other rental agreements that overlap the same dates for the same equipment will be refused at reserve time.
Availability checking #
Before committing an agreement, you can check availability from Rentals → Rental Calendar or via the API. The calendar shows what equipment is out and when, so you can spot gaps before creating agreements.
The rental agreements list #
The list (Rentals → Rental Agreements) shows each agreement's number, customer, status badge, start date, expected return, and total amount. Search by customer name or agreement number (status filtering is available via the API). Agreements are sorted newest-first.
Related records #
When you close a rental agreement, two records are created automatically:
- A Customer Invoice linked via
customer_invoice_id— see Customer Invoices for how to collect payment. - A Credit Memo linked via
deposit_credit_memo_id(if a deposit was collected), which can be applied to any outstanding invoice for the customer.
Rental agreements also carry a full change history tab powered by the change tracker.
Doing it from the API #
# Create a rental agreement in Draft
curl -X POST "https://your-domain.com/api/v1/rental-agreements" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"customer_id": "...",
"start_date": "2026-07-01",
"end_date": "2026-07-07",
"deposit_amount": 25000,
"billing_cycle": "none"
}'
# Reserve it (confirms availability and snapshots rates)
curl -X POST "https://your-domain.com/api/v1/rental-agreements/{id}/reserve" \
-H "Authorization: Bearer $TOKEN"
# Return only some units (partial return). Omit checkout_ids to return everything.
curl -X POST "https://your-domain.com/api/v1/rental-agreements/{id}/return" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"bin_id": "<bin-id>", "checkout_ids": ["<checkout-id>"]}'
# Close it (generates the invoice and refunds the deposit)
curl -X POST "https://your-domain.com/api/v1/rental-agreements/{id}/close" \
-H "Authorization: Bearer $TOKEN"
A picked-up agreement lists the units still out under out_units (each with a
checkout_id) — pass a subset as checkout_ids on the return call to return only those.
The agreement reports partially_returned until the last unit is back, and a
rental.partially_returned webhook fires on that transition.
Money fields (
deposit_amount,damage_charge, andrate_amounton line items) are integers in cents over the API (25000= $250.00). Invalid lifecycle transitions (e.g. closing a Draft) return HTTP 422 with an error message.