Fivexer

Sites, posts & shifts

The coverage model describes the week your operation must run. Build it from the outside in: site → post → shift band → cover.

Sites are places

A site is geographic: a building, depot, ward, or customer location. Store an address for people, coordinates for distance estimates, and explicit travel times when you know them.

ts
const north = await fivexer.roster.createSite({
  name: 'North clinic',
  address: '12 North Road',
  lat: 59.447,
  lng: 24.753,
});

Sites do not describe what must be staffed. That is the job of posts.

Posts are responsibilities

A post is one thing that needs cover at a site: Reception, Loading bay, Ward A, or Patrol van 2. The TypeScript SDK and HTTP API use the historical name station; the console says post.

ts
const reception = await fivexer.roster.createStation({
  name: 'Reception',
  siteId: north.id,
  requiredTags: ['first-aid'],
});

requiredTags is a hard gate inherited by shifts on the post. A person without every required tag is ineligible, not merely ranked lower. Use a post requirement for qualifications that apply whenever that responsibility is staffed.

Shift bands own the clock

A shift band is a reusable span such as Day or Night. An end time equal to or earlier than the start crosses midnight.

ts
const day = await fivexer.roster.createBand({
  name: 'Day',
  startTime: '08:00',
  endTime: '16:00',
  unpaidBreakMinutes: 30,
});

Times are wall-clock times in the roster’s IANA time zone. Fivexer resolves daylight-saving transitions when it expands a template into dated occurrences, so an overnight shift may contain seven or nine elapsed hours on a clock-change night.

Coverage cells create shift templates

The coverage grid’s rows are posts and its columns are shift bands. A cell says which weekdays run and how many people are needed.

ts
await fivexer.roster.setCell(reception.id, day.id, {
  daysOfWeek: [1, 2, 3, 4, 5],
  minEmployees: 2,
  maxEmployees: 3,
  tagRequirements: { 'first-aid': 1 },
  tagMaximums: { trainee: 1 },
});

Three different qualification controls answer three different questions:

FieldMeaning
requiredTagsEvery assigned person must carry every tag
tagRequirementsAt least this many people on the shift must carry each tag
tagMaximumsNo more than this many assigned people may carry each tag

For example, requiredTags: ['security-cleared'] gates the whole shift, tagRequirements: { lead: 1 } requires at least one lead in the team, and tagMaximums: { trainee: 1 } prevents a crew made mostly of trainees.

Direct shift templates

Use createTemplate when a simple list is clearer than a post × band matrix, or for one-off dated shifts.

ts
await fivexer.roster.createTemplate({
  name: 'Month-end stock count',
  startTime: '18:00',
  endTime: '23:00',
  dates: ['2026-09-30'],
  minEmployees: 4,
  siteId: north.id,
});

A template uses either daysOfWeek or explicit dates, never both. Deactivating or deleting a template changes future plans; already published rosters retain their snapshotted structure.

Check the coverage model

fivexer.roster.coverage() returns the rows, columns, templates, cells, weekly totals, uncovered weekdays, and unplaced templates. Use it to catch structural gaps before creating a roster. A gap here means demand was never described; no solver can infer it later.

Next, record people and their working terms or build the first roster.

Was this page helpful?