Skip to content
Knowledge ERP Docs

API Reference ↗
Inventory

Equipment Loans

Loan equipment to a customer at no charge — reserve it, check it out, and get it back — with full availability and due-date tracking.

An equipment loan lets you hand equipment to a borrower at no charge and get it back — think demo units, courtesy loaners, or trial gear. A loan is operationally the same as a rental, just without the billing.

Loans live in the Inventory module, so any plan that includes Inventory can use them — you don't need the Rentals module.

In this section #

Detailed guides for everything covered here:

  • Loan Agreements — A loan agreement tracks a free equipment loan from creation through reserve, check-out, and return — with availability enforcement and a full audit trail, but no billing.

Starting a loan #

Loans → Loan Agreements → New loan agreement. The same button is on Loans → On Loan, which is the list of units that are out right now.

When to use a loan, a rental, or a plain checkout #

  • Loan — free, no invoice. You still track who has it, when it's due back, and whether a unit is available.
  • Rental — paid, with rates, deposits, and an invoice on close.
  • Checkout — no agreement at all. Hand the unit over, record who took it, get it back. Nothing is reserved and nothing is charged.

Both kinds of agreement reserve a unit over a date window, so a single piece of equipment can never be double-promised across a loan and a rental at the same time. A plain checkout reserves nothing of its own, which is the main reason to make an agreement instead when dates matter — but it can no longer walk off with a unit somebody else has booked. A checkout is refused when it would leave a reserved date window short, and the refusal names the agreement and its dates. Every checkout has to state a due date, and that date is what decides it: a checkout due back before the booking starts doesn't clash, so it goes ahead.

Both also check the units out when they go, so a loan's equipment appears in the Checkouts list alongside everything else — tagged with the loan number it went out under.

The loan lifecycle #

A loan agreement moves through a simple set of states:

  1. Draft — you're still building it.
  2. Reserved — the equipment is held for the loan's date window.
  3. Checked out — the units are physically out with the borrower.
  4. Partially returned — some, but not all, of the units are back; the rest are still out.
  5. Returned — everything is back in stock.
  6. Cancelled — the loan was voided before or during the loan period and will not proceed.

You can check out directly from Draft if you're handing equipment over on the spot; reserving first is optional.

Per-unit tracking and partial returns #

Knowledge tracks the life of every individual inventory unit, so checking out a loan always hands out specific units — even when a line is a quantity of a Product (5 of a Product checks out 5 real units) or a kit (every component unit is checked out). Each unit is linked back to its loan line.

Because of that, you don't have to return a loan all at once. When equipment comes back, choose which units to check in and pick the destination bin. The bins offered are the ones at the site the units went out from, and a bin at another site is refused — the bin is what tells the app which building a unit is in, so returning to one elsewhere would move the equipment rather than shelve it. You do not need permission to view bins to be offered them; returning a loan is loan work.

  • Return a subset and the loan becomes Partially returned — the returned units go back to stock and become available again, while the rest stay out.
  • Return the last outstanding unit and the loan flips to Returned.

A loan line is marked returned once its final unit is back, so a multi-unit line can be brought back in several trips.

Taking equipment back at another site #

Check it in against a bin at its origin, then move it with the Transfer action on the unit. Two steps rather than one on purpose: it records the inter-site movement instead of hiding it inside a return.

Between them the two steps need a role at both ends — the origin, because the Transfer action is only offered on a unit you may edit, and the destination, because the same form asks for update_inventory_items at the site you are moving it to. Both ends want update_inventory_items, not merely view. Somebody who covers only one end gets stuck halfway. (One exception, which is a bug rather than a feature: a reader who can see every bin in the account can leave the Transfer form's location field blank and pick the far bin directly.)

A unit you cannot see cannot be checked in, and the app now says so. Equipment belonging to a site you hold no role at is invisible to your account, so there is nothing for a return to write to. The return is refused, in these words:

Your role does not cover the site it went out from, so it cannot be checked in under your account. Ask a colleague with a role at that site to receive it, or ask an administrator to give you one.

The same sentence on the screen, from POST /loan-agreements/{id}/return as a 422, and from the MCP tool. Nothing is written — the loan stays exactly as it was, and the unit stays checked out where it is. If the loan happens to name a site you hold no role at either, you will not be able to open it at all: Not Found on the page, 404 from the API. From the mobile app it is refused too, whichever way you come at it — its endpoints address the unit, and the unit is the thing you cannot see.

So the answer is simply to hand the job to a colleague who covers the origin. There is no half-finished state to worry about any more: this used to report success and quietly write the loan to Partially Returned over a unit that never moved, which left the kit unbookable and the records disagreeing. It does not do that now.

Creating a loan #

  1. Go to Inventory → Loans and create a new loan.
  2. Choose the borrower (a customer, contact, or staff user) and the loan's start and expected-return dates.
  3. Add the equipment — specific units, Products, or kits.
  4. Optionally fill in any custom fields and link an appointment.
  5. Reserve to hold the equipment, then Check Out when it leaves, and Return it to a bin when it comes back.

Availability #

While a loan is reserved or checked out, its equipment is unavailable for the overlapping dates — to other loans and to rentals. The availability check is shared, so you can trust a single answer to "is this unit available?"

Doing it from the API #

The same lifecycle is available over the REST API: create a loan agreement, add line items, then POST to /reserve, /check-out, and /return.

# Create a loan agreement for a customer
curl -X POST https://your-domain.com/api/v1/loan-agreements \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "borrower_type": "customer",
    "borrower_id": "<customer-id>",
    "start_date": "2026-06-01",
    "end_date": "2026-06-08"
  }'

# Check the equipment out
curl -X POST https://your-domain.com/api/v1/loan-agreements/<loan-id>/check-out \
  -H "Authorization: Bearer $TOKEN"

A checked-out loan exposes the units still out as out_units, each with a checkout_id. To return everything, POST to /return with just a bin_id. To do a partial return, also pass the checkout_ids of the units coming back — the loan stays partially returned until the last one is in.

# Return only two specific units
curl -X POST https://your-domain.com/api/v1/loan-agreements/<loan-id>/return \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "bin_id": "<bin-id>",
    "checkout_ids": ["<checkout-id-1>", "<checkout-id-2>"]
  }'