The maintenance operations of the Rentals & Bookings GraphQL API: maintenance tickets for rental units (repairs, services and inspections) and the stock they keep out, technicians, service schedules and checklists, costs, parts and vendors, damage charges and the maintenance reports. They use the same address, keys and rules as the rest of the API: see GraphQL API reference: Rentals & Bookings for how to send a request, and the API overview for keys, limits and errors. The ticket statuses, the actions, the cost lines and every field are explained on the REST page: REST API reference: Maintenance.
Needs the Rentals & Bookings app. Every operation needs a secret key; mutations need Allow changes (write). The Free plan’s API reads only: a mutation is refused before it runs with errors[].extensions.code: "plan_required" (data.plan: "free", data.required_plan: "regular"). Maintenance is on every plan; while it is turned off in Settings › Maintenance, sendRentalUnitToMaintenance answers maintenance_off (tickets already open keep working).
- Ids are global:
gid://sirentals/MaintenanceTicket/17,MaintenanceTechnician,MaintenanceSchedule,MaintenanceServiceUnit(one unit’s row of a schedule),MaintenanceChecklist,MaintenanceInspection,MaintenancePart,MaintenanceVendor,MaintenanceCost(a cost line),LateFee(a damage charge),SerialNumberandBooking; products, variants, locations, orders and customers are Shopify gids. Every id argument also takes the bare number, andlegacyResourceIdgives it. A status id (statusId) is the number fromrentalMaintenanceStatuses. kind,priority,holdMode,outcome,momentandrouteare lowercase strings (repair,high,block,fixed,checkin,link); the ticket action, the timer action, the ticket list and the report type are enums.- Times (
holdStart,expectedBack,openedAt,closedAt) areY-m-d H:iin the store’s time zone (expectedBackmay be a day);createdAtandupdatedAtare ISO 8601. Money is a decimal string in the store currency. - A ticket never carries the customer’s name or email: only the order and customer ids.
- Mutations answer
userErrors { field message code data }when a change is refused:invalid,invalid_product,unit_not_found,unit_on_ticket,confirm_backdate,not_allowed,confirm_write_off,ticket_closed,timer_running,charges_off,charge_open,no_rental,reason_required,not_foundand so on. The REST errors table explains each.
curl -s "https://YOUR-API-ADDRESS/graphql/2026-10" -H "Authorization: Bearer sirb_your_secret_key" -H "Content-Type: application/json" \
-d '{"query": "{ rentalMaintenanceTickets(first: 20, status: OVERDUE) { totalCount nodes { id reference title status priority expectedBack } } }"}'
Tickets #
A ticket is one repair, service or inspection of one rent variant. While its status blocks stock and its hold mode is block, its units can’t be booked from holdStart until expectedBack (or until it closes). actions lists what the ticket’s status allows now; the statuses and actions are listed on the REST page.
| Operation | Arguments | What it does |
|---|---|---|
rentalMaintenanceTicketsquery · secret key returns RentalMaintenanceTicketConnection! | first: Intafter: Stringlast: Intbefore: Stringstatus: RentalMaintenanceTicketFilterquery: StringvariantId: IDproductId: IDserial: StringbookingId: IDticketStatus: Stringpriority: StringupdatedSince: String | Tickets, paged. status picks the list (default OPEN). Open lists come most urgent first (priority, then expected back); CLOSED and ALL come last updated first. query searches the MT number, title, product, SKU, order name and serial. |
rentalMaintenanceTicketquery · secret key returns RentalMaintenanceTicket | id: ID! | One ticket with its timeline (events), its files (attachments, metadata only), costs and damage, or null. |
rentalMaintenanceStatusesquery · secret key returns [RentalMaintenanceStatus!]! | – | The store’s ticket statuses in their order: the built-in ones and the store’s own (which have no key). Their id is what MOVE takes as statusId. |
rentalMaintenanceTechniciansquery · secret key returns [RentalMaintenanceTechnician!]! | – | Who tickets can be assigned to, the least busy first: id, name and open tickets. Never an email address. |
sendRentalUnitToMaintenancemutation · secret key returns RentalMaintenanceTicketPayload! | input: RentalMaintenanceTicketCreateInput! | Open a ticket (source api) for serials or a quantity of one rent variant. With hold mode block it keeps the units out of stock from start. Refused with unit_on_ticket (a serial is on an open ticket already), confirm_backdate (a start in the past without confirmBackdate: true) or maintenance_off (maintenance is turned off in Settings › Maintenance). |
updateRentalMaintenanceTicketmutation · secret key returns RentalMaintenanceTicketPayload! | input: RentalMaintenanceTicketUpdateInput! | Change a ticket’s details, its hold or Customer may be charged; only the fields you send change. On a closed ticket only the title, description, priority and mayCharge change; anything else is ticket_closed until it is reopened. |
changeRentalMaintenanceTicketStatusmutation · secret key returns RentalMaintenanceTicketPayload! | input: RentalMaintenanceTicketStatusInput! | Move a ticket on with one of the actions its status allows (the ticket’s actions); any other is not_allowed. WRITE_OFF also takes the units out of stock for good unless reduceStock: false, and asks for confirm: true (confirm_write_off) when bookings would be left short. MOVE goes to one of the store’s own open or waiting statuses (statusId). |
addRentalMaintenanceTicketCommentmutation · secret key returns RentalMaintenanceTicketPayload! | ticketId: ID!text: String! | Add a comment to the ticket’s timeline. |
assignRentalMaintenanceTicketmutation · secret key returns RentalMaintenanceTicketPayload! | ticketId: ID!technicianId: ID | Assign a technician from rentalMaintenanceTechnicians; they get an email. Leave out technicianId to unassign. |
query Overdue {
rentalMaintenanceTickets(first: 20, status: OVERDUE) {
totalCount
pageInfo { hasNextPage endCursor }
nodes {
id reference title kind status statusLabel priority productTitle sku
units { code holdState }
expectedBack assigneeName orderName actions
}
}
}
mutation SendToMaintenance {
sendRentalUnitToMaintenance(input: {
variantId: "gid://shopify/ProductVariant/44001", units: ["PW-07"], priority: "high", problem: "Damaged",
title: "Trigger stuck", bookingId: "gid://sirentals/Booking/42", mayCharge: true, expectedBack: "2026-11-12",
technicianId: "gid://sirentals/MaintenanceTechnician/3"
}) {
ticket { id reference status hold { state start end } }
userErrors { field code message data }
}
}
mutation ReadyToRent {
changeRentalMaintenanceTicketStatus(input: {
ticketId: "gid://sirentals/MaintenanceTicket/17", action: READY, outcome: "replaced", note: "New trigger fitted and tested."
}) {
ticket { id status statusCategory outcome closedAt actions }
userErrors { field code message }
}
}
RentalMaintenanceTicketCreateInput
| Field | Type | Notes |
|---|---|---|
variantId | ID! | gid://shopify/ProductVariant/… or the number: a rent variant. |
units | [String!] | Serial numbers (or unit ids) of a product that tracks serials. |
quantity | Int | Units (a product without serials). |
kind | String | repair (default), service or inspection. |
priority | String | low, normal (default), high or urgent. |
title | String | Default: the problem, else the kind. |
description | String | |
problem | String | |
locationId | ID | |
holdMode | String | block or none (default: Settings › Maintenance). |
start | String | Y-m-d H:i, store time (default now). A past start needs confirmBackdate. |
expectedBack | String | Y-m-d or Y-m-d H:i; null = until done. |
confirmBackdate | Boolean | |
bookingId | ID | Link the rental it came back from: its order and customer come with it. |
mayCharge | Boolean | |
technicianId | ID | Assign it to a technician from rentalMaintenanceTechnicians (they get an email). |
RentalMaintenanceTicketUpdateInput
| Field | Type | Notes |
|---|---|---|
ticketId | ID! | |
title | String | |
description | String | |
kind | String | |
priority | String | |
start | String | |
expectedBack | String | |
holdMode | String | |
locationId | ID | |
confirmBackdate | Boolean | |
mayCharge | Boolean | Customer may be charged (the security deposit is held until you decide). |
RentalMaintenanceTicketStatusInput
| Field | Type | Notes |
|---|---|---|
ticketId | ID! | |
action | RentalMaintenanceAction! | |
note | String | |
outcome | String | READY: fixed, no_fault or replaced (default fixed). |
reduceStock | Boolean | WRITE_OFF: take the units out of stock for good. |
confirm | Boolean | WRITE_OFF: go ahead although bookings would be left short. |
statusId | ID | MOVE: the status to move to (an id from rentalMaintenanceStatuses). |
| Enum | Values |
|---|---|
RentalMaintenanceTicketFilter | OPEN – Not closed.OVERDUE – Not closed and past the expected back date.WAITING – Waiting for parts or at a vendor.CLOSED – Ready to rent, written off or cancelled.ALL |
RentalMaintenanceAction | CONFIRM – A reported ticket becomes New (its hold starts).STARTREADY – Ready to rent: closes the ticket and frees the stock.WAIT_PARTSSEND_VENDORRESUMEBACK_FROM_VENDORWRITE_OFF – Closes the ticket; reduceStock also takes the units out of stock for good.CANCELREOPENMOVE – To one of the store’s own open or waiting statuses (statusId, from rentalMaintenanceStatuses). |
| Type | Fields |
|---|---|
RentalMaintenanceTicketA maintenance ticket: a repair, service or inspection of one product’s units, and the stock it keeps out. | id: ID!, legacyResourceId: Int!, number: Int!, reference: String!, title: String!, kind: String!, source: String!, status: String, statusLabel: String, statusId: ID, statusCategory: String!, blocksStock: Boolean!, priority: String!, problem: String, description: String, productId: ID, variantId: ID!, productTitle: String!, variantTitle: String, sku: String, units: [RentalMaintenanceTicketUnit!]!, quantity: Int!, locationId: ID, holdMode: String!, holdStart: String, expectedBack: String, overdue: Boolean!, hold: RentalMaintenanceHold!, assigneeId: ID, assigneeName: String, bookingId: ID, orderId: ID, orderName: String, customerId: ID, mayCharge: Boolean!, chargeDecided: String, costTotal: String!, billableTotal: String!, vendorId: ID, openedAt: String!, closedAt: String, outcome: String, writeOff: RentalMaintenanceWriteOff, actions: [String!]!, createdAt: String, updatedAt: String, events: [RentalMaintenanceEvent!]!, attachments: [RentalMaintenanceAttachment!]!, costs: RentalMaintenanceCosts!, damage: RentalMaintenanceDamage! |
RentalMaintenanceTicketUnitA unit on the ticket: a serial, or a quantity of a product without serials. | unitId: ID, code: String, quantity: Int!, holdState: String |
RentalMaintenanceHoldThe stock the ticket keeps out (its hold). | state: String!, coversNow: Boolean!, start: String, end: String |
RentalMaintenanceWriteOff | at: String, reduceStock: Boolean!, units: Int! |
RentalMaintenanceEventOne line of the ticket’s timeline. | id: ID!, type: String!, text: String!, actor: String, customerVisible: Boolean!, at: String |
RentalMaintenanceAttachmentA photo or file on the ticket (metadata only; the file opens in the app). | id: ID!, name: String!, mime: String!, size: Int!, image: Boolean!, at: String |
RentalMaintenanceCostsThe ticket’s costs (Costs card). | lines: [RentalMaintenanceCostLine!]!, total: String!, billable: String!, currency: String!, labourRate: String, timer: RentalMaintenanceLabourTimer, vendor: RentalMaintenanceVendorCard! |
RentalMaintenanceCostLineA cost line on a ticket: a part, labour, a vendor’s invoice or anything else. Money in the store currency. | id: ID!, legacyResourceId: Int!, kind: String!, description: String!, partId: ID, part: String, vendorId: ID, vendor: String, unitId: ID, quantity: String!, unitCost: String, minutes: Int, rate: String, amount: String!, billable: Boolean!, stockTaken: Int!, invoiceId: ID, date: String |
RentalMaintenanceLabourTimerThe labour timer while it runs. | startedAt: String!, by: String |
RentalMaintenanceVendorCardThe ticket’s vendor card: who repairs it and when it is due back. | vendorId: ID, name: String, ref: String, sent: String, due: String, quote: String, late: Boolean! |
RentalMaintenanceDamageCharging the customer for the damage on a ticket. | enabled: Boolean!, mayCharge: Boolean!, decided: String, canCharge: Boolean!, why: String, orderName: String, amount: String!, billable: String!, currency: String!, waiver: RentalMaintenanceWaiver, charges: [RentalMaintenanceDamageCharge!]! |
RentalMaintenanceWaiverThe damage waiver the rental bought (Custom Fields app). | bought: Boolean!, state: String!, amount: String!, label: String |
RentalMaintenanceDamageChargeA damage charge (DC-<order>-<n>): it takes the late fees’ routes (payment link, counter, deposit). | id: ID!, legacyResourceId: Int!, number: String!, status: String!, amount: String!, currency: String!, route: String, paidVia: String, paidAt: String, noteCustomer: String, createdAt: String |
RentalMaintenanceStatus | id: ID!, key: String, label: String!, category: String!, blocksStock: Boolean!, tone: String |
RentalMaintenanceTechnician | id: ID!, name: String!, openTickets: Int! |
RentalMaintenanceTicketPayload | ticket: RentalMaintenanceTicket, userErrors: [RentalUserError!]! |
Service schedules and checklists #
A service schedule makes a rent variant’s units due for a service every interval, number of rentals, days on rent or meter hours. Schedules and checklists are set up in the app; the API reads them, snoozes a unit’s service, records inspections and imports schedules from the CSV the REST API exports.
| Operation | Arguments | What it does |
|---|---|---|
rentalMaintenanceSchedulesquery · secret key returns [RentalMaintenanceSchedule!]! | variantId: ID | Service schedules with each unit’s state (ok, due_soon, due, overdue or snoozed) and next due date. variantId limits them to one rent variant. |
rentalMaintenanceChecklistsquery · secret key returns [RentalMaintenanceChecklist!]! | variantId: IDmoment: String | The checklists. With variantId only the active ones filled for that product, and with moment only those filled then (manual matches every one). |
snoozeRentalMaintenanceServicemutation · secret key returns RentalMaintenanceServiceUnitPayload! | input: RentalMaintenanceSnoozeInput! | Snooze one unit’s service until a later day (until) and/or for rentals more rentals, or end the snooze with clear: true. id is the unit row from rentalMaintenanceSchedules. |
recordRentalMaintenanceInspectionmutation · secret key returns RentalMaintenanceInspectionPayload! | input: RentalMaintenanceInspectionInput! | Fill a checklist for a unit (the serial is required for a product with serials). A failed item set to open a ticket opens one (source inspection, or checkout at check-out) or joins the unit’s open ticket; with ticketId the inspection belongs to that service ticket. While maintenance is turned off, no new ticket is opened. |
importRentalMaintenanceSchedulesmutation · secret key returns RentalMaintenanceImportPayload! | csv: String!dryRun: Boolean | Import service schedules from CSV, in the columns of the schedules export. Rows match a schedule by product and name. dryRun (the default) checks every row and saves nothing. New schedules come in paused unless the file has an active column. At most 2,000 rows. |
query DueServices {
rentalMaintenanceSchedules(variantId: "gid://shopify/ProductVariant/44001") {
id name interval rentals onDue active
units { id code state trigger nextDue lastDoneAt snoozeUntil ticketId }
}
}
mutation ReturnCheck {
recordRentalMaintenanceInspection(input: {
checklistId: "gid://sirentals/MaintenanceChecklist/2", variantId: "gid://shopify/ProductVariant/44001", serial: "PW-07",
moment: "checkin", bookingId: "gid://sirentals/Booking/42",
answers: [{key: "hose", value: "pass"}, {key: "trigger", value: "fail"}, {key: "hours", value: "212"}]
}) {
inspection { id failed meter ticketId answers { label value failed } }
ticketOpened
failed
userErrors { field code message }
}
}
RentalMaintenanceSnoozeInput
| Field | Type | Notes |
|---|---|---|
id | ID! | gid://sirentals/MaintenanceServiceUnit/… or the number. |
until | String | YYYY-MM-DD, later than today. |
rentals | Int | Snooze for this many more rentals. |
reason | String | |
clear | Boolean | End the snooze. |
RentalMaintenanceInspectionInput
| Field | Type | Notes |
|---|---|---|
checklistId | ID! | gid://sirentals/MaintenanceChecklist/… or the number. |
variantId | ID | gid://shopify/ProductVariant/… (not needed with ticketId). |
unitId | ID | gid://sirentals/SerialNumber/… or use serial. |
serial | String | |
moment | String | checkout, checkin, service or manual (default manual; service with ticketId). |
bookingId | ID | |
ticketId | ID | gid://sirentals/MaintenanceTicket/…: filled during this ticket’s service. |
answers | [RentalMaintenanceAnswerInput!]! |
RentalMaintenanceAnswerInput
| Field | Type | Notes |
|---|---|---|
key | String! | |
value | String | pass or fail, one of a choice item’s options, a number, text, or a photo count. |
skipped | Boolean | |
reason | String | Why a required item was skipped. |
| Type | Fields |
|---|---|
RentalMaintenanceScheduleA service schedule on a rent variant: every interval, rentals, days on rent or meter hours, whichever comes first. | id: ID!, name: String!, variantId: ID!, interval: String, rentals: Int, rentalDays: String, hours: String, dueSoonPercent: String!, onDue: String!, active: Boolean!, units: [RentalMaintenanceServiceUnit!]! |
RentalMaintenanceServiceUnitOne unit’s state for a service schedule (Maintenance › Services); a product without serials has one row for its stock. | id: ID!, unitId: ID, code: String, state: String!, trigger: String, nextDue: String, lastDoneAt: String!, snoozeUntil: String, snoozeUntilRentals: Int, snoozeReason: String, ticketId: ID |
RentalMaintenanceChecklistA checklist filled for a unit at check-out, at check-in, during a service or any time. | id: ID!, name: String!, moments: [String!]!, variantIds: [ID!]!, active: Boolean!, items: [RentalMaintenanceChecklistItem!]! |
RentalMaintenanceChecklistItemOne check on a checklist. | key: String!, label: String!, type: String!, required: Boolean!, options: [String!]!, failValues: [String!]!, onFail: String, unit: String |
RentalMaintenanceServiceUnitPayload | unit: RentalMaintenanceServiceUnit, userErrors: [RentalUserError!]! |
RentalMaintenanceInspectionPayload | inspection: RentalMaintenanceInspection, ticketOpened: Boolean, failed: [String!], userErrors: [RentalUserError!]! |
RentalMaintenanceInspectionA filled-in checklist. | id: ID!, checklistId: ID, checklist: String!, variantId: ID!, unitId: ID, unit: String, bookingId: ID, ticketId: ID, moment: String!, failed: Boolean!, meter: String, answers: [RentalMaintenanceInspectionAnswer!]!, at: String!, by: String |
RentalMaintenanceInspectionAnswer | key: String!, label: String!, type: String!, value: String, failed: Boolean, skipped: Boolean, reason: String |
RentalMaintenanceImportPayload | dryRun: Boolean, summary: RentalMaintenanceImportSummary, rows: [RentalMaintenanceImportRow!], unknownColumns: [String!], userErrors: [RentalUserError!]! |
RentalMaintenanceImportSummary | rows: Int!, created: Int!, updated: Int!, unchanged: Int!, refused: Int! |
RentalMaintenanceImportRowOne row of a CSV import. | line: Int!, action: String!, name: String!, errors: [String!]! |
Costs, parts and vendors #
A ticket’s costs: parts, labour, a vendor’s invoice or anything else. Every cost mutation answers the ticket’s whole costs, so the totals are always current. The parts list and the vendors are the store’s own lists, used on cost lines.
| Operation | Arguments | What it does |
|---|---|---|
addRentalMaintenanceTicketCostmutation · secret key returns RentalMaintenanceCostsPayload! | input: RentalMaintenanceCostInput! | Add a cost line. A part is quantity × unit cost (a part of the parts list starts at its unit cost, and a counted part’s stock goes down by whole parts); labour is minutes (or hours) × the hourly rate (the labour rate in Settings › Maintenance unless you send rate); vendor and other lines take an amount. billable defaults to the ticket’s Customer may be charged. Lines can be added to a closed ticket; at most 200 per ticket. A vendor’s invoice file is added in the app. |
updateRentalMaintenanceTicketCostmutation · secret key returns RentalMaintenanceCostsPayload! | input: RentalMaintenanceCostUpdateInput! | Change a cost line; only the fields you send change. |
removeRentalMaintenanceTicketCostmutation · secret key returns RentalMaintenanceCostsPayload! | ticketId: ID!lineId: ID! | Remove a cost line; a counted part goes back in stock. |
runRentalMaintenanceLabourTimermutation · secret key returns RentalMaintenanceCostsPayload! | ticketId: ID!action: RentalMaintenanceTimerAction! | Start or stop the labour timer (one per ticket). STOP adds a labour line of the whole minutes it ran. Refused with timer_running, timer_stopped, or ticket_closed when starting it on a closed ticket. |
setRentalMaintenanceTicketVendormutation · secret key returns RentalMaintenanceCostsPayload! | input: RentalMaintenanceVendorCardInput! | The ticket’s vendor card: the vendor, their reference, the days it was sent and is due back, and the quote. Only the fields you send change; vendorId: null clears the vendor. |
rentalMaintenancePartsquery · secret key returns [RentalMaintenancePart!]! | query: StringincludeHidden: Boolean | The parts list by name. query searches the name and SKU; includeHidden adds the hidden parts. |
saveRentalMaintenancePartmutation · secret key returns RentalMaintenancePartPayload! | input: RentalMaintenancePartInput! | Create a part (no id) or change one. stock: null means the part isn’t counted. At most 2,000 parts. |
removeRentalMaintenancePartmutation · secret key returns RentalMaintenanceRemovePayload! | id: ID! | Remove a part: deleted, or hidden (hidden: true) when a cost line used it. |
importRentalMaintenancePartsmutation · secret key returns RentalMaintenanceImportPayload! | csv: String!dryRun: Boolean | Import parts from CSV, in the columns of the parts export (name, sku, unit_cost, vendor, stock, active). Rows match a part by SKU, or by name when the row has no SKU; a vendor the list doesn’t have is added. dryRun (the default) checks every row and saves nothing. At most 2,000 rows. |
rentalMaintenanceVendorsquery · secret key returns [RentalMaintenanceVendor!]! | includeHidden: Boolean | The vendors by name; includeHidden adds the hidden ones. |
saveRentalMaintenanceVendormutation · secret key returns RentalMaintenanceVendorPayload! | input: RentalMaintenanceVendorInput! | Create a vendor (no id) or change one. At most 2,000 vendors. |
removeRentalMaintenanceVendormutation · secret key returns RentalMaintenanceRemovePayload! | id: ID! | Remove a vendor: deleted, or hidden (hidden: true) when a ticket, part or cost line uses it. |
mutation AddLabour {
addRentalMaintenanceTicketCost(input: {ticketId: "gid://sirentals/MaintenanceTicket/17", kind: "labour", minutes: 50}) {
lineId
costs { total billable currency labourRate lines { id kind description quantity unitCost amount billable } }
userErrors { field code message }
}
}
query Parts {
rentalMaintenanceParts(query: "trigger") { id name sku unitCost vendor stock low active }
}
RentalMaintenanceCostInput
| Field | Type | Notes |
|---|---|---|
ticketId | ID! | |
kind | String! | part, labour, vendor or other. |
partId | ID | A part of the parts list (its unit cost by default). |
vendorId | ID | |
unitId | ID | gid://sirentals/SerialNumber/…: a unit on the ticket. |
description | String | |
quantity | String | |
unitCost | String | |
minutes | Int | Labour: minutes (or hours). |
hours | String | |
rate | String | Labour: hourly rate (default: the labour rate). |
amount | String | Vendor and other lines. |
billable | Boolean | Default: the ticket’s Customer may be charged. |
RentalMaintenanceCostUpdateInput
| Field | Type | Notes |
|---|---|---|
ticketId | ID! | |
lineId | ID! | gid://sirentals/MaintenanceCost/… or the number. |
vendorId | ID | |
unitId | ID | |
description | String | |
quantity | String | |
unitCost | String | |
minutes | Int | |
hours | String | |
rate | String | |
amount | String | |
billable | Boolean |
RentalMaintenanceVendorCardInput
| Field | Type | Notes |
|---|---|---|
ticketId | ID! | |
vendorId | ID | null clears it. |
ref | String | |
sent | String | YYYY-MM-DD |
due | String | |
quote | String |
RentalMaintenancePartInput
| Field | Type | Notes |
|---|---|---|
id | ID | Change this part (none: a new part). |
name | String | |
sku | String | |
unitCost | String | |
vendorId | ID | |
stock | Int | null: not counted. |
active | Boolean |
RentalMaintenanceVendorInput
| Field | Type | Notes |
|---|---|---|
id | ID | Change this vendor (none: a new vendor). |
name | String | |
contact | String | |
email | String | |
phone | String | |
notes | String | |
active | Boolean |
| Enum | Values |
|---|---|
RentalMaintenanceTimerAction | STARTSTOP – Adds a labour line of the minutes it ran. |
| Type | Fields |
|---|---|
RentalMaintenanceCostsPayload | lineId: ID, costs: RentalMaintenanceCosts, userErrors: [RentalUserError!]! |
RentalMaintenancePartA part of the parts list. | id: ID!, legacyResourceId: Int!, name: String!, sku: String, unitCost: String!, vendorId: ID, vendor: String, stock: Int, low: Boolean!, active: Boolean! |
RentalMaintenancePartPayload | part: RentalMaintenancePart, userErrors: [RentalUserError!]! |
RentalMaintenanceRemovePayload | hidden: Boolean, deleted: Boolean, userErrors: [RentalUserError!]! |
RentalMaintenanceVendorA vendor (repair shop, supplier). | id: ID!, legacyResourceId: Int!, name: String!, contact: String, email: String, phone: String, notes: String, active: Boolean! |
RentalMaintenanceVendorPayload | vendor: RentalMaintenanceVendor, userErrors: [RentalUserError!]! |
Damage charges #
When Settings › Maintenance has damage charges on, a ticket linked to a rental can charge the customer for the damage: a damage charge (DC-<order number>-<n>) on the rental’s order, collected by the payment link, at the counter or from the security deposit. One open charge per ticket. A charge has the fields of a late fee (see GraphQL API reference: Late fees). The ticket’s damage says whether a charge can be made now and what it starts at (the billable costs, or 0 when the rental bought the damage waiver).
| Operation | Arguments | What it does |
|---|---|---|
chargeRentalMaintenanceDamagemutation · secret key returns RentalMaintenanceChargePayload! | input: RentalMaintenanceChargeInput! | Charge the customer for the damage: a damage charge (DC-…) on the rental’s order, To review, then collected by route (the default review only creates it). When collecting fails, the charge stays To review and collectError says why. Refused with charges_off, no_rental or charge_open (one open charge per ticket). |
declineRentalMaintenanceDamageChargemutation · secret key returns RentalMaintenanceTicketPayload! | ticketId: ID!reason: String | Decide not to charge: the ticket records No charge, so the security deposit no longer waits. charge_open while a charge is open: waive it first. |
collectRentalMaintenanceDamageChargemutation · secret key returns RentalMaintenanceChargePayload! | input: RentalMaintenanceChargeCollectInput! | Collect a damage charge waiting for review, as Accept does for a late fee: route auto (the store’s ways to collect, the default), link, counter (with method) or deposit. not_reviewable when it isn’t To review. |
waiveRentalMaintenanceDamageChargemutation · secret key returns RentalMaintenanceChargePayload! | chargeId: ID!reason: String | Waive a damage charge. A reason is required (reason_required); a paid charge can’t be waived (paid). |
query DamageState {
rentalMaintenanceTicket(id: "gid://sirentals/MaintenanceTicket/17") {
reference mayCharge chargeDecided costTotal billableTotal
damage {
enabled canCharge why orderName amount currency
waiver { bought state amount }
charges { id number status amount currency paidVia paidAt }
}
}
}
mutation ChargeDamage {
chargeRentalMaintenanceDamage(input: {
ticketId: "gid://sirentals/MaintenanceTicket/17", amount: "86.50", noteCustomer: "Replacement trigger and labour", route: "link"
}) {
charge { id number status amount currency }
collectError { code message }
userErrors { field code message }
}
}
RentalMaintenanceChargeInput
| Field | Type | Notes |
|---|---|---|
ticketId | ID! | |
amount | String! | Store currency, before tax. |
noteCustomer | String | Shown to the customer (email, invoice). |
reasonStaff | String | |
route | String | review (default: only create it, To review), auto (Settings), link, counter or deposit. |
method | String | counter: cash, terminal, bank or other. |
to | String | link: the email to send it to (default the customer’s). |
RentalMaintenanceChargeCollectInput
| Field | Type | Notes |
|---|---|---|
chargeId | ID! | gid://sirentals/LateFee/… or the number. |
route | String | auto (default: Settings), link, counter or deposit. |
method | String | |
to | String |
| Type | Fields |
|---|---|
RentalMaintenanceChargePayload | charge: RentalMaintenanceDamageCharge, ticket: RentalMaintenanceTicket, collectError: RentalUserError, userErrors: [RentalUserError!]! |
Reports and the dashboard #
The five reports of the Maintenance › Reports page and the board’s top row. Each report fills its own row fields; the fields of each report are listed on the REST page.
| Operation | Arguments | What it does |
|---|---|---|
rentalMaintenanceReportquery · secret key returns RentalMaintenanceReport! | type: RentalMaintenanceReportType!from: Stringto: StringvariantId: IDlocationId: IDkind: String | One of the five reports: cost, downtime, utilisation, compliance or problems. from and to are days (YYYY-MM-DD, store time); the default is this month up to today, and at most 366 days are read. Filter by variantId, locationId and kind. |
rentalMaintenanceDashboardquery · secret key returns RentalMaintenanceDashboard! | – | The Maintenance board’s top row: units down, back today, overdue, open, waiting, services due soon, due and overdue, and this month’s downtime and cost. |
query OctoberCost {
rentalMaintenanceReport(type: COST, from: "2026-10-01", to: "2026-10-31") {
from to currency
rows { variantId product part labour vendor other total billable revenue percent tickets }
totals { total billable revenue percent }
}
}
query Board {
rentalMaintenanceDashboard {
down backToday overdue open waiting servicesDueSoon servicesDue servicesOverdue downtimeDays downtimePercent cost currency
}
}
| Enum | Values |
|---|---|
RentalMaintenanceReportType | COST – Maintenance cost per product and unit, against its rental revenue.DOWNTIME – Days each unit was out of stock for maintenance, failures, mean time to repair, rentals between failures.UTILISATION – Per product: days blocked and days rented against the stock’s days, and the days it fell short.COMPLIANCE – Per service schedule: done on time, late, overdue now.PROBLEMS – Tickets per product and problem type. |
| Type | Fields |
|---|---|
RentalMaintenanceReport | type: RentalMaintenanceReportType!, from: String!, to: String!, currency: String!, rows: [RentalMaintenanceReportRow!]!, totals: RentalMaintenanceReportRow!, top: [RentalMaintenanceReportRow!] |
RentalMaintenanceReportRowOne row of a maintenance report; each report fills its own fields. Money in the store currency. | variantId: ID, product: String, unitId: ID, serial: String, scheduleId: ID, schedule: String, problem: String, part: String, labour: String, vendor: String, other: String, total: String, billable: String, revenue: String, tickets: Int, percent: Float, days: Float, failures: Int, mttr: Float, rentals: Int, between: Float, stock: Int, stockDays: Int, blocked: Float, blockedPct: Float, rented: Int, rentedPct: Float, shortage: Int, done: Int, onTime: Int, late: Int, overdue: Int, share: Float, serials: [RentalMaintenanceReportRow!] |
RentalMaintenanceDashboardThe Maintenance board’s top row. | down: Int!, backToday: Int!, overdue: Int!, open: Int!, waiting: Int!, servicesDueSoon: Int!, servicesDue: Int!, servicesOverdue: Int!, downtimeDays: Float!, downtimePercent: Float, cost: String!, currency: String! |
