View Categories

REST API: Sub-Rentals and suppliers

11 min read

The REST API for Sub-Rentals: list and read the sub-rentals that cover short bookings, see which bookings are still short, create a cover, move a sub-rental through its statuses, count units in and out, add supplier charges, and manage the suppliers. Everything the Sub-rentals screens do goes through these endpoints, so an outside system (a purchasing tool, a warehouse app, your own dashboard) can do the same. The setup and the conventions shared by every endpoint (keys, errors, pagination) are in <a href=”/docs/rest-api/”>REST API overview and authentication</a>.

Base URL and sign-in #

NamespaceWhat lives thereNeeds
/wp-json/wc-sibooking/v1/subrentals (list, create, read, update, status, receive, return, charges, shortages) and suppliersSub-Rentals, with Rentals & Bookings Regular
  • wc-sibooking/v1 takes a WooCommerce REST API key (WooCommerce > Settings > Advanced > REST API) sent as HTTP Basic, like the other rental endpoints. A read key can call the GET routes; the routes that change something need a read/write key. The key’s user decides what the call may do (next section), so make the key under a user who has the abilities you need.
  • The routes have been in Sub-Rentals since 1.0.0.
  • Send bodies as JSON (Content-Type: application/json).
  • Dates are Y-m-d or Y-m-d H:i or Y-m-d H:i:s in the store’s time. A bare date means the start of that day for collect_by, and the end of that day for return_by. Responses give Y-m-d H:i:s.
  • Money is a plain number in the store’s currency (120 or 35.5), never in cents. Money fields are sent as a string or a number.
  • Errors use the WordPress shape {"code", "message", "data": {"status"}}. The Sub-Rentals codes start with sisubrent_.
  • Nothing here emails a supplier. Moving a sub-rental to requested records the move and the sent_at time, and staff still press Send on the screen to email the request.
STORE="https://example.com/wp-json"
curl -u "ck_your_key:cs_your_secret" "$STORE/wc-sibooking/v1/subrentals?segment=open"

Who may do what #

Anyone with manage_woocommerce (shop managers and administrators) has all four Sub-Rentals abilities without any setup, and a role editor can still give or take each one on a role or a user.

AbilityWho has itOpens
sisubrent_createUsers with manage_woocommerce, and any role given itCreating and editing sub-rentals, moving their status (except closing), receiving and returning units
sisubrent_manageUsers with manage_woocommerce, and any role given itThe suppliers routes, closing a sub-rental, adding charges, a back-dated at on a receive or return
sisubrent_view_costsUsers with manage_woocommerce, and any role given itThe cost, money and margin fields, and GET /subrentals/{id}/charges
sisubrent_approveUsers with manage_woocommerce, and any role given itSending or confirming a sub-rental over the approval limit
operate (Rentals & Bookings)Users with manage_woocommerceListing and reading sub-rentals, and receiving and returning units, for a user who has no Sub-Rentals ability

A user without the ability gets 401 (not signed in) or 403, code sisubrent_forbidden.

Who sees what in the answers:

  • Without sisubrent_view_costs, a sub-rental comes back without the money object and its lines without cost, and fees on an update is ignored.
  • notes comes back empty unless the user has sisubrent_create or sisubrent_manage. An operate user sees the status and the lines, and no more.

Sub-rentals #

A sub-rental is one supplier order that covers one or more short bookings. Its number is SR- followed by a counter (SR-1104). A sub-rental is created draft.

Statuses #

StatusMeaningCan become
draftMade, not sentrequested, confirmed, cancelled
requestedAsked of the supplierconfirmed, received, declined, cancelled
confirmedThe supplier said yesreceived, declined, cancelled
receivedThe units are inreturned
returnedThe units went back to the supplierclosed
closed, declined, cancelledFinishedNothing

Moving to the status a sub-rental is already in is accepted and changes nothing. A move not in the table answers 409 with code sisubrent_status. A sub-rental with no lines cannot move to requested, confirmed or received (400, sisubrent_empty). Moving from draft to requested or confirmed also checks the approval limit (Sub-rentals > Settings > Money): a sub-rental over the limit answers 409, sisubrent_approval, unless the user has sisubrent_approve.

The sub-rental object #

