Skip to content

Renting Products

The Rentals module lets a catalog product be rented for a time period. You mark a product as rentable (with a capacity and rental terms), check date-ranged availability, create a rental agreement, confirm it to hold capacity, and record returns. SynthesQ guarantees a product is never double-booked beyond its capacity.

All endpoints are under /api/v1/rentals and require a Bearer token.

Catalog products are referenced by id

Rentals never modifies your catalog. A rentable product simply points at an existing product by its product_id. Create the product through the Operations API first.

Concepts

  • Rentable product — a catalog product you have enabled for rent, with a pooled capacity and rental terms (unit period + min/max duration).
  • Rental agreement — the contract with a customer. It owns one or more lines.
  • Line — a single dated hold: [period_from, period_to) against a rentable product, for a quantity. The line is the reservation.
  • Availabilitycapacity minus the peak number of overlapping held lines over the requested window. It is computed live, so it is always correct.

Rental terms

FieldMeaning
unit_periodGranularity for durations. One of: hour, day, week, month, year.
min_durationMinimum number of unit_periods a single hold may span (≥ 1).
max_durationMaximum number of unit_periods, or omit for unbounded.
auto_release_defaultWhether holds free capacity automatically at their end date (see below).
capacityHow many units may be held at the same time.

Agreement lifecycle

StatusMeaningCan transition to
draftCreated, capacity not yet held.confirmed, cancelled
confirmedCapacity is held for every line.completed, cancelled
completedAll lines have ended/returned.— (final)
cancelledCancelled; capacity freed.— (final)
draft ──confirm──▶ confirmed ──(all lines ended)──▶ completed
  │                    │
  └──cancel──▶ cancelled◀──cancel──┘

Auto-release vs. manual return

Each line is either auto-release or manual-release (resolved when you confirm, from the agreement's auto_release override or the product's auto_release_default):

  • Auto-release — the hold frees capacity automatically at period_to. Good for time-boxed bookings (e.g. a nightly room booking).
  • Manual-release — the hold persists until you record a return. Past its period_to without a return, the line is overdue and appears in the overdue feed.

Line states (read-only)

Each line reports a derived state:

StateMeaning
scheduledThe hold has not started yet.
activeCurrently within [period_from, period_to).
completedReturned, or auto-released past its end.
overdueManual-release, past its end, not yet returned.

Walkthrough

1. Make a product rentable

bash
curl -X POST https://api.synthesq.com/api/v1/rentals/rentable-products \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "product_id": "01hwxyz123abc456def789ghi0",
    "capacity": 3,
    "unit_period": "day",
    "min_duration": 1,
    "max_duration": 30,
    "auto_release_default": true
  }'

Returns 201 with the rentable product. Re-posting for the same product_id updates it (there is one rentable record per product).

2. Check availability for a window

bash
curl "https://api.synthesq.com/api/v1/rentals/rentable-products/01hwxyz123abc456def789ghi0/availability?from=2026-08-02&to=2026-08-04" \
  -H "Authorization: Bearer <token>"
json
{
  "success": true,
  "data": {
    "product_id": "01hwxyz123abc456def789ghi0",
    "period": { "from": "2026-08-02T00:00:00+00:00", "to": "2026-08-04T00:00:00+00:00" },
    "capacity": 3,
    "available": 2
  }
}

Half-open intervals

Periods are half-open: a hold that ends exactly when another begins does not collide, so back-to-back bookings both fit.

3. Create a draft agreement

bash
curl -X POST https://api.synthesq.com/api/v1/rentals/agreements \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "customer_id": "01hwxyzcustomer000000000aa",
    "lines": [
      {
        "product_id": "01hwxyz123abc456def789ghi0",
        "quantity": 1,
        "period_from": "2026-08-01",
        "period_to": "2026-08-05"
      }
    ]
  }'

A draft does not hold capacity yet. Each line's period must be in the future, end after it starts, and fit the product's rental terms; the product must be rentable.

4. Confirm to hold capacity

bash
curl -X POST https://api.synthesq.com/api/v1/rentals/agreements/01hwxyzagreement0000000aa/confirm \
  -H "Authorization: Bearer <token>"

Returns 200 with data.status.value = confirmed. If the window is already fully booked, you get 409:

json
{ "success": false, "message": "Insufficient availability for [..]: requested 1, available 0" }

No double-booking

Confirmation is the point where capacity is checked and held under a lock. Two confirmations competing for the last unit cannot both succeed — one gets 409.

5. Record a return (manual-release lines)

bash
curl -X POST https://api.synthesq.com/api/v1/rentals/agreements/01hwxyzagreement0000000aa/lines/01hwxyzline00000000000aa/return \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{ "returned_at": "2026-08-05T10:00:00Z" }'

When the last open line is returned (or auto-releases), the agreement becomes completed. Omit returned_at to use the current time.

6. Cancel

bash
curl -X POST https://api.synthesq.com/api/v1/rentals/agreements/01hwxyzagreement0000000aa/cancel \
  -H "Authorization: Bearer <token>"

Cancelling a confirmed agreement frees its held capacity immediately.

Finding overdue rentals

bash
curl https://api.synthesq.com/api/v1/rentals/agreements/overdue \
  -H "Authorization: Bearer <token>"

Returns the lines that are confirmed, manual-release, past their end date, and not yet returned.

Roles

RoleCapabilities
rentals-adminEverything, including configuring rentable products and cancelling agreements.
rentals-agentView, create, confirm, and record returns — but not configure products or cancel.

See also

Documentation for SynthesQ CRM/ERP Platform