View Categories

Launching soon on the Shopify App StoreJoin the waitlist

GraphQL API reference: Maintenance

17 min read

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), SerialNumber and Booking; products, variants, locations, orders and customers are Shopify gids. Every id argument also takes the bare number, and legacyResourceId gives it. A status id (statusId) is the number from rentalMaintenanceStatuses.
  • kind, priority, holdMode, outcome, moment and route are 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) are Y-m-d H:i in the store’s time zone (expectedBack may be a day); createdAt and updatedAt are 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_found and 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.

OperationArgumentsWhat it does
rentalMaintenanceTickets
query · secret key
returns RentalMaintenanceTicketConnection!
first: Int
after: String
last: Int
before: String
status: RentalMaintenanceTicketFilter
query: String
variantId: ID
productId: ID
serial: String
bookingId: ID
ticketStatus: String
priority: String
updatedSince: 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.
rentalMaintenanceTicket
query · secret key
returns RentalMaintenanceTicket
id: ID!One ticket with its timeline (events), its files (attachments, metadata only), costs and damage, or null.
rentalMaintenanceStatuses
query · 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.
rentalMaintenanceTechnicians
query · secret key
returns [RentalMaintenanceTechnician!]!
–Who tickets can be assigned to, the least busy first: id, name and open tickets. Never an email address.
sendRentalUnitToMaintenance
mutation · 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).
updateRentalMaintenanceTicket
mutation · 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.
changeRentalMaintenanceTicketStatus
mutation · 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).
addRentalMaintenanceTicketComment
mutation · secret key
returns RentalMaintenanceTicketPayload!
ticketId: ID!
text: String!
Add a comment to the ticket’s timeline.
assignRentalMaintenanceTicket
mutation · 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

FieldTypeNotes
variantIdID!gid://shopify/ProductVariant/… or the number: a rent variant.
units[String!]Serial numbers (or unit ids) of a product that tracks serials.
quantityIntUnits (a product without serials).
kindStringrepair (default), service or inspection.
priorityStringlow, normal (default), high or urgent.
titleStringDefault: the problem, else the kind.
descriptionString
problemString
locationIdID
holdModeStringblock or none (default: Settings › Maintenance).
startStringY-m-d H:i, store time (default now). A past start needs confirmBackdate.
expectedBackStringY-m-d or Y-m-d H:i; null = until done.
confirmBackdateBoolean
bookingIdIDLink the rental it came back from: its order and customer come with it.
mayChargeBoolean
technicianIdIDAssign it to a technician from rentalMaintenanceTechnicians (they get an email).

RentalMaintenanceTicketUpdateInput

FieldTypeNotes
ticketIdID!
titleString
descriptionString
kindString
priorityString
startString
expectedBackString
holdModeString
locationIdID
confirmBackdateBoolean
mayChargeBooleanCustomer may be charged (the security deposit is held until you decide).

RentalMaintenanceTicketStatusInput

FieldTypeNotes
ticketIdID!
actionRentalMaintenanceAction!
noteString
outcomeStringREADY: fixed, no_fault or replaced (default fixed).
reduceStockBooleanWRITE_OFF: take the units out of stock for good.
confirmBooleanWRITE_OFF: go ahead although bookings would be left short.
statusIdIDMOVE: the status to move to (an id from rentalMaintenanceStatuses).
EnumValues
RentalMaintenanceTicketFilterOPEN – 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
RentalMaintenanceActionCONFIRM – A reported ticket becomes New (its hold starts).
START
READY – Ready to rent: closes the ticket and frees the stock.
WAIT_PARTS
SEND_VENDOR
RESUME
BACK_FROM_VENDOR
WRITE_OFF – Closes the ticket; reduceStock also takes the units out of stock for good.
CANCEL
REOPEN
MOVE – To one of the store’s own open or waiting statuses (statusId, from rentalMaintenanceStatuses).
TypeFields
RentalMaintenanceTicket
A 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!
RentalMaintenanceTicketUnit
A unit on the ticket: a serial, or a quantity of a product without serials.
unitId: ID, code: String, quantity: Int!, holdState: String
RentalMaintenanceHold
The stock the ticket keeps out (its hold).
state: String!, coversNow: Boolean!, start: String, end: String
RentalMaintenanceWriteOffat: String, reduceStock: Boolean!, units: Int!
RentalMaintenanceEvent
One line of the ticket’s timeline.
id: ID!, type: String!, text: String!, actor: String, customerVisible: Boolean!, at: String
RentalMaintenanceAttachment
A 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
RentalMaintenanceCosts
The ticket’s costs (Costs card).
lines: [RentalMaintenanceCostLine!]!, total: String!, billable: String!, currency: String!, labourRate: String, timer: RentalMaintenanceLabourTimer, vendor: RentalMaintenanceVendorCard!
RentalMaintenanceCostLine
A 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
RentalMaintenanceLabourTimer
The labour timer while it runs.
startedAt: String!, by: String
RentalMaintenanceVendorCard
The 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!
RentalMaintenanceDamage
Charging 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!]!
RentalMaintenanceWaiver
The damage waiver the rental bought (Custom Fields app).
bought: Boolean!, state: String!, amount: String!, label: String
RentalMaintenanceDamageCharge
A 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
RentalMaintenanceStatusid: ID!, key: String, label: String!, category: String!, blocksStock: Boolean!, tone: String
RentalMaintenanceTechnicianid: ID!, name: String!, openTickets: Int!
RentalMaintenanceTicketPayloadticket: 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.