FieldNotes
id, numberThe id and SR-1104
statusOne of the statuses above
supplier_id, supplierThe supplier’s id and name
location_idThe location that takes delivery; 0 = none (Multi Location Inventory)
delivery_modecollect (default), to_shop or on_site
collect_by, return_byThe window the supplier’s units are in your hands
notesStaff notes; empty for users who may not see them
sent_at, confirmed_at, received_at, returned_at, closed_atSet when the status moved there; null before
linesThe bookings this sub-rental covers (below)
moneyOnly with sisubrent_view_costs (below)

Each entry in lines:

FieldNotes
idThe line id; the key of lines in a receive or return
booking_id, order_idThe short booking it covers and its WooCommerce order
product_id, variation_id, product_nameWhat it covers
quantity, received_qty, returned_qtyUnits ordered, counted in and counted back
asset_tagsSerial or asset tags written on the line
cover_stateWhether the line covers its booking, as covers
costThe line’s cost; only with sisubrent_view_costs

money, only with sisubrent_view_costs:

FieldNotes
linesThe cost of the lines
invoiceThe supplier’s invoice total, or null until one is entered
billed_onThe part billed on to customers
invoice_coverstrue when the invoice replaces the line costs in the total
feesFees on the sub-rental
chargesThe sum of the charges
totalWhat the sub-rental costs
revenue, margin, margin_percentWhat the covered bookings bring in, the margin on total, and the percent (a string)

GET /wc-sibooking/v1/subrentals #

The list, the same as the Sub-rentals screen. Needs sisubrent_create, sisubrent_manage or operate.

ParameterNotes
segmentopen (default: not closed, declined or cancelled), all, to_send (draft), awaiting (requested), collect (requested or confirmed, collect-by within 7 days), out (received), return_due (received, return-by within the store’s “show as return due” hours), overdue (received, return-by passed), to_close (returned), closed (closed, declined and cancelled). An unknown value reads as open
supplier_idOnly this supplier’s sub-rentals
searchMatches the number, the supplier’s name, a product name on a line, or an order id
page, per_pageDefault 1 and 25; per_page is capped at 500

Sorted by collect_by, earliest first. The answer is an array of sub-rental objects. The X-WP-Total header holds the count; there is no X-WP-TotalPages.

GET /wc-sibooking/v1/subrentals/shortages #

The bookings the stock cannot hold and nothing covers yet. Needs the same ability as the list.

ParameterNotes
page, per_pageDefault 1 and 25; per_page is capped at 500
FieldNotes
product_idThe product that is short (the stock pool’s product)
booking_id, order_idThe short booking and its order
shortHow many units are short
from, toThe span that is short, in store time

The X-WP-Total header holds the count. A booking leaves this list once a sub-rental covers it, and comes back if that sub-rental is cancelled or declined.

GET /wc-sibooking/v1/subrentals/{id} #

One sub-rental object. Errors: 404 sisubrent_missing when it does not exist.

POST /wc-sibooking/v1/subrentals #

Covers one short booking with a new draft sub-rental. Needs sisubrent_create. It answers 201 with the sub-rental object.

ParameterNotes
booking_idInteger, required. A booking from the shortages list
supplier_idInteger, required. An active supplier
unitsInteger, required. At least the booking’s short
collect_by, return_byStrings, required. The supplier’s window. It has to reach over the whole rental: collect earlier or return later than the booking’s own dates
costOptional. The line cost you were quoted. Without it the supplier’s rate for the product is used
feesOptional. Fees on the sub-rental
ErrorWhen
409 sisubrent_windowThe dates do not cover the rental
409 sisubrent_unitsunits is below what is short
409 sisubrent_nothing_shortThe booking is not short, or is already covered
409 sisubrent_approvalThe total is over the approval limit and the user has no sisubrent_approve. Nothing is saved
400 sisubrent_datesA date is missing or unreadable
400 sisubrent_supplier_missingThe supplier is missing or inactive
400 sisubrent_no_bookingNo booking to cover was found
400 rest_missing_callback_paramA required parameter is missing

PATCH /wc-sibooking/v1/subrentals/{id} #

Changes dates, delivery, notes or fees (PUT works too). Send only what changes. Needs sisubrent_create. It answers with the sub-rental object.

