Skip to content
Docs
Sign in

Schedule API

Read the board, add imposed jobs, move and pin steps, place jobs with a preview, and post floor events from your own systems.

For integrators

The Schedule API does what the Schedule pages do: it reads the board, adds imposed jobs, changes the plan, and records what happens on the floor. Use it to feed the Schedule from a machine's own controller, show the queue on another screen, or add jobs from another system. Every endpoint is under your team, at /a/<team_slug>/schedule/api/v1/.

Every call takes the same authentication as the rest of the API: an API key of a team member, or a signed-in session that also sends its CSRF token when it changes data (see authentication).

Ids are numbers. An object of another team is a 404. Every member can read. Changing the setup (machines, hours, routes, ready checks and settings) needs a team administrator (403 for other members); planning endpoints need a planner (see Schedule settings).

Times, revisions and polling#

  • Times are Unix times in seconds (UTC). The board's tz is your team's time zone, for showing them.
  • Revision. The team's schedule has a revision number, rev, that goes up with every change. Every change answers with the new rev.
  • Polling. Send the last rev you have in If-None-Match when you read the board: an unchanged schedule answers 304 Not Modified at once. ?since=<rev> returns only what changed since.
  • Stale changes. A plan change sends the rev it was based on. If the plan changed in between, the answer is 409 with code: "stale" and what changed. Moves are relative ("after step 88"), so you can usually send them again. Every refusal also has detail, a sentence to show people; code is for your code.
BASE="https://app.example.com/a/<team_slug>/schedule/api/v1"   # your team's slug
AUTH="Authorization: Api-Key $API_KEY"

# The board for one day, then poll it (304 while nothing changed)
curl -s "$BASE/board/?from=1790000000&to=1790086400" -H "$AUTH"
curl -s -o /dev/null -w "%{http_code}" "$BASE/board/" -H "$AUTH" -H 'If-None-Match: "214"'

The board#

GET board/ returns the machines, their working time, downtime, jobs and steps in one answer, with short keys:

{
  "rev": 214,
  "now": 1790000000,
  "tz": "Europe/London",
  "resources": [{"id": 1, "name": "Press 1", "kind": "press_offset", "dept": "Print", "state": "running"}],
  "windows": {"1": [[1789970400, 1790002800]]},
  "downtime": [{"id": 5, "r": 1, "kind": "maintenance", "s": 1790010000, "e": 1790013600, "reason": "Blanket wash"}],
  "orders": {"42": {"job": 42, "name": "Postcard A", "customer": "C-102", "due": 1790200000, "prio": 3,
                    "status": "scheduled", "ready": true, "risk": "ok"}},
  "ops": [{"id": 88, "o": 42, "k": "print", "n": "Print", "r": 1, "seq": 3, "s": 1790003600, "e": 1790011200,
           "su": 2400, "st": "ready", "pin": null, "km": true, "preds": [87]}],
  "tray": [43, 44]
}

In ops, r is the machine, seq the place in its queue, s and e the planned start and end, su the makeready in seconds, st the status and km Only this machine. GET today/ gives the phone view's summary per machine, its counts (late, at risk, machines down, ready to place: the board's own counts) and the jobs ready to place, and GET stations/<machine id>/ a station's current step, Up next and Later today.

Jobs#

Call What it does
GET orders/ Jobs, filtered with status, risk, customer or q.
POST orders/ with {"job": 42} Adds imposition job 42 to the tray (409 with no_layout when it has no selected layout); a finished job is added again as a reprint, or refused with 409 finished when you send "reprint": false. {"jobs": "all"} adds every imposed job with a selected layout that was never scheduled. {"name", "customer", "due_at", "priority", "route", "quantity", "notes"} adds a job that isn't imposed.
PATCH orders/<id>/ {"status": "hold", "hold_reason": "…"} holds a job; {"status": "scheduled"} releases it. Also notes, release_at (not before) and route; a job that isn't imposed also takes name, customer, due_at and priority.
DELETE orders/<id>/ Removes the job from the schedule. The imposition job isn't touched.
POST orders/<id>/refresh/ Times the job again from its layout.
POST orders/<id>/steps/, DELETE orders/<id>/steps/<step id>/ Adds a step to the job, or skips one that hasn't started.
PATCH orders/<id>/checks/<key>/ {"state": "passed"} or "pending", with eta and note, ticks a manual ready check. Planners may also send "waived".

