API Documentation

Shift tags let you categorize shifts beyond their basic attributes. Want to ensure night shifts are distributed fairly? Need to track ICU vs. general ward assignments? Tags give you fine-grained control over shift distribution and quotas.


Why use tags

Without tags, you're limited to the shift's built-in properties: spot, time, importance. Tags add semantic meaning:

  • Time of day: morning, evening, night, weekend
  • Service type: icu, emergency, surgery, admin
  • Severity: high-acuity, standard, supervision
  • Special roles: oncall, training, backup

Tags enable constraints like "no more than 4 night shifts per month" or "distribute ICU shifts evenly across qualified staff."

Tag structure

Define your tag catalog at the request level:

{
  "shiftTags": [
    {
      "id": 1,
      "departmentId": 7,
      "tag": "night",
      "category": "time",
      "description": "Overnight shift (7pm - 7am)",
      "color": "#1E293B",
      "active": true
    },
    {
      "id": 2,
      "departmentId": 7,
      "tag": "icu",
      "category": "service",
      "description": "Intensive care unit assignment",
      "color": "#DC2626",
      "active": true
    }
  ]
}

Tag fields

  • id - Unique identifier for this tag
  • departmentId - Associates tag with your organizational unit
  • tag - The actual tag string (e.g., "night", "icu")
  • category - Groups related tags (e.g., "time", "service", "severity")
  • description - Human-readable explanation
  • color - Hex color for UI display
  • active - Whether this tag is currently in use

Applying tags to shifts

Once defined, attach tags to any shift:

{
  "shifts": [
    {
      "id": 101,
      "spot": 11,
      "start": "2024-09-06T19:00:00Z",
      "end": "2024-09-07T07:00:00Z",
      "importance": "MANDATORY",
      "tags": ["night", "icu"]
    }
  ]
}

A shift can have multiple tags. The solver uses these for distribution and quota enforcement.


Tag-based constraints

Enable tag constraints via settings:

Category shift quotas

Limit how many shifts with a specific tag category an employee can work:

{
  "settings": {
    "categoryShiftQuota": {
      "firstPriorityWeight": 10,
      "secondPriorityWeight": 0,
      "thirdPriorityWeight": 0,
      "fourthPriorityWeight": 0
    }
  }
}

This works with employee contracts. For example, if you want to cap night shifts, combine tags with contract settings to enforce "no more than 4 night tagged shifts per 4-week rolling period."

Load balance category shifts

Distribute shifts with specific tags evenly across employees:

{
  "settings": {
    "loadBalanceCategoryShifts": {
      "firstPriorityWeight": 15,
      "secondPriorityWeight": 0,
      "thirdPriorityWeight": 0,
      "fourthPriorityWeight": 0
    }
  }
}

Use this to ensure everyone shares the burden of unpopular shifts (nights, weekends) or to distribute desirable assignments (training, special projects) fairly.


Complete example

A 24/7 urgent care center using tags:

{
  "shiftTags": [
    {
      "id": 1,
      "departmentId": 10,
      "tag": "day",
      "category": "time",
      "description": "Daytime hours (7am - 3pm)",
      "color": "#FCD34D",
      "active": true
    },
    {
      "id": 2,
      "departmentId": 10,
      "tag": "evening",
      "category": "time",
      "description": "Evening hours (3pm - 11pm)",
      "color": "#FB923C",
      "active": true
    },
    {
      "id": 3,
      "departmentId": 10,
      "tag": "night",
      "category": "time",
      "description": "Overnight hours (11pm - 7am)",
      "color": "#1E293B",
      "active": true
    },
    {
      "id": 4,
      "departmentId": 10,
      "tag": "triage",
      "category": "service",
      "description": "Patient intake and assessment",
      "color": "#3B82F6",
      "active": true
    }
  ],
  "shifts": [
    {
      "id": 201,
      "spot": 5,
      "start": "2024-09-10T07:00:00Z",
      "end": "2024-09-10T15:00:00Z",
      "importance": "MANDATORY",
      "tags": ["day", "triage"]
    },
    {
      "id": 202,
      "spot": 5,
      "start": "2024-09-10T23:00:00Z",
      "end": "2024-09-11T07:00:00Z",
      "importance": "MANDATORY",
      "tags": ["night", "triage"]
    }
  ],
  "settings": {
    "categoryShiftQuota": {
      "firstPriorityWeight": 10,
      "secondPriorityWeight": 0,
      "thirdPriorityWeight": 0,
      "fourthPriorityWeight": 0
    },
    "loadBalanceCategoryShifts": {
      "firstPriorityWeight": 12,
      "secondPriorityWeight": 0,
      "thirdPriorityWeight": 0,
      "fourthPriorityWeight": 0
    }
  }
}

This configuration:

  1. Defines four tags across two categories (time, service)
  2. Tags each shift appropriately
  3. Enforces quotas to prevent excessive night shifts
  4. Balances triage assignments across staff

Benefits for frontends

Tags travel with the schedule response. Your UI can:

  • Color-code shifts automatically using the color field
  • Filter schedules by category
  • Show employees their tag distribution ("You worked 3 night shifts this month")
  • Display tag metadata without hardcoding shift types

Everything needed for display is in the tag definition-no backend roundtrips required.

Backward compatibility

Tags are completely optional. If you omit them:

  • The solver ignores tag-based constraints
  • Existing payloads continue working unchanged
  • You can adopt tags incrementally (add the catalog first, enable constraints later)

For more advanced tag usage, see Shift dependency rules.