View Categories

Launching soon on the Shopify App StoreJoin the waitlist

GraphQL API reference: Staff & resources

18 min read

The staff & resources operations of the Rentals & Bookings GraphQL API: staff members and their skills, hours and time off; resources such as boats, vehicles and rooms; the jobs they are given (bookings that need staff, departures, maintenance tickets and your own custom jobs); assignments, who is free, conflicts and the scheduled hours for payroll. 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 same operations are in REST, with every field explained: REST API reference: Staff & resources.

Needs the Rentals & Bookings app. Every operation needs a secret key; mutations need Allow changes (write). The Free plan’s API can read only: a mutation is refused with plan_required.

  • Ids are global: gid://sirentals/Staff/7, gid://sirentals/Resource/3, gid://sirentals/StaffAssignment/120, gid://sirentals/ScheduleBlock/31 (a time off or blocked time). Every id argument also takes the bare number, and legacyResourceId gives it. Locations, products and variants are Shopify’s (gid://shopify/Location/801, Product, ProductVariant), Shopify logins gid://shopify/StaffMember/โ€ฆ; each also takes the number.
  • A job is named by its type and its jobId: booking (the booking id), departure (the departure id, see GraphQL API reference: Departures), maintenance_ticket (the ticket id) or custom (a 26-character id). Only custom jobs are made, changed and cancelled here; the others follow their booking, departure or ticket. Job types explains them.
  • Times are the store’s wall clock, Y-m-d H:i; a date alone is that day (as an end, to the end of the day). Ranges without from and to cover today and the next 13 days, at most 92 days.
  • Jobs never carry a customer’s name or email: only the order name and ids.
  • Mutations answer userErrors { field message code data } when a change is refused: invalid_param, not_found, conflict (the conflicts in data.conflicts), already_assigned, job_cancelled, not_editable, not_live, duplicate, too_many. The REST errors table explains each. rentalStaffMember, rentalResource and rentalStaffJob answer null for an id that doesn’t exist; the other queries answer errors[].extensions.code: "not_found" for a staff member, resource or job that doesn’t exist.
curl -s "https://YOUR-API-ADDRESS/graphql/2026-10" -H "Authorization: Bearer sirb_your_secret_key" -H "Content-Type: application/json" \
  -d '{"query": "{ rentalStaffMembers(first: 20, skill: \"guide\") { totalCount nodes { id name status skills { code level expiresOn } } } }"}'

Staff members and skills #

Staff members are the people jobs are given to; skills are what they can do (guide, driver, captain โ€ฆ), each held at a level from 1 to 3, with a valid-until date for a skill that expires (a licence or certificate). Archiving a staff member cancels their assignments that haven’t ended.

