Scheduler REST API
The scheduler is a long-running service that manages access to SUT classes and dispatches queued work onto concrete SUT instances as they become available. It provides a REST API for:
creating scheduler users and API tokens
submitting plans for execution, tracking their progress, reprioritizing and cancelling them
acquiring and releasing manual leases on SUTs
querying SUT class metadata and usage
The main use cases are:
Plan execution: submit a plan that targets a SUT class and let the scheduler split the plan and dispatch onto available SUTs in parallel.
SUT leasing: request a lease on a SUT from a SUT class, wait for a SUT to become available, and release it when finished.
Operational reporting: inspect leases, plans, and SUT class usage.
Note
Users are expected to interact with the scheduler via the CLI commands (see Using the Scheduler). Those commands wrap the API documented here. The API is documented to enable integration with other systems.
Authentication
All endpoints require a bearer token in the Authorization header:
Authorization: Bearer <token>
Tokens are created via POST /users.
Capabilities
The scheduler enforces capabilities on each endpoint:
CAP_ADMIN: unrestricted administrative accessCAP_EXEC: submit and modify plansCAP_LEASE: acquire and release manual leasesCAP_QUERY: query scheduler state
An admin token bypasses ownership checks. Non-admin users are restricted to operating only on their own leases and plans.
Content Types
Most requests and all responses use JSON.
Plan submission is the exception: POST /plans accepts either JSON or
multipart/form-data. Multipart must be used when the plan references local
files that need to be uploaded alongside the plan payload (e.g. kernel images).
Endpoints
Users
POST /usersCreate a new scheduler user. Requires
CAP_ADMIN.Request body:
{ "name": "alice", "capabilities": "lease,query,exec" }
Response
201:{ "status": "success", "user_id": 3, "token": "<bearer-token>" }
Plans
POST /plansSubmit a plan for scheduler execution. Requires
CAP_EXEC.The scheduler validates the plan, stores any uploaded input files under the plan storage directory, stores a normalized
plan.yaml, splits the plan into plan jobs, and queues those jobs for dispatch. If the scheduler was started with a configured resultstore, plans publish results there by default; this can be disabled per-submission withpublish.JSON request body:
{ "plan": { ... plan object ... }, "priority": 5, "publish": true }
Multipart request:
form field
payloadcontaining JSON withplan,priority, and optionalpublishrepeated file field
filesfor any local files referenced by the plan
Response
201:{ "status": "success", "plan_id": 11 }
GET /plansList plans. Requires
CAP_QUERY.Optional query parameters to filter the response. If not provided, acts as if all values were provided:
states=queued,running,success,failed,cancelledusers=alice,bob
The special user value
__current__may be used to mean the authenticated user.GET /plans/<plan_id>Retrieve a single plan. Requires
CAP_QUERY.PATCH /plans/<plan_id>Modify a plan. Requires
CAP_EXEC. Non-admin users may only modify their own plans.Supported fields:
priority: reprioritize all non-completed child jobscancel: boolean; whentruerequests plan cancellation
Either field may be provided on its own, or both together.
Request body:
{ "priority": 8, "cancel": false }
Response
200:{ "status": "success" }
- Plan fields
plan_idPlan id.
userObject containing
idandname.sutclassObject containing
idandname.priorityPlan priority.
statePlan state. One of
queued,running,success,failed, orcancelled.total_jobsNumber of split plan jobs.
completed_jobsNumber of split plan jobs that completed successfully.
queued_at,started_at,completed_atplan timestamps.
Leases
POST /leasesQueue a manual lease against a SUT class. Requires
CAP_LEASE.Request body:
{ "sutclass": "myclass", "priority": 5 }
Response
201:{ "status": "success", "lease_id": 7 }
PATCH /leases/<lease_id>Release a lease. Requires
CAP_LEASE. Non-admin users may only release their own leases.Response
200:{ "status": "success" }
GET /leasesList leases. Requires
CAP_QUERY.Optional query parameters to filter the response. If not provided, acts as if all values were provided:
states=queued,acquired,released,failed,cancelledusers=alice,bob
The special user value
__current__may be used to mean the authenticated user.GET /leases/<lease_id>Retrieve a single lease. Requires
CAP_QUERY.- Lease fields
lease_idLease id.
userObject containing
idandname.job_idBacking job id.
stateLease state. One of
queued,acquired,released,failed, orcancelled.priorityLease priority.
sutclassObject containing
idandname.sutThe acquired SUT description, or
nullif not yet acquired.queued_at,started_at,completed_atTimestamps for the backing job lifecycle.
SUT Classes
GET /sutclassesList SUT classes known to the scheduler. Requires
CAP_QUERY.Optional query parameters:
from=<iso-datetime>to=<iso-datetime>
When
fromand/ortoare provided, the server calculatesusageonly within that time window. When neither is provided,usageis the scheduler’s accumulated all-time usage counter.- SUT class fields
idSUT class id.
nameSUT class name.
enabledBoolean indicating whether the SUT class is enabled.
usageRuntime usage in seconds.
created_atTimestamp when the SUT class row was created.
Errors
Errors return JSON of the form {"status": "<status>"}.
The scheduler currently uses these status codes:
400invalid400resourcebusy401unauthorized403forbidden404notfound409exists413toobig500internalerror
Examples
Create a scheduler user:
curl -X POST \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"name":"alice","capabilities":"lease,query,exec"}' \
http://localhost:5000/users
Acquire a lease:
curl -X POST \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"sutclass":"myclass","priority":5}' \
http://localhost:5000/leases
Submit a plan using multipart upload:
curl -X POST \
-H "Authorization: Bearer $TOKEN" \
-F 'payload={"plan": {...}, "priority": 5}' \
-F 'files=@Image' \
http://localhost:5000/plans
List SUT classes for a specific window:
curl -X GET \
-H "Authorization: Bearer $TOKEN" \
'http://localhost:5000/sutclasses?from=2026-03-01T00:00:00+00:00&to=2026-04-01T00:00:00+00:00'