Due dates, customers and priorities belong to the imposition job: change them with the Imposition API.

Plan changes#

Call Body
POST operations/<id>/move/ {"resource": 2, "after": 91, "rev": 214} (or before). Answers the new rev and the steps that changed; 409 with stale, cycle or ineligible.
POST operations/<id>/pin/ {"at": 1790020000, "rev": 214}; unpin/ removes it.
POST operations/<id>/keep-machine/ {"value": false, "rev": 214} switches Only this machine.
POST plan/preview/ {"mode": "place", "orders": [42, 43]}, or no orders for everything ready. Answers a preview_id, a summary and the steps that would change; nothing is saved.
POST plan/apply/ {"preview_id": "…"} applies a preview, or 409 when the plan changed too much since (plan_changed) or the preview is older than 10 minutes (expired).
POST activity/<id>/undo/, POST activity/<id>/redo/ Undoes a change from GET activity/, or redoes an undo. Steps that changed or started since are kept and listed.

Floor events#

POST operations/<id>/events/ records what happened at a machine: start, makeready_done, pause, resume, progress, done, problem, resolve, note, and check, which ticks a manual ready check the way Stock arrived does. Planners can also send reopen (a done step, within 24 hours) and skip (a step that hasn't started).

curl -s -X POST "$BASE/operations/88/events/" -H "$AUTH" -H "Content-Type: application/json" \
  -d '{"kind": "done", "client_id": "00000000-0000-0000-0000-000000000000", "qty_good": 2100, "qty_waste": 40}'
  • client_id makes the call safe to repeat: the same id twice records one event (201 the first time, 200 after).
  • at (when it happened) defaults to now; reason is a pause or problem reason (see The station), note any text.
  • resource records a step started on another machine than planned; running_choice (pause or finish) says what to do with the step already running there.
  • An event that doesn't fit the step answers 409 with invalid_transition, or check_pending when a ready check holds it back. A planner can send "override": true to start anyway.

Setup#

resources/ (with import-equipment/), downtime/, routes/ (with <id>/test/?job=42), checks/ and settings/ create, read, change and delete the machines, downtime, routes, ready checks and settings. Changes need a team administrator, except POST resources/<id>/down/ and up/, which any member can call to report a machine down or back up. PATCH settings/ also takes timezone, the team's time zone (an IANA name such as Europe/London; blank for UTC), the same field as the team settings: the shop hours are re-timed in it.

GET activity/ lists the last 50 plan changes, and GET alerts/ the open alerts (POST alerts/<id>/ack/ acknowledges one).

Every Schedule endpoint#

API operations tagged scheduling
MethodPathWhat it does
GET /a/{team_slug}/schedule/api/v1/activity/ List the latest plan changes and floor decisions, newest first.
POST /a/{team_slug}/schedule/api/v1/activity/{id}/redo/ Redo an undone change (the undo's id).
POST /a/{team_slug}/schedule/api/v1/activity/{id}/undo/ Undo a plan change (steps changed or started since are kept).
GET /a/{team_slug}/schedule/api/v1/alerts/ List the open alerts.
POST /a/{team_slug}/schedule/api/v1/alerts/{id}/ack/ Acknowledge an alert.
GET /a/{team_slug}/schedule/api/v1/board/ Read the planning board: machines, working time, downtime, jobs and steps.
GET /a/{team_slug}/schedule/api/v1/checks/ Read the team's ready checks.
PATCH /a/{team_slug}/schedule/api/v1/checks/ Switch built-in ready checks, set custom checks and Require a proof.
GET /a/{team_slug}/schedule/api/v1/downtime/ List downtime and overtime (open and coming).
POST /a/{team_slug}/schedule/api/v1/downtime/ Add downtime (closed, maintenance, breakdown) or overtime to a machine or the whole shop.
PATCH /a/{team_slug}/schedule/api/v1/downtime/{id}/ Change a downtime.
DELETE /a/{team_slug}/schedule/api/v1/downtime/{id}/ Remove a downtime.
POST /a/{team_slug}/schedule/api/v1/operations/{id}/events/ Record a floor event on a step: start, pause, resume, done, problem and more.
GET /a/{team_slug}/schedule/api/v1/operations/{id}/explain/ Explain a step: why it starts when it does, other machines, late causes and fixes.
POST /a/{team_slug}/schedule/api/v1/operations/{id}/keep-machine/ Switch Only this machine for a step.
POST /a/{team_slug}/schedule/api/v1/operations/{id}/move/ Put a step on a machine, after or before another step of that machine.
POST /a/{team_slug}/schedule/api/v1/operations/{id}/override/ Set a step's duration by hand, or go back to the estimate.
POST /a/{team_slug}/schedule/api/v1/operations/{id}/pin/ Pin a step: keep it on its machine, not before a time.
POST /a/{team_slug}/schedule/api/v1/operations/{id}/unpin/ Remove a step's pin.
GET /a/{team_slug}/schedule/api/v1/orders/ List the schedule's jobs.
POST /a/{team_slug}/schedule/api/v1/orders/ Send an imposition job (or all of them) to the schedule, or add a manual job.
GET /a/{team_slug}/schedule/api/v1/orders/{id}/ Read a job with its steps and ready checks.
PATCH /a/{team_slug}/schedule/api/v1/orders/{id}/ Hold or release a job, or change its notes, not-before time or route.
DELETE /a/{team_slug}/schedule/api/v1/orders/{id}/ Remove a job from the schedule.
PATCH /a/{team_slug}/schedule/api/v1/orders/{id}/checks/{key}/ Tick, untick or waive a job's ready check.
POST /a/{team_slug}/schedule/api/v1/orders/{id}/refresh/ Time a job again from its layout (Review new times).
POST /a/{team_slug}/schedule/api/v1/orders/{id}/steps/ Add a step to a job.
DELETE /a/{team_slug}/schedule/api/v1/orders/{id}/steps/{op_id}/ Skip a step of a job that hasn't started.
POST /a/{team_slug}/schedule/api/v1/plan/apply/ Apply a previewed plan as one change you can undo.
POST /a/{team_slug}/schedule/api/v1/plan/preview/ Preview Place (new steps only) or Re-plan: nothing changes until you apply it.
GET /a/{team_slug}/schedule/api/v1/plan/preview/{task_id}/ Read a background preview: 202 while it is still working.
GET /a/{team_slug}/schedule/api/v1/resources/ List the schedule's machines.
POST /a/{team_slug}/schedule/api/v1/resources/ Add a machine.
GET /a/{team_slug}/schedule/api/v1/resources/{id}/ Read a machine.
PATCH /a/{team_slug}/schedule/api/v1/resources/{id}/ Change a machine.
DELETE /a/{team_slug}/schedule/api/v1/resources/{id}/ Remove a machine that has no work or history.
POST /a/{team_slug}/schedule/api/v1/resources/{id}/down/ Report a machine down (a breakdown with an expected end).
POST /a/{team_slug}/schedule/api/v1/resources/{id}/up/ Report a machine back up (closes its breakdown).
POST /a/{team_slug}/schedule/api/v1/resources/import-equipment/ Add equipment from the equipment library as machines (all of it, or the listed items).
GET /a/{team_slug}/schedule/api/v1/routes/ List the routes jobs follow.
POST /a/{team_slug}/schedule/api/v1/routes/ Add a route.
GET /a/{team_slug}/schedule/api/v1/routes/{id}/ Read a route.
PATCH /a/{team_slug}/schedule/api/v1/routes/{id}/ Change a route (jobs already on the schedule keep their steps).
DELETE /a/{team_slug}/schedule/api/v1/routes/{id}/ Remove a route (not the fallback route).
GET /a/{team_slug}/schedule/api/v1/routes/{id}/test/ Test a route with an imposition job: its steps, every machine's time, the machines that can't.
GET /a/{team_slug}/schedule/api/v1/settings/ Read the schedule's settings.
PATCH /a/{team_slug}/schedule/api/v1/settings/ Change schedule settings (shop hours, time fence, automation, who can plan…).
GET /a/{team_slug}/schedule/api/v1/stations/{id}/ Read one machine's queue: the step on it, up next, later today and other work it could run.
GET /a/{team_slug}/schedule/api/v1/today/ Read today's floor per machine: its state, the step on it and what is next.

All “scheduling” operations in the API reference

Last updated Sept. 29, 2026