OperationArgumentsWhat it does
rentalStaffMembers
query ยท secret key
returns RentalStaffMemberConnection!
first: Int
after: String
last: Int
before: String
status: RentalStaffStatusFilter
query: String
skill: String
locationId: ID
The store’s staff members, by name. status defaults to ACTIVE; query searches name, email and phone; skill is a skill code; locationId keeps the people who work there or anywhere.
rentalStaffMember
query ยท secret key
returns RentalStaffMember
id: ID!One staff member with their weekly hours and their time off from today on, or null.
createRentalStaffMember
mutation ยท secret key
returns RentalStaffMemberPayload!
input: RentalStaffMemberInput!Add a staff member. A name and an email or a phone number are needed; everything else is optional.
updateRentalStaffMember
mutation ยท secret key
returns RentalStaffMemberPayload!
id: ID!
input: RentalStaffMemberInput!
Change a staff member. Only the fields you send change; skills and hours replace their lists. Setting status to active brings an archived person back.
archiveRentalStaffMember
mutation ยท secret key
returns RentalStaffMemberPayload!
id: ID!Remove (archive) a staff member: their assignments that haven’t ended are cancelled, past ones stay.
addRentalStaffTimeOff
mutation ยท secret key
returns RentalStaffMemberPayload!
staffId: ID!
input: RentalScheduleBlockInput!
Add time off (kind: "time_off", the default) or an extra shift (kind: "extra"). Answers the staff member.
removeRentalStaffTimeOff
mutation ยท secret key
returns RentalStaffMemberPayload!
staffId: ID!
blockId: ID!
Delete a time off or extra shift. Answers the staff member.
rentalStaffSkills
query ยท secret key
returns [RentalStaffSkill!]!
includeArchived: BooleanThe store’s skills with how many active staff hold each. A store starts with guide, driver, technician, captain and instructor. includeArchived: true adds the archived ones.
saveRentalStaffSkill
mutation ยท secret key
returns RentalStaffSkillPayload!
code: String
input: RentalStaffSkillInput!
Add a skill (leave out code; the code is made from the label) or change one. duplicate when an active skill already has that name.
archiveRentalStaffSkill
mutation ยท secret key
returns RentalStaffSkillPayload!
code: String!Archive a skill: the staff who hold it keep it, but it is no longer offered.
query Guides {
  rentalStaffMembers(first: 20, skill: "guide", locationId: "gid://shopify/Location/801") {
    totalCount
    pageInfo { hasNextPage endCursor }
    nodes {
      id legacyResourceId name email phone status colour homeLocationId locationIds hoursMode dailyMaxMinutes
      notify { email sms daySheet }
      skills { code level expiresOn expired }
    }
  }
}
mutation AddStaffMember {
  createRentalStaffMember(input: {
    name: "Sam Patel", email: "[email protected]", homeLocationId: "gid://shopify/Location/801",
    hours: [{weekday: 6, from: "08:00", to: "16:00"}, {weekday: 7, from: "08:00", to: "16:00"}],
    skills: [{code: "guide"}, {code: "captain", expiresOn: "2027-06-30"}],
    notify: {daySheet: true}
  }) {
    staffMember { id legacyResourceId name hoursMode hours { weekday from to } skills { code expiresOn } }
    userErrors { field code message }
  }
}
mutation Holiday {
  addRentalStaffTimeOff(staffId: "gid://sirentals/Staff/7", input: {start: "2026-12-24", end: "2026-12-26", reason: "Holiday"}) {
    staffMember { id timeOff { id kind start end reason } }      # end "2026-12-27 00:00": to the end of the 26th
    userErrors { field code message }
  }
}
query Skills {
  rentalStaffSkills { code label expires archived holders }
}
mutation AddSkill {
  saveRentalStaffSkill(input: {label: "Lead guide"}) {       # code "lead-guide"; duplicate when it already exists
    skill { code label expires }
    userErrors { field code message }
  }
}

RentalStaffMemberInput โ€“ A staff member: only name and an email or a phone are needed. On update only the fields sent change; skills and hours replace their lists.