OperationArgumentsWhat it does
rentalMaintenanceSchedules
query · secret key
returns [RentalMaintenanceSchedule!]!
variantId: IDService schedules with each unit’s state (ok, due_soon, due, overdue or snoozed) and next due date. variantId limits them to one rent variant.
rentalMaintenanceChecklists
query · secret key
returns [RentalMaintenanceChecklist!]!
variantId: ID
moment: String
The checklists. With variantId only the active ones filled for that product, and with moment only those filled then (manual matches every one).
snoozeRentalMaintenanceService
mutation · 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.
recordRentalMaintenanceInspection
mutation · 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.
importRentalMaintenanceSchedules
mutation · 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

FieldTypeNotes
idID!gid://sirentals/MaintenanceServiceUnit/… or the number.
untilStringYYYY-MM-DD, later than today.
rentalsIntSnooze for this many more rentals.
reasonString
clearBooleanEnd the snooze.

RentalMaintenanceInspectionInput

FieldTypeNotes
checklistIdID!gid://sirentals/MaintenanceChecklist/… or the number.
variantIdIDgid://shopify/ProductVariant/… (not needed with ticketId).
unitIdIDgid://sirentals/SerialNumber/… or use serial.
serialString
momentStringcheckout, checkin, service or manual (default manual; service with ticketId).
bookingIdID
ticketIdIDgid://sirentals/MaintenanceTicket/…: filled during this ticket’s service.
answers[RentalMaintenanceAnswerInput!]!

RentalMaintenanceAnswerInput

FieldTypeNotes
keyString!
valueStringpass or fail, one of a choice item’s options, a number, text, or a photo count.
skippedBoolean
reasonStringWhy a required item was skipped.
TypeFields
RentalMaintenanceSchedule
A 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!]!
RentalMaintenanceServiceUnit
One 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
RentalMaintenanceChecklist
A 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!]!
RentalMaintenanceChecklistItem
One check on a checklist.
key: String!, label: String!, type: String!, required: Boolean!, options: [String!]!, failValues: [String!]!, onFail: String, unit: String
RentalMaintenanceServiceUnitPayloadunit: RentalMaintenanceServiceUnit, userErrors: [RentalUserError!]!
RentalMaintenanceInspectionPayloadinspection: RentalMaintenanceInspection, ticketOpened: Boolean, failed: [String!], userErrors: [RentalUserError!]!
RentalMaintenanceInspection
A 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
RentalMaintenanceInspectionAnswerkey: String!, label: String!, type: String!, value: String, failed: Boolean, skipped: Boolean, reason: String
RentalMaintenanceImportPayloaddryRun: Boolean, summary: RentalMaintenanceImportSummary, rows: [RentalMaintenanceImportRow!], unknownColumns: [String!], userErrors: [RentalUserError!]!
RentalMaintenanceImportSummaryrows: Int!, created: Int!, updated: Int!, unchanged: Int!, refused: Int!
RentalMaintenanceImportRow
One 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.