ParameterNotes
collect_by, return_byStrings. The return has to be after the collect
delivery_modecollect, to_shop or on_site; another value is ignored
notesString
feesNumber or string. Ignored without sisubrent_view_costs
ErrorWhen
404 sisubrent_missingNo such sub-rental
409 sisubrent_lockedThe sub-rental is closed, declined or cancelled
400 sisubrent_datesThe return is not after the collect, or a date is unreadable

POST /wc-sibooking/v1/subrentals/{id}/status #

Moves the sub-rental to another status. Needs sisubrent_create; moving to closed needs sisubrent_manage.

ParameterNotes
statusRequired. One of the eight statuses. Another value answers 400 rest_invalid_param
noteOptional. A note kept in the sub-rental’s history

It answers with the sub-rental object. Errors: 409 sisubrent_status (the move is not allowed), 409 sisubrent_moved (someone changed it at the same moment: read it again), 409 sisubrent_approval, 400 sisubrent_empty, 403 sisubrent_forbidden (closing without sisubrent_manage).

POST /wc-sibooking/v1/subrentals/{id}/receive #

Counts the units in and moves a requested or confirmed sub-rental to received. Needs sisubrent_create or operate.

ParameterNotes
linesOptional object of line id to units counted, for example {"105": 1}. A line left out counts its whole quantity. A count above quantity is cut to quantity
atOptional date and time of the count. Used only for users with sisubrent_manage; everyone else gets the time of the call

POST /wc-sibooking/v1/subrentals/{id}/return #

The same for giving the units back: moves a received sub-rental to returned and sets returned_qty. Same parameters and errors as receive.

GET /wc-sibooking/v1/subrentals/{id}/charges #

The sub-rental’s charges, oldest first. Needs sisubrent_view_costs.

FieldNotes
idThe charge id
line_idThe line it belongs to, or 0
kindlate, damage, loss, freight, cancellation or other
amountA number in the store’s currency
notesWhat the charge is for
rebill_order_idThe customer order it was billed on to, or 0
late_billtrue when it was added after the sub-rental finished

POST /wc-sibooking/v1/subrentals/{id}/charges #

Adds a charge. Needs sisubrent_manage. It answers 201 with the charge object. There is no route to remove or edit a charge: do that on the sub-rental’s screen.

ParameterNotes
kindRequired. late, damage, loss, freight, cancellation or other
amountRequired. A number above zero
line_idOptional. A line id of this sub-rental
notesOptional while the sub-rental is open. Required for a late bill

Suppliers bill late, so a finished sub-rental still takes some charges:

StatusWhat it takes
draft, requested, confirmed, received, returnedEvery kind except cancellation
closedEvery kind except cancellation, as a late bill: notes are required and the charge comes back with late_bill: true
cancelledOnly cancellation, as a late bill
declinedNothing: it never happened
ErrorWhen
409 sisubrent_charge_kindA cancellation charge on a sub-rental that is not cancelled
409 sisubrent_lockedAny other kind on a cancelled sub-rental, or any charge on a declined one
400 sisubrent_charge_noteA late bill without notes
400 sisubrent_charge_amountamount is zero or less
403 sisubrent_forbiddenThe user lacks sisubrent_manage

Suppliers #

All the suppliers routes need sisubrent_manage.

The supplier object:

FieldNotes
id, activeThe id, and whether the supplier is offered in the pickers
nameRequired
contact, email, phoneWho to ask
address_1, address_2, city, postcode, countrycountry is a two-letter code, saved upper case
notes, termsFree text
lead_daysDays of notice the supplier needs, 0 to 365, or null

GET /wc-sibooking/v1/suppliers #

Active suppliers, sorted by name.

ParameterNotes
searchMatches name, contact or email
page, per_pageDefault 1 and 25; per_page is capped at 500

The X-WP-Total header holds the count. A supplier made inactive on the screen is not listed.

GET /wc-sibooking/v1/suppliers/{id} #

One supplier. Errors: 404 sisubrent_supplier_missing.

POST /wc-sibooking/v1/suppliers #

Creates a supplier and answers 201 with it. name is required (400 sisubrent_supplier_name when empty); any other field of the object can be sent. The supplier is active. A supplier’s rates per product and its late-fee policy are set on the screen: this route does not take them.

