Roster workers are the same workers used by task routing, with additional planning facts. Keep identity and qualifications on the worker; keep contract, pay, and site-planning facts in roster terms.
Qualifications
Shift eligibility is checked against a worker’s date-valid tags and qualifications. Use hard requirements for licences, clearances, languages, or role qualifications that must never be waived by scoring.
Requirements can apply to:
- every person on a post or shift (
requiredTags); - the composition of the whole shift (
tagRequirements); - a maximum number in one category (
tagMaximums).
Candidate explanations return failed requirements explicitly, so “not eligible” never has to be a black box.
Working terms
tsawait fivexer.roster.setTerms('worker_anna', { weeklyMinutes: 2_400, maxDaysInPeriod: 5, rateCents: 2_250, overtimeConsent: true, homeSiteId: 'site_north', siteIds: ['site_north', 'site_south'], });
Important semantics:
weeklyMinutes: nullmeans the contractual week is not stated.maxDaysInPeriod: nullmeans no personal period cap is stated.rateCents: nullinherits the workspace default rate when one exists.overtimeConsentis tri-state:true,false, ornullfor never recorded. When consent is required,nullis treated like no consent.homeSiteIdis a preference, not permission.siteIds: []means the person may work at every site. A non-empty list is a hard allow-list.
Pay configuration
Pay settings price a plan; they do not invent legal rules.
tsawait fivexer.roster.setPay({ defaultRateCents: 2_000, bands: [ { id: 'night', label: 'Night', startTime: '22:00', endTime: '06:00', multiplier: 1.25 }, ], sundayMultiplier: 1.5, holidayMultiplier: 2, holidays: ['2026-12-25'], overtimeMultiplier: 1.5, stacking: 'max', });
stacking: 'max' uses the largest applicable premium for a minute; add combines premiums. Personal rates override the workspace default. If no rate resolves for a worker, their planned time remains visible but no invented cost is returned.
Use roster.plannedHours({ from, to }) to read shift counts, ordinary time, premium-band minutes, overtime, and cost by worker and day. The response says whether it came from a published or draft plan.
Time off
Only approved leave constrains the solver. Pending requests appear in publishing preflight because publishing over one may be a legitimate manager decision, but it should never happen invisibly.
tsconst request = await fivexer.timeOff.create({ workerId: 'worker_anna', startDate: '2026-09-14', endDate: '2026-09-18', kind: 'vacation', }); const impact = await fivexer.timeOff.impact(request.id); await fivexer.timeOff.approve(request.id);
Check impact before deciding: it identifies affected rosters and conflicting shifts. For sickness or a no-show after publication, use the cover workflow instead of rewriting historical leave.