{
  "openapi": "3.0.1",
  "info": {
    "title": "Shift Scheduler: Employee Scheduling & Staff Rota Generator",
    "description": "Make staff schedules (rotas) with Google OR-Tools: shifts with roles and headcounts, availability, time off, weekly hours, rest rules, fairness and preferences. Every gap explained. Rota image, PDF, Excel and calendar files. From text, JSON, CSV or Google Sheets. For AI agents.",
    "version": "0.1",
    "x-build-id": "Lw19ZUwYayw3PyoSM"
  },
  "servers": [
    {
      "url": "https://api.apify.com/v2"
    }
  ],
  "paths": {
    "/acts/jumblemog~shift-scheduler/run-sync-get-dataset-items": {
      "post": {
        "operationId": "run-sync-get-dataset-items-jumblemog-shift-scheduler",
        "x-openai-isConsequential": false,
        "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
        "tags": [
          "Run Actor"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/inputSchema"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "token",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Enter your Apify token here"
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    },
    "/acts/jumblemog~shift-scheduler/runs": {
      "post": {
        "operationId": "runs-sync-jumblemog-shift-scheduler",
        "x-openai-isConsequential": false,
        "summary": "Executes an Actor and returns information about the initiated run in response.",
        "tags": [
          "Run Actor"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/inputSchema"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "token",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Enter your Apify token here"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/runsResponseSchema"
                }
              }
            }
          }
        }
      }
    },
    "/acts/jumblemog~shift-scheduler/run-sync": {
      "post": {
        "operationId": "run-sync-jumblemog-shift-scheduler",
        "x-openai-isConsequential": false,
        "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
        "tags": [
          "Run Actor"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/inputSchema"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "token",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Enter your Apify token here"
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "inputSchema": {
        "type": "object",
        "properties": {
          "employees": {
            "title": "Employees",
            "type": "array",
            "description": "The people to schedule, one per entry, as text or an object. Text: \"Ana: shift lead, barista; 30-40 h; off Sun; prefers mornings; $18/h\": the name, the roles they can work, then any of: weekly hours as a target (36 h), a range (20-32 h) or a limit (max 30 h); times they can't work (off Sun, no Tue after 17:00); the only times they can (available weekdays); times they prefer or want to avoid; fixed shifts (always Mon Morning); max 5 days; max 4 shifts; their hourly cost. Object: {\"name\": \"Ana\", \"skills\": [\"shift lead\", \"barista\"], \"minHours\": 30, \"maxHours\": 40, \"targetHours\": 36, \"unavailable\": \"Sun, 2026-11-05\", \"available\": \"weekdays\", \"prefer\": \"mornings\", \"avoid\": \"weekends\", \"fixed\": \"Mon Morning\", \"maxDaysPerWeek\": 5, \"maxShiftsPerWeek\": 5, \"maxConsecutiveDays\": 5, \"minRestHours\": 12, \"cost\": 18}. Times can be weekdays (Mon, Mon-Fri, weekends), dates (2026-11-05, Nov 5-9), shift names (Morning), parts of the day (mornings, evenings, nights) or clock times (after 17:00, before 10am), alone or together, such as \"Tue after 17:00\" or \"Sat Evening\". Up to 500 people."
          },
          "shifts": {
            "title": "Shifts",
            "type": "array",
            "description": "The shifts to fill, as text or objects. Text: \"Morning 07:00-15:00: 1 shift lead, 2 barista; daily\": the name and times, then the people needed, in total (3) or by role, and the days it runs (Mon-Fri, weekends, Sat, 2026-12-24), with optional parts such as \"30 min break\" (unpaid), \"max 4\" (extra people allowed) or \"priority high\". Object: {\"name\": \"Morning\", \"start\": \"07:00\", \"end\": \"15:00\", \"roles\": {\"shift lead\": 1, \"barista\": 2}, \"days\": \"Mon-Fri\", \"break\": 30, \"maxStaff\": 4, \"priority\": \"high\"}. The headcount can change by day: \"staff\": {\"Mon-Thu\": 2, \"Fri-Sat\": 4, \"default\": 3}, or seven numbers, Monday first. Overnight shifts such as 22:00-06:00 work. Places beyond the named roles can go to anyone. Up to 60 shifts."
          },
          "employeesCsv": {
            "title": "Employees as CSV or link",
            "type": "string",
            "description": "Employees as CSV or TSV text with a header row, such as name,skills,minHours,maxHours,unavailable,prefer,cost (the same fields as above), or a link to a CSV, Excel or JSON file, or a Google Sheet shared as \"Anyone with the link\". Added to Employees."
          },
          "shiftsCsv": {
            "title": "Shifts as CSV or link",
            "type": "string",
            "description": "Shifts as CSV text with a header row, such as name,start,end,roles,days,break, or a link to a file or Google Sheet. Added to Shifts."
          },
          "startDate": {
            "title": "Start date",
            "type": "string",
            "description": "The schedule's first day, such as 2026-11-02, or today, tomorrow or a weekday name. Empty: next Monday."
          },
          "days": {
            "title": "Number of days",
            "minimum": 1,
            "maximum": 92,
            "type": "integer",
            "description": "How many days to schedule, up to 92 (13 weeks). Weekly limits count in 7-day blocks from the first day.",
            "default": 7
          },
          "endDate": {
            "title": "End date",
            "type": "string",
            "description": "The last day to schedule, such as 2026-11-29, instead of Number of days."
          },
          "closedDates": {
            "title": "Closed days",
            "type": "array",
            "description": "Days with no shifts at all, such as 2026-12-25 or Sun.",
            "items": {
              "type": "string"
            }
          },
          "maxHoursPerWeek": {
            "title": "Most hours a week",
            "minimum": 0,
            "maximum": 168,
            "type": "number",
            "description": "The most hours anyone works in a week. 0: no limit.",
            "default": 40
          },
          "minHoursPerWeek": {
            "title": "Fewest hours a week",
            "minimum": 0,
            "maximum": 168,
            "type": "number",
            "description": "Hours everyone should get each week. The schedule gives them whenever the shifts and rules allow, before fairness and preferences, and lists anyone who falls short."
          },
          "minRestHours": {
            "title": "Rest between shifts (hours)",
            "minimum": 0,
            "maximum": 48,
            "type": "number",
            "description": "The least time between the end of one shift and the start of the next, such as 11 hours under EU working time rules, so nobody closes late and opens early.",
            "default": 11
          },
          "maxConsecutiveDays": {
            "title": "Most days in a row",
            "minimum": 0,
            "maximum": 92,
            "type": "integer",
            "description": "The most days in a row anyone works. 0: no limit.",
            "default": 6
          },
          "maxDaysPerWeek": {
            "title": "Most days a week",
            "minimum": 1,
            "maximum": 7,
            "type": "integer",
            "description": "The most days anyone works in a week, such as 5."
          },
          "maxShiftsPerWeek": {
            "title": "Most shifts a week",
            "minimum": 1,
            "maximum": 50,
            "type": "integer",
            "description": "The most shifts anyone works in a week."
          },
          "maxShiftsPerDay": {
            "title": "Shifts per person per day",
            "minimum": 1,
            "maximum": 4,
            "type": "integer",
            "description": "How many shifts one person may work on the same day. Above 1, split shifts are allowed when they don't overlap.",
            "default": 1
          },
          "weekendDays": {
            "title": "Weekend days",
            "type": "array",
            "description": "The days that count as the weekend, for sharing weekend shifts fairly and for \"weekends\" in availability.",
            "items": {
              "type": "string",
              "enum": [
                "Mon",
                "Tue",
                "Wed",
                "Thu",
                "Fri",
                "Sat",
                "Sun"
              ],
              "enumTitles": [
                "Monday",
                "Tuesday",
                "Wednesday",
                "Thursday",
                "Friday",
                "Saturday",
                "Sunday"
              ]
            },
            "default": [
              "Sat",
              "Sun"
            ]
          },
          "fairness": {
            "title": "Share the work fairly",
            "type": "boolean",
            "description": "Spread hours in proportion to each person's limit, and weekend and night shifts evenly.",
            "default": true
          },
          "daysOffTogether": {
            "title": "Keep days off together",
            "type": "boolean",
            "description": "Avoid single days off between work days, such as working Monday and Wednesday but not Tuesday.",
            "default": true
          },
          "goal": {
            "title": "Optimize for",
            "enum": [
              "balanced",
              "cost",
              "preferences"
            ],
            "type": "string",
            "description": "What matters most once every shift is staffed as fully as the rules allow and everyone's minimum hours are met.",
            "default": "balanced"
          },
          "timeOff": {
            "title": "Time off",
            "type": "array",
            "description": "Approved time off, one entry per person and period: [{\"employee\": \"Ana\", \"from\": \"2026-11-05\", \"to\": \"2026-11-07\"}, \"Ben: Fri\", {\"employee\": \"Cara\", \"dates\": [\"2026-11-03\"], \"soft\": true}]. Time off is a rule; with \"soft\": true it's a request the schedule keeps when it can."
          },
          "fixedShifts": {
            "title": "Fixed shifts",
            "type": "array",
            "description": "Shifts someone must work: [\"Dev: Mon Morning as shift lead\", {\"employee\": \"Ana\", \"shift\": \"Sat Evening\"}]. Kept unless a rule makes that impossible, in which case the result says which rule."
          },
          "title": {
            "title": "Title",
            "type": "string",
            "description": "The schedule's name on the rota and in the results, such as Corner Café, week 45."
          },
          "timeFormat": {
            "title": "Time format",
            "enum": [
              "24h",
              "12h"
            ],
            "type": "string",
            "description": "How times are written on the rota and in the files.",
            "default": "24h"
          },
          "timezone": {
            "title": "Time zone for calendar files",
            "type": "string",
            "description": "Such as America/New_York or Europe/London. Empty: the calendar files use local times as written."
          },
          "timeLimitSeconds": {
            "title": "Solving time (seconds)",
            "minimum": 1,
            "maximum": 600,
            "type": "integer",
            "description": "The most time the solver spends improving the schedule; it stops sooner once the schedule stops improving. Small teams take a few seconds; for 30 or more people over several weeks, 60 to 120 seconds gives better hours. The first 30 seconds come with the schedule's price.",
            "default": 20
          },
          "schedules": {
            "title": "Several schedules (JSON)",
            "type": "array",
            "description": "Many schedules in one run, each an object with its own employees, shifts or settings: [{\"title\": \"Downtown\", \"employees\": [...], \"shifts\": [...]}, {\"title\": \"Airport\", \"employeesCsv\": \"https://...\", \"days\": 14}]. Settings outside schedules apply to every schedule, and a schedule with its own employees or shifts doesn't use the shared ones. Up to 50."
          }
        }
      },
      "runsResponseSchema": {
        "type": "object",
        "properties": {
          "data": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "actId": {
                "type": "string"
              },
              "userId": {
                "type": "string"
              },
              "startedAt": {
                "type": "string",
                "format": "date-time",
                "example": "2025-01-08T00:00:00.000Z"
              },
              "finishedAt": {
                "type": "string",
                "format": "date-time",
                "example": "2025-01-08T00:00:00.000Z"
              },
              "status": {
                "type": "string",
                "example": "READY"
              },
              "meta": {
                "type": "object",
                "properties": {
                  "origin": {
                    "type": "string",
                    "example": "API"
                  },
                  "userAgent": {
                    "type": "string"
                  }
                }
              },
              "stats": {
                "type": "object",
                "properties": {
                  "inputBodyLen": {
                    "type": "integer",
                    "example": 2000
                  },
                  "rebootCount": {
                    "type": "integer",
                    "example": 0
                  },
                  "restartCount": {
                    "type": "integer",
                    "example": 0
                  },
                  "resurrectCount": {
                    "type": "integer",
                    "example": 0
                  },
                  "computeUnits": {
                    "type": "integer",
                    "example": 0
                  }
                }
              },
              "options": {
                "type": "object",
                "properties": {
                  "build": {
                    "type": "string",
                    "example": "latest"
                  },
                  "timeoutSecs": {
                    "type": "integer",
                    "example": 300
                  },
                  "memoryMbytes": {
                    "type": "integer",
                    "example": 1024
                  },
                  "diskMbytes": {
                    "type": "integer",
                    "example": 2048
                  }
                }
              },
              "buildId": {
                "type": "string"
              },
              "defaultKeyValueStoreId": {
                "type": "string"
              },
              "defaultDatasetId": {
                "type": "string"
              },
              "defaultRequestQueueId": {
                "type": "string"
              },
              "buildNumber": {
                "type": "string",
                "example": "1.0.0"
              },
              "containerUrl": {
                "type": "string"
              },
              "usage": {
                "type": "object",
                "properties": {
                  "ACTOR_COMPUTE_UNITS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_WRITES": {
                    "type": "integer",
                    "example": 1
                  },
                  "KEY_VALUE_STORE_LISTS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_INTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_EXTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_SERPS": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_UNBLOCKER_UNITS": {
                    "type": "integer",
                    "example": 0
                  }
                }
              },
              "usageTotalUsd": {
                "type": "number",
                "example": 0.00005
              },
              "usageUsd": {
                "type": "object",
                "properties": {
                  "ACTOR_COMPUTE_UNITS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_WRITES": {
                    "type": "number",
                    "example": 0.00005
                  },
                  "KEY_VALUE_STORE_LISTS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_INTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_EXTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_SERPS": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_UNBLOCKER_UNITS": {
                    "type": "integer",
                    "example": 0
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}