PATCH /wc-sibooking/v1/suppliers/{id} #

Changes the fields you send (PUT works too) and answers with the supplier. Fields you leave out keep their value. Errors: 404 sisubrent_supplier_missing, 400 sisubrent_supplier_name (the name was set to empty). There is no route to deactivate or delete a supplier: do that on the screen.

Examples #

Which bookings are short:

curl -u "ck_your_key:cs_your_secret" \
  "https://example.com/wp-json/wc-sibooking/v1/subrentals/shortages"
[
  {
    "product_id": 456,
    "booking_id": 773,
    "order_id": 7929,
    "short": 1,
    "from": "2027-02-01 00:00:00",
    "to": "2027-03-01 23:59:00"
  }
]

Create a supplier, then cover booking 773 with a sub-rental. The supplier’s window starts three days before the rental and ends three days after:

curl -u "ck_your_key:cs_your_secret" -X POST \
  -H "Content-Type: application/json" \
  -d '{"name": "Cooper Rentals", "contact": "James Cooper", "email": "[email protected]", "lead_days": 2}' \
  "https://example.com/wp-json/wc-sibooking/v1/suppliers"

curl -u "ck_your_key:cs_your_secret" -X POST \
  -H "Content-Type: application/json" \
  -d '{"booking_id": 773, "supplier_id": 123, "units": 1, "collect_by": "2027-01-29", "return_by": "2027-03-04", "cost": "120.00", "fees": "10"}' \
  "https://example.com/wp-json/wc-sibooking/v1/subrentals"
{
  "id": 104,
  "number": "SR-1104",
  "status": "draft",
  "supplier_id": 123,
  "supplier": "Cooper Rentals",
  "delivery_mode": "collect",
  "collect_by": "2027-01-29 00:00:00",
  "return_by": "2027-03-04 23:59:59",
  "lines": [
    {
      "id": 105,
      "booking_id": 773,
      "order_id": 7929,
      "product_id": 456,
      "quantity": 1,
      "received_qty": 0,
      "returned_qty": 0,
      "cover_state": "covers",
      "cost": 120,
      "...": "..."
    }
  ],
  "money": { "lines": 120, "fees": 10, "charges": 0, "total": 130, "...": "..." },
  "...": "..."
}

Mark it requested, count it in, count it back, close it, and add a late bill from the supplier:

curl -u "ck_your_key:cs_your_secret" -X POST \
  -H "Content-Type: application/json" \
  -d '{"status": "requested", "note": "Sent by phone"}' \
  "https://example.com/wp-json/wc-sibooking/v1/subrentals/104/status"

curl -u "ck_your_key:cs_your_secret" -X POST \
  -H "Content-Type: application/json" \
  -d '{"lines": {"105": 1}}' \
  "https://example.com/wp-json/wc-sibooking/v1/subrentals/104/receive"

curl -u "ck_your_key:cs_your_secret" -X POST \
  -H "Content-Type: application/json" -d '{}' \
  "https://example.com/wp-json/wc-sibooking/v1/subrentals/104/return"

curl -u "ck_your_key:cs_your_secret" -X POST \
  -H "Content-Type: application/json" -d '{"status": "closed"}' \
  "https://example.com/wp-json/wc-sibooking/v1/subrentals/104/status"

curl -u "ck_your_key:cs_your_secret" -X POST \
  -H "Content-Type: application/json" \
  -d '{"kind": "late", "amount": "20", "notes": "One extra day"}' \
  "https://example.com/wp-json/wc-sibooking/v1/subrentals/104/charges"

The last call answers 201:

{
  "id": 30,
  "line_id": 0,
  "kind": "late",
  "amount": 20,
  "notes": "One extra day",
  "rebill_order_id": 0,
  "late_bill": true
}

A cover that does not fit answers 409 and saves nothing:

{
  "code": "sisubrent_window",
  "message": "Those dates do not cover the rental. Collect earlier or return later.",
  "data": { "status": 409 }
}

Hooks #

sisubrent_status_changed fires after every status move made through the API, with the sub-rental id, the old status, the new status and a context array. It is listed in the plugin’s hooks reference, in the plugin’s docs folder.