OperationArgumentsWhat it does
addRentalMaintenanceTicketCost
mutation · 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.
updateRentalMaintenanceTicketCost
mutation · secret key
returns RentalMaintenanceCostsPayload!
input: RentalMaintenanceCostUpdateInput!Change a cost line; only the fields you send change.
removeRentalMaintenanceTicketCost
mutation · secret key
returns RentalMaintenanceCostsPayload!
ticketId: ID!
lineId: ID!
Remove a cost line; a counted part goes back in stock.
runRentalMaintenanceLabourTimer
mutation · 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.
setRentalMaintenanceTicketVendor
mutation · 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.
rentalMaintenanceParts
query · secret key
returns [RentalMaintenancePart!]!
query: String
includeHidden: Boolean
The parts list by name. query searches the name and SKU; includeHidden adds the hidden parts.
saveRentalMaintenancePart
mutation · 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.
removeRentalMaintenancePart
mutation · secret key
returns RentalMaintenanceRemovePayload!
id: ID!Remove a part: deleted, or hidden (hidden: true) when a cost line used it.
importRentalMaintenanceParts
mutation · 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.
rentalMaintenanceVendors
query · secret key
returns [RentalMaintenanceVendor!]!
includeHidden: BooleanThe vendors by name; includeHidden adds the hidden ones.
saveRentalMaintenanceVendor
mutation · secret key
returns RentalMaintenanceVendorPayload!
input: RentalMaintenanceVendorInput!Create a vendor (no id) or change one. At most 2,000 vendors.
removeRentalMaintenanceVendor
mutation · 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

FieldTypeNotes
ticketIdID!
kindString!part, labour, vendor or other.
partIdIDA part of the parts list (its unit cost by default).
vendorIdID
unitIdIDgid://sirentals/SerialNumber/…: a unit on the ticket.
descriptionString
quantityString
unitCostString
minutesIntLabour: minutes (or hours).
hoursString
rateStringLabour: hourly rate (default: the labour rate).
amountStringVendor and other lines.
billableBooleanDefault: the ticket’s Customer may be charged.

RentalMaintenanceCostUpdateInput

FieldTypeNotes
ticketIdID!
lineIdID!gid://sirentals/MaintenanceCost/… or the number.
vendorIdID
unitIdID
descriptionString
quantityString
unitCostString
minutesInt
hoursString
rateString
amountString
billableBoolean

RentalMaintenanceVendorCardInput

FieldTypeNotes
ticketIdID!
vendorIdIDnull clears it.
refString
sentStringYYYY-MM-DD
dueString
quoteString

RentalMaintenancePartInput

FieldTypeNotes
idIDChange this part (none: a new part).
nameString
skuString
unitCostString
vendorIdID
stockIntnull: not counted.
activeBoolean

RentalMaintenanceVendorInput

FieldTypeNotes
idIDChange this vendor (none: a new vendor).
nameString
contactString
emailString
phoneString
notesString
activeBoolean
EnumValues
RentalMaintenanceTimerActionSTART
STOP – Adds a labour line of the minutes it ran.
TypeFields
RentalMaintenanceCostsPayloadlineId: ID, costs: RentalMaintenanceCosts, userErrors: [RentalUserError!]!
RentalMaintenancePart
A 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!
RentalMaintenancePartPayloadpart: RentalMaintenancePart, userErrors: [RentalUserError!]!
RentalMaintenanceRemovePayloadhidden: Boolean, deleted: Boolean, userErrors: [RentalUserError!]!
RentalMaintenanceVendor
A vendor (repair shop, supplier).
id: ID!, legacyResourceId: Int!, name: String!, contact: String, email: String, phone: String, notes: String, active: Boolean!
RentalMaintenanceVendorPayloadvendor: 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).

OperationArgumentsWhat it does
chargeRentalMaintenanceDamage
mutation · 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).
declineRentalMaintenanceDamageCharge
mutation · 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.
collectRentalMaintenanceDamageCharge
mutation · 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.
waiveRentalMaintenanceDamageCharge
mutation · 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

FieldTypeNotes
ticketIdID!
amountString!Store currency, before tax.
noteCustomerStringShown to the customer (email, invoice).
reasonStaffString
routeStringreview (default: only create it, To review), auto (Settings), link, counter or deposit.
methodStringcounter: cash, terminal, bank or other.
toStringlink: the email to send it to (default the customer’s).

RentalMaintenanceChargeCollectInput

FieldTypeNotes
chargeIdID!gid://sirentals/LateFee/… or the number.
routeStringauto (default: Settings), link, counter or deposit.
methodString
toString
TypeFields
RentalMaintenanceChargePayloadcharge: 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.

OperationArgumentsWhat it does
rentalMaintenanceReport
query · secret key
returns RentalMaintenanceReport!
type: RentalMaintenanceReportType!
from: String
to: String
variantId: ID
locationId: ID
kind: 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.
rentalMaintenanceDashboard
query · 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
  }
}
EnumValues
RentalMaintenanceReportTypeCOST – 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.
TypeFields
RentalMaintenanceReporttype: RentalMaintenanceReportType!, from: String!, to: String!, currency: String!, rows: [RentalMaintenanceReportRow!]!, totals: RentalMaintenanceReportRow!, top: [RentalMaintenanceReportRow!]
RentalMaintenanceReportRow
One 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!]
RentalMaintenanceDashboard
The 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!