FieldTypeNotes
nameStringUp to 120 characters; needed to create.
emailStringAn email or a phone number is needed to create.
phoneStringStored in international format (+16145550123).
statusStringactive or inactive.
colourStringTheir colour on the schedule, #RRGGBB.
homeLocationIdIDA Shopify location (gid or number).
locationIds[ID!]Other locations they also work at.
hoursModeStringopening (the store’s opening hours) or own (hours). Sending hours sets own.
hours[RentalStaffHoursInput!]Their own weekly hours, at most 21 rows; replaces the list.
dailyMaxMinutesIntMost minutes a day, 1-1440: a soft limit (a warning, never a refusal).
notifyRentalStaffNotifyInput
notesStringUp to 5000 characters.
skills[RentalStaffHeldSkillInput!]Replaces the list.
staffUserIdIDThe Shopify staff member who uses the app as them (gid://shopify/StaffMember/โ€ฆ or the number).
posStaffMemberIdIDTheir Shopify POS staff member (gid://shopify/StaffMember/โ€ฆ or the number).

RentalStaffHoursInput

FieldTypeNotes
weekdayInt!1 = Monday โ€ฆ 7 = Sunday.
fromString!HH:MM
toString!HH:MM; at or before from = past midnight.
locationIdIDA Shopify location (gid or number); null = any.

RentalStaffNotifyInput

FieldTypeNotes
emailBooleanEmail them about new and changed jobs and jobs they are taken off (default true).
smsBooleanText them about new and changed jobs and jobs they are taken off (default false).
daySheetBooleanAn email at 7:00 with the day’s jobs, when email is on (default false).

RentalStaffHeldSkillInput

FieldTypeNotes
codeString!One of the store’s skill codes.
levelInt1-3; leave it out for any level.
expiresOnStringY-m-d; needed for a skill that expires.

RentalScheduleBlockInput

FieldTypeNotes
startString!Y-m-d or Y-m-d H:i.
endStringY-m-d or Y-m-d H:i. A date alone runs to the end of that day; leave it out for a whole day when start is a date alone.
kindStringtime_off (default) or extra, for staff. A resource’s block is always blocked.
reasonStringUp to 200 characters.

RentalStaffSkillInput

FieldTypeNotes
labelStringUp to 80 characters. A new skill’s code is made from it (lower case, dashes).
expiresBooleanA licence or certificate: each holder needs a valid-until date.
EnumValues
RentalStaffStatusFilterACTIVE โ€“ Active (the default).
INACTIVE โ€“ Set to inactive, not removed.
ARCHIVED โ€“ Removed (archived).
ALL
TypeFields
RentalStaffMember
One of the store’s staff members: a person who can be given jobs.
id: ID!, legacyResourceId: Int!, name: String!, email: String, phone: String, status: String!, colour: String!, homeLocationId: ID, locationIds: [ID!]!, hoursMode: String!, hours: [RentalStaffHours!], dailyMaxMinutes: Int, notify: RentalStaffNotify!, notes: String, skills: [RentalStaffHeldSkill!]!, staffUserId: ID, posStaffMemberId: ID, timeOff: [RentalScheduleBlock!], createdAt: String, updatedAt: String
RentalStaffHours
A weekly working-hours row: weekday 1 = Monday โ€ฆ 7 = Sunday; to at or before from = past midnight.
weekday: Int!, from: String!, to: String!, locationId: ID
RentalStaffNotifyemail: Boolean!, sms: Boolean!, daySheet: Boolean!
RentalStaffHeldSkill
A skill a staff member holds.
code: String!, level: Int, expiresOn: String, expired: Boolean!
RentalScheduleBlock
Time off, an extra shift, or a blocked time of a resource.
id: ID!, kind: String!, start: String!, end: String!, reason: String, source: String
RentalStaffMemberPayloadstaffMember: RentalStaffMember, userErrors: [RentalUserError!]!
RentalStaffSkillcode: String!, label: String!, expires: Boolean!, archived: Boolean!, holders: Int
RentalStaffSkillPayloadskill: RentalStaffSkill, userErrors: [RentalUserError!]!

Resources #

Resources are what a job needs besides people: boats, vehicles, rooms, equipment, with the seats they have. A resource can stand for rental stock (stockLink): it can’t be assigned when those units aren’t free. A blocked time (a repair, a private use) keeps it off jobs.

OperationArgumentsWhat it does
rentalResources
query ยท secret key
returns RentalResourceConnection!
first: Int
after: String
last: Int
before: String
status: RentalStaffStatusFilter
query: String
type: String
locationId: ID
The store’s resources (boats, vehicles, rooms, equipment), by name. status defaults to ACTIVE; type is a resource type; locationId keeps the ones at that location or at none.
rentalResource
query ยท secret key
returns RentalResource
id: ID!One resource with its weekly hours and its blocked times from today on, or null.
createRentalResource
mutation ยท secret key
returns RentalResourcePayload!
input: RentalResourceInput!Add a resource. name and type are needed.
updateRentalResource
mutation ยท secret key
returns RentalResourcePayload!
id: ID!
input: RentalResourceInput!
Change a resource. Only the fields you send change; hours replaces the list.
archiveRentalResource
mutation ยท secret key
returns RentalResourcePayload!
id: ID!Remove (archive) a resource: its assignments that haven’t ended are cancelled, past ones stay.
addRentalResourceBlock
mutation ยท secret key
returns RentalResourcePayload!
resourceId: ID!
input: RentalScheduleBlockInput!
Block a resource for a time (a repair, a private use). Answers the resource.
removeRentalResourceBlock
mutation ยท secret key
returns RentalResourcePayload!
resourceId: ID!
blockId: ID!
Delete a blocked time. Answers the resource.
query Boats {
  rentalResources(first: 20, type: "boat") {
    totalCount
    nodes { id legacyResourceId name type seats locationId status colour stockLink { productId variantId units } }
  }
}
mutation AddBoat {
  createRentalResource(input: {
    name: "Pontoon 3", type: "boat", seats: 12, locationId: "801",
    stockLink: {productId: "gid://shopify/Product/88001", units: 1}
  }) {
    resource { id legacyResourceId name seats stockLink { productId units } }
    userErrors { field code message }
  }
}
mutation EngineService {
  addRentalResourceBlock(resourceId: "gid://sirentals/Resource/3", input: {start: "2026-12-10", reason: "Engine service"}) {
    resource { id blocks { id kind start end reason } }
    userErrors { field code message }
  }
}

RentalResourceInput

FieldTypeNotes
nameStringUp to 120 characters; needed to create.
typeStringboat, vehicle, room, equipment or your own word (stored lower case with dashes).
seatsInt0-10000.
locationIdIDOne of your locations (gid or number); null = any.
statusStringactive or inactive.
colourString#RRGGBB
notesStringUp to 5000 characters.
stockLinkRentalResourceStockLinkInputTie the resource to rental stock: it can’t be assigned when those units aren’t free (stock_unavailable). null removes the link.
hours[RentalStaffHoursInput!]Weekly hours, at most 21 rows; replaces the list.

RentalResourceStockLinkInput

FieldTypeNotes
productIdID!A rental product (gid or number).
variantIdIDOne rent variant of it (optional).
unitsIntUnits of that product the resource stands for, 1-1000 (default 1).
TypeFields
RentalResource
A boat, van, room โ€ฆ: something a job needs, with its seats.
id: ID!, legacyResourceId: Int!, name: String!, type: String!, seats: Int!, locationId: ID, status: String!, colour: String!, stockLink: RentalResourceStockLink, notes: String, hours: [RentalStaffHours!], blocks: [RentalScheduleBlock!], createdAt: String, updatedAt: String
RentalResourceStockLinkproductId: ID!, variantId: ID, units: Int!
RentalResourcePayloadresource: RentalResource, userErrors: [RentalUserError!]!

Jobs #

A job’s needs say what it asks for, one row per requirement: count is how many this job needs (a ratio row works it out from the guests or units), assigned the staff or resource ids that fill it, missing how many are still needed, reason unfilled or too_small when something is missing. before and after are the minutes around the job that its assignments also take (set-up, travel, clean-up).

OperationArgumentsWhat it does
rentalStaffJobs
query ยท secret key
returns RentalStaffJobConnection!
first: Int
after: String
last: Int
before: String
from: String
to: String
type: String
status: RentalStaffJobFilter
locationId: ID
Jobs between two days (default: today and the next 13 days, at most 92), soonest first. status defaults to OPEN; type is booking, departure, maintenance_ticket or custom.
rentalStaffJob
query ยท secret key
returns RentalStaffJob
type: String!
id: String!
One job with its needs (how many each asks for, who fills it, what is missing) and its assignments, or null.
createRentalStaffJob
mutation ยท secret key
returns RentalStaffJobPayload!
input: RentalStaffJobInput!Make a custom job: something staff do that isn’t a booking, such as cleaning the boats on Saturday morning. title, start and end are needed.
updateRentalStaffJob
mutation ยท secret key
returns RentalStaffJobPayload!
id: String!
input: RentalStaffJobInput!
Change a custom job (id is its job id). Only the fields you send change; its assignments move with it.
cancelRentalStaffJob
mutation ยท secret key
returns RentalStaffJobPayload!
type: String!
id: String!
reason: String
Cancel a custom job and its assignments. Other jobs follow their booking, departure or ticket: not_editable.
query NextWeek {
  rentalStaffJobs(first: 20, from: "2026-12-05", to: "2026-12-11", type: "booking") {
    totalCount
    pageInfo { hasNextPage endCursor }
    nodes {
      type jobId ref title orderName start end locationId status guests units before after autoAssign missing
      needs { kind skill level type count perGuests perUnits seats seatsTotal mode role assigned missing reason }
    }
  }
}
query OneJob {
  rentalStaffJob(type: "booking", id: "5471") {
    ref title start end missing
    needs { role count assigned missing reason }
    assignments { id subjectType subjectId role start end status source warnings override }
  }
}
mutation CleanTheBoats {
  createRentalStaffJob(input: {
    title: "Clean the boats", start: "2026-12-05 07:00", end: "2026-12-05 08:30", locationId: "801",
    needs: [{kind: "staff", count: 2}], after: "15m"
  }) {
    job { type jobId ref start end after missing needs { role count missing } }
    userErrors { field code message }
  }
}

RentalStaffJobInput โ€“ A custom job (boat cleaning Saturday 8-10, one technician). On update only the fields sent change.

FieldTypeNotes
titleStringUp to 200 characters; needed to create.
startStringY-m-d H:i (a date alone = that day).
endStringY-m-d H:i (a date alone = the end of that day).
locationIdIDOne of your locations (gid or number).
needs[RentalStaffNeedInput!]At most 10 rows; replaces the list.
notesStringUp to 5000 characters.
colourString#RRGGBB
beforeStringMinutes before the job that its assignments also take (set-up, travel): 30, 30m, 1h or 1h30m; 0-1440.
afterStringMinutes after the job that its assignments also take (clean-up); like before.

RentalStaffNeedInput

FieldTypeNotes
kindString!staff or resource.
skillStringA skill code (staff).
levelInt1-3 (staff).
typeStringA resource type (resource).
countIntHow many, 1-100 (default 1).
perGuestsIntOne for every N guests, instead of count.
perUnitsIntOne for every N units, instead of count.
seatsStringSeats the resource needs: party or a number.
seatsTotalBooleantrue: the resources of this need seat the party together.
roleStringA name for the slot (default: the skill, type or kind).
EnumValues
RentalStaffJobFilterOPEN
CANCELLED
ALL
TypeFields
RentalStaffJob
A job staff and resources can be given: a booking whose product needs staff, a departure, a maintenance ticket or a custom job.
type: String!, jobId: String!, ref: String!, title: String, url: String, orderName: String, colour: String, notes: String, start: String!, end: String!, locationId: ID, status: String!, cancelReason: String, guests: Int, units: Int, before: Int!, after: Int!, autoAssign: String, needs: [RentalStaffNeed!]!, missing: Int, assignments: [RentalStaffAssignment!], updatedAt: String
RentalStaffNeed
What a job needs: one requirement row, with how many the job asks for and what fills it.
kind: String!, skill: String, level: Int, type: String, count: Int!, perGuests: Int, perUnits: Int, seats: String, seatsTotal: Boolean, mode: String!, role: String!, assigned: [Int!], missing: Int, reason: String
RentalStaffAssignment
A staff member or resource given a job for a window, in a role.
id: ID!, legacyResourceId: Int!, jobType: String!, jobId: String!, subjectType: String!, subjectId: ID!, role: String, start: String!, end: String!, locationId: ID, status: String!, source: String!, warnings: [String!]!, override: JSON, notes: String, cancelReason: String, job: RentalStaffJob, createdAt: String, updatedAt: String
RentalStaffJobPayloadjob: RentalStaffJob, userErrors: [RentalUserError!]!

Assignments and who is free #

An assignment gives a staff member or resource a job, for the job’s window with its before and after, or a window of its own. Each is checked for conflicts: a hard one (overlap, time_off, blocked, inactive, stock_unavailable) refuses it unless you give forceReason; soft ones (outside_hours, missing_skill, skill_expired, wrong_location, daily_max, too_small) are kept in its warnings. Candidates and conflicts lists every code. A candidate is qualified when it has no conflict at all; only qualified ones are suggested and assigned automatically.

OperationArgumentsWhat it does
rentalFreeStaff
query ยท secret key
returns [RentalStaffCandidate!]!
start: String
end: String
skill: String
level: Int
locationId: ID
jobType: String
jobId: String
includeBusy: Boolean
limit: Int
Staff free for a window, best first, or for a job (jobType + jobId: its window, and its own assignments don’t count as busy). includeBusy: true also lists the busy ones with their conflicts. limit 1-100, default 20.
rentalFreeResources
query ยท secret key
returns [RentalStaffCandidate!]!
start: String
end: String
type: String
minSeats: Int
locationId: ID
jobType: String
jobId: String
includeBusy: Boolean
limit: Int
Resources free for a window or a job, with at least minSeats seats, best first. Same options as rentalFreeStaff.
rentalStaffAssignments
query ยท secret key
returns RentalStaffAssignmentConnection!
first: Int
after: String
last: Int
before: String
from: String
to: String
staffId: ID
resourceId: ID
jobType: String
jobId: String
status: RentalStaffAssignmentFilter
Assignments between two days (default: today and the next 13 days), or every assignment of one job (jobType + jobId). status defaults to LIVE (planned, confirmed and done).
assignRentalStaff
mutation ยท secret key
returns RentalStaffAssignmentPayload!
input: RentalStaffAssignInput!Give a staff member or resource a job. A hard conflict refuses it with conflict and the conflicts in data.conflicts, unless you give forceReason; soft conflicts are kept as warnings.
unassignRentalStaff
mutation ยท secret key
returns RentalStaffAssignmentPayload!
assignmentId: ID!
reason: String
Cancel an assignment. One already cancelled or declined comes back unchanged.
reassignRentalStaff
mutation ยท secret key
returns RentalStaffAssignmentPayload!
assignmentId: ID!
subjectId: ID!
subjectType: String
forceReason: String
Give an assignment’s slot (its role and window) to someone else in one step. The old assignment is cancelled; the new one is checked like assignRentalStaff. not_live when the assignment is no longer active.
autoAssignRentalJob
mutation ยท secret key
returns RentalStaffAutoAssignPayload!
jobType: String!
jobId: String!
commit: Boolean
Fill a job’s missing needs. Without commit it only suggests (nothing is written); commit: true assigns the suggestion, skipping anyone who conflicts.
query WhoIsFree {
  rentalFreeStaff(start: "2026-12-05 09:00", end: "2026-12-05 12:00", skill: "guide", locationId: "801", includeBusy: true) {
    id legacyResourceId name rank qualified hard nextFreeAt
    conflicts { code hard message otherJob start end }
  }
}
mutation AssignAlex {
  assignRentalStaff(input: {jobType: "booking", jobId: "5471", subjectId: "gid://sirentals/Staff/7"}) {
    assignment { id role start end status warnings }
    userErrors { field code message data }
  }
}

When Alex is already on another job then, nothing is written and the payload answers:

{"data": {"assignRentalStaff": {"assignment": null, "userErrors": [{
  "field": ["input", "subjectId"], "code": "conflict",
  "message": "Can't assign: Already on another job then (booking:5480, 2026-12-05 08:00 โ€“ 2026-12-05 11:00). Assign anyway with a reason.",
  "data": {"conflicts": [{"code": "overlap", "hard": true,
    "message": "Already on another job then (booking:5480, 2026-12-05 08:00 โ€“ 2026-12-05 11:00)",
    "subjectType": "staff", "subjectId": 7, "job": "booking:5471", "otherJob": "booking:5480",
    "start": "2026-12-05 08:00", "end": "2026-12-05 11:00"}]}}]}}}
mutation AssignAnyway {
  assignRentalStaff(input: {
    jobType: "booking", jobId: "5471", subjectId: "gid://sirentals/Staff/7", forceReason: "Swaps with Sam at 09:00"
  }) {
    assignment { id status warnings override }      # override: {reason, by, at, codes: ["overlap"]}
    userErrors { field code message data }
  }
}
mutation FillTheJob {
  autoAssignRentalJob(jobType: "booking", jobId: "5471") {      # commit: true assigns the matched ids
    suggested { index kind role count missing matched candidates { id name rank } }
    unmet { index role missing reason }
    userErrors { code message }
  }
}
mutation Swap {
  reassignRentalStaff(assignmentId: "gid://sirentals/StaffAssignment/120", subjectId: "gid://sirentals/Staff/9") {
    assignment { id subjectId role start end status }
    userErrors { field code message data }
  }
}

RentalStaffAssignInput

FieldTypeNotes
jobTypeString!booking, departure, maintenance_ticket or custom.
jobIdString!The job’s id (jobId on RentalStaffJob).
subjectIdID!gid://sirentals/Staff/โ€ฆ, gid://sirentals/Resource/โ€ฆ, or a number with subjectType.
subjectTypeStringstaff (default) or resource.
roleStringThe slot it fills, up to 60 characters (default: the role of the need it fills).
needIntThe need it fills (its index).
startStringA window of its own (default: the job’s with its before and after).
endStringWith start: a window of its own.
forceReasonStringAssign through a hard conflict (overlap, time off โ€ฆ): why.
statusStringplanned or confirmed. Default: planned when Settings โ€บ Staff โ€บ “Staff confirm their jobs” is on, confirmed otherwise (resources: confirmed).
notesStringUp to 2000 characters.
EnumValues
RentalStaffAssignmentFilterLIVE โ€“ Planned, confirmed or done (the ones that take the time).
PLANNED
CONFIRMED
DECLINED
DONE
CANCELLED
ALL
TypeFields
RentalStaffCandidate
A staff member or resource for a window, best first: already working another part of the same job that day, then at their home location, then the fewest minutes booked that day, then the fewest other skills (resources: the smallest that seats enough).
id: ID!, legacyResourceId: Int!, subjectType: String!, name: String, colour: String, rank: Int!, qualified: Boolean!, hard: Boolean!, conflicts: [RentalStaffConflict!]!, nextFreeAt: String
RentalStaffConflict
Why a staff member or resource can’t (or shouldn’t) take a job. Hard conflicts refuse unless forced with a reason.
code: String!, hard: Boolean!, message: String!, subjectType: String, subjectId: ID, assignmentId: ID, job: String, otherJob: String, start: String, end: String
RentalStaffAssignmentPayloadassignment: RentalStaffAssignment, userErrors: [RentalUserError!]!
RentalStaffAutoAssignPayloadassigned: [RentalStaffAssignment!], suggested: [RentalStaffSuggestion!], unmet: [RentalStaffUnmet!], job: RentalStaffJob, userErrors: [RentalUserError!]!
RentalStaffSuggestionindex: Int!, kind: String!, role: String!, count: Int!, missing: Int!, matched: [Int!]!, candidates: [RentalStaffCandidate!]!
RentalStaffUnmetindex: Int!, role: String!, missing: Int!, reason: String!

Schedules, conflicts and hours #

OperationArgumentsWhat it does
rentalStaffSchedule
query ยท secret key
returns RentalStaffSchedule!
subjectId: ID!
from: String
to: String
A staff member’s or resource’s assignments (each with its job) and blocked times between two days (default: today and the next 13 days). subjectId is a gid://sirentals/Staff/โ€ฆ or gid://sirentals/Resource/โ€ฆ; a bare number means a staff member.
rentalStaffUnassigned
query ยท secret key
returns [RentalStaffJob!]!
from: String
to: String
locationId: ID
Open jobs still missing staff or resources between two days (default: today and the next 13 days), soonest first.
rentalStaffConflicts
query ยท secret key
returns [RentalStaffConflict!]!
from: String
to: String
locationId: ID
Every conflict of the assignments between two days (default: today and the next 13 days).
rentalStaffHours
query ยท secret key
returns RentalStaffHoursReport!
from: String
to: String
locationId: ID
staffId: ID
Scheduled hours per staff member per day, for payroll: their planned, confirmed and done assignments, overlapping ones counted once, a night job split at midnight. Days are Y-m-d, to included; default 7 days from today, at most 92.
query AlexSchedule {
  rentalStaffSchedule(subjectId: "gid://sirentals/Staff/7", from: "2026-12-05", to: "2026-12-06") {
    from to
    assignments { id role start end status job { ref title orderName start end } }
    blocks { id kind start end reason }
  }
}
query Gaps {
  rentalStaffUnassigned(from: "2026-12-05", to: "2026-12-11") {
    type jobId ref title start end missing
    needs { role count missing reason }
  }
  rentalStaffConflicts(from: "2026-12-05", to: "2026-12-11") {
    code hard message subjectType subjectId assignmentId job otherJob start end
  }
}
query PayrollWeek {
  rentalStaffHours(from: "2026-12-01", to: "2026-12-07") {
    from to
    rows { staffId staffLegacyId name date minutes hours jobs checkedIn }
    totals { staffId name minutes hours jobs checkedIn days }
  }
}
TypeFields
RentalStaffSchedule
A staff member’s or resource’s jobs and blocks between two days.
from: String!, to: String!, assignments: [RentalStaffAssignment!]!, blocks: [RentalScheduleBlock!]!
RentalStaffHoursReport
Scheduled hours per staff member per day (rentalStaffHours).
from: String!, to: String!, rows: [RentalStaffHoursDay!]!, totals: [RentalStaffHoursTotal!]!
RentalStaffHoursDaystaffId: ID!, staffLegacyId: Int!, name: String!, email: String, date: String!, minutes: Int!, hours: Float!, jobs: Int!, checkedIn: Int!
RentalStaffHoursTotalstaffId: ID!, staffLegacyId: Int!, name: String!, minutes: Int!, hours: Float!, jobs: Int!, checkedIn: Int!, days: Int!