API reference
Schedules
Run commands, restarts and backups on a timetable.
← API docs9 endpointsUpdated
Browse the docs
Schedules
Schedules run a list of tasks (console commands, power actions and backups) on a cron timetable. Each schedule's tasks run in order, each one waiting its time_offset after the one before.
List schedules
GET/servers/{server}/schedules
Permission schedule.read
Returns every schedule on the server, each with its tasks in attributes.relationships.tasks. The list is not paginated.
Parameters
| Name | Type | Description |
|---|---|---|
| serverrequired | string | The server's 8-character identifier, as shown in the panel, or its full UUID. |
Example
curl "https://sillydev.co.uk/panel/api/client/servers/1a7ce997/schedules" \ -H "Authorization: Bearer $SILLYDEV_API_KEY" \ -H "Accept: application/json"
Response 200The server's schedules.
{
"object": "list",
"data": [
{
"object": "server_schedule",
"attributes": {
"id": 12,
"name": "Nightly restart",
"cron": {
"day_of_week": "*",
"day_of_month": "*",
"month": "*",
"hour": "4",
"minute": "0"
},
"is_active": true,
"is_processing": false,
"only_when_online": true,
"last_run_at": "2026-10-10T04:00:00+00:00",
"next_run_at": "2026-10-11T04:00:00+00:00",
"created_at": "2026-09-01T12:00:00+00:00",
"updated_at": "2026-10-10T04:00:03+00:00",
"relationships": {
"tasks": {
"object": "list",
"data": [
{
"object": "schedule_task",
"attributes": {
"id": 31,
"sequence_id": 1,
"action": "command",
"payload": "say Restarting in 1 minute",
"time_offset": 0,
"is_queued": false,
"continue_on_failure": false,
"created_at": "2026-09-01T12:00:00+00:00",
"updated_at": "2026-09-01T12:00:00+00:00"
}
},
{
"object": "schedule_task",
"attributes": {
"id": 32,
"sequence_id": 2,
"action": "power",
"payload": "restart",
"time_offset": 60,
"is_queued": false,
"continue_on_failure": false,
"created_at": "2026-09-01T12:00:00+00:00",
"updated_at": "2026-09-01T12:00:00+00:00"
}
}
]
}
}
}
}
]
}Every field in the response
| Name | Type | Description |
|---|---|---|
| objectrequired | string | |
| datarequired | array of object | |
| data[].objectrequired | string | |
| data[].attributesrequired | object | |
| data[].attributes.idrequired | integer | |
| data[].attributes.namerequired | string | |
| data[].attributes.cronrequired | object | The five fields of a standard cron expression, in the panel's timezone. |
| data[].attributes.cron.day_of_weekrequired | string | |
| data[].attributes.cron.day_of_monthrequired | string | |
| data[].attributes.cron.monthrequired | string | |
| data[].attributes.cron.hourrequired | string | |
| data[].attributes.cron.minuterequired | string | |
| data[].attributes.is_activerequired | boolean | Whether the schedule runs on its timetable. |
| data[].attributes.is_processingrequired | boolean | True while the schedule's tasks are being worked through. |
| data[].attributes.only_when_onlinerequired | boolean | When true, a timed run is skipped if the server is offline or stopping. Manual runs ignore this. |
| data[].attributes.last_run_atrequired | string (date-time) | null | |
| data[].attributes.next_run_atrequired | string (date-time) | null | |
| data[].attributes.created_atrequired | string (date-time) | |
| data[].attributes.updated_atrequired | string (date-time) | |
| data[].attributes.relationships | object | |
| data[].attributes.relationships.tasks | object |
Errors
- 401 No API key was sent, or it is wrong, expired or deleted.
- 403 The key is valid but may not do this: it lacks the permission or account scope, it is limited to other servers or IP addresses, or the account may not do it at all.
- 404 There is no such resource, or the key cannot see it. Features that are switched off answer 404 too.
Create a schedule
POST/servers/{server}/schedules
Permission schedule.createLimited to 2 per minute per server
Creates a schedule with no tasks; add them with createScheduleTask. The five cron fields are evaluated in the panel's timezone and must together make a valid cron expression. is_active and only_when_online are false when left out, so send is_active: true for the schedule to run. New schedules are limited to 2 a minute per server, shared by everyone managing that server.
Parameters
| Name | Type | Description |
|---|---|---|
| serverrequired | string | The server's 8-character identifier, as shown in the panel, or its full UUID. |
Body
| Name | Type | Description |
|---|---|---|
| namerequired | string | |
| minuterequired | string | Cron minute field, such as 0, */5 or 0,30. |
| hourrequired | string | Cron hour field. |
| day_of_monthrequired | string | Cron day-of-month field. |
| monthrequired | string | Cron month field. Always send it, * for every month. |
| day_of_weekrequired | string | Cron day-of-week field, 0 or 7 being Sunday. |
| is_active | boolean | Whether the schedule runs on its timetable. False when left out. |
| only_when_online | boolean | Skip timed runs while the server is offline or stopping. False when left out. |
Example
curl -X POST "https://sillydev.co.uk/panel/api/client/servers/1a7ce997/schedules" \
-H "Authorization: Bearer $SILLYDEV_API_KEY" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{"name":"Nightly restart","minute":"0","hour":"4","day_of_month":"*","month":"*","day_of_week":"*","is_active":true,"only_when_online":true}'Response 200The new schedule.
{
"object": "server_schedule",
"attributes": {
"id": 12,
"name": "Nightly restart",
"cron": {
"day_of_week": "*",
"day_of_month": "*",
"month": "*",
"hour": "4",
"minute": "0"
},
"is_active": true,
"is_processing": false,
"only_when_online": true,
"last_run_at": null,
"next_run_at": "2026-10-11T04:00:00+00:00",
"created_at": "2026-10-10T12:00:00+00:00",
"updated_at": "2026-10-10T12:00:00+00:00",
"relationships": {
"tasks": {
"object": "list",
"data": []
}
}
}
}Every field in the response
| Name | Type | Description |
|---|---|---|
| objectrequired | string | |
| attributesrequired | object | |
| attributes.idrequired | integer | |
| attributes.namerequired | string | |
| attributes.cronrequired | object | The five fields of a standard cron expression, in the panel's timezone. |
| attributes.cron.day_of_weekrequired | string | |
| attributes.cron.day_of_monthrequired | string | |
| attributes.cron.monthrequired | string | |
| attributes.cron.hourrequired | string | |
| attributes.cron.minuterequired | string | |
| attributes.is_activerequired | boolean | Whether the schedule runs on its timetable. |
| attributes.is_processingrequired | boolean | True while the schedule's tasks are being worked through. |
| attributes.only_when_onlinerequired | boolean | When true, a timed run is skipped if the server is offline or stopping. Manual runs ignore this. |
| attributes.last_run_atrequired | string (date-time) | null | |
| attributes.next_run_atrequired | string (date-time) | null | |
| attributes.created_atrequired | string (date-time) | |
| attributes.updated_atrequired | string (date-time) | |
| attributes.relationships | object | |
| attributes.relationships.tasks | object | |
| attributes.relationships.tasks.objectrequired | string | |
| attributes.relationships.tasks.datarequired | array of object |
Errors
- 400 The cron fields do not make a valid cron expression.
- 401 No API key was sent, or it is wrong, expired or deleted.
- 403 The key is valid but may not do this: it lacks the permission or account scope, it is limited to other servers or IP addresses, or the account may not do it at all.
- 404 There is no such resource, or the key cannot see it. Features that are switched off answer 404 too.
- 422 Some fields were missing or invalid. There is one error per problem, and
meta.source_fieldnames the field. - 429 Too many requests. Wait for the number of seconds in the
Retry-Afterheader, then try again.
Get a schedule
GET/servers/{server}/schedules/{schedule}
Permission schedule.read
Returns one schedule with its tasks in attributes.relationships.tasks.
Parameters
| Name | Type | Description |
|---|---|---|
| serverrequired | string | The server's 8-character identifier, as shown in the panel, or its full UUID. |
| schedulerequired | integer | The schedule's numeric ID. |
Example
curl "https://sillydev.co.uk/panel/api/client/servers/1a7ce997/schedules/{schedule}" \
-H "Authorization: Bearer $SILLYDEV_API_KEY" \
-H "Accept: application/json"Response 200The schedule.
{
"object": "server_schedule",
"attributes": {
"id": 12,
"name": "Nightly restart",
"cron": {
"day_of_week": "*",
"day_of_month": "*",
"month": "*",
"hour": "4",
"minute": "0"
},
"is_active": true,
"is_processing": false,
"only_when_online": true,
"last_run_at": "2026-10-10T04:00:00+00:00",
"next_run_at": "2026-10-11T04:00:00+00:00",
"created_at": "2026-09-01T12:00:00+00:00",
"updated_at": "2026-10-10T04:00:03+00:00",
"relationships": {
"tasks": {
"object": "list",
"data": [
{
"object": "schedule_task",
"attributes": {
"id": 32,
"sequence_id": 1,
"action": "power",
"payload": "restart",
"time_offset": 0,
"is_queued": false,
"continue_on_failure": false,
"created_at": "2026-09-01T12:00:00+00:00",
"updated_at": "2026-09-01T12:00:00+00:00"
}
}
]
}
}
}
}Every field in the response
| Name | Type | Description |
|---|---|---|
| objectrequired | string | |
| attributesrequired | object | |
| attributes.idrequired | integer | |
| attributes.namerequired | string | |
| attributes.cronrequired | object | The five fields of a standard cron expression, in the panel's timezone. |
| attributes.cron.day_of_weekrequired | string | |
| attributes.cron.day_of_monthrequired | string | |
| attributes.cron.monthrequired | string | |
| attributes.cron.hourrequired | string | |
| attributes.cron.minuterequired | string | |
| attributes.is_activerequired | boolean | Whether the schedule runs on its timetable. |
| attributes.is_processingrequired | boolean | True while the schedule's tasks are being worked through. |
| attributes.only_when_onlinerequired | boolean | When true, a timed run is skipped if the server is offline or stopping. Manual runs ignore this. |
| attributes.last_run_atrequired | string (date-time) | null | |
| attributes.next_run_atrequired | string (date-time) | null | |
| attributes.created_atrequired | string (date-time) | |
| attributes.updated_atrequired | string (date-time) | |
| attributes.relationships | object | |
| attributes.relationships.tasks | object | |
| attributes.relationships.tasks.objectrequired | string | |
| attributes.relationships.tasks.datarequired | array of object |
Errors
- 401 No API key was sent, or it is wrong, expired or deleted.
- 403 The key is valid but may not do this: it lacks the permission or account scope, it is limited to other servers or IP addresses, or the account may not do it at all.
- 404 There is no such resource, or the key cannot see it. Features that are switched off answer 404 too.
Update a schedule
POST/servers/{server}/schedules/{schedule}
Permission schedule.update
Replaces the schedule's name, cron fields and switches; send every field, as with createSchedule. Leaving out is_active or only_when_online sets it to false. Turning a schedule on or off also clears a stuck is_processing flag. Tasks are not changed.
Parameters
| Name | Type | Description |
|---|---|---|
| serverrequired | string | The server's 8-character identifier, as shown in the panel, or its full UUID. |
| schedulerequired | integer | The schedule's numeric ID. |
Body
| Name | Type | Description |
|---|---|---|
| namerequired | string | |
| minuterequired | string | Cron minute field, such as 0, */5 or 0,30. |
| hourrequired | string | Cron hour field. |
| day_of_monthrequired | string | Cron day-of-month field. |
| monthrequired | string | Cron month field. Always send it, * for every month. |
| day_of_weekrequired | string | Cron day-of-week field, 0 or 7 being Sunday. |
| is_active | boolean | Whether the schedule runs on its timetable. False when left out. |
| only_when_online | boolean | Skip timed runs while the server is offline or stopping. False when left out. |
Example
curl -X POST "https://sillydev.co.uk/panel/api/client/servers/1a7ce997/schedules/{schedule}" \
-H "Authorization: Bearer $SILLYDEV_API_KEY" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{"name":"Nightly restart","minute":"30","hour":"3","day_of_month":"*","month":"*","day_of_week":"1-5","is_active":true,"only_when_online":true}'Response 200The updated schedule.
{
"object": "server_schedule",
"attributes": {
"id": 12,
"name": "Nightly restart",
"cron": {
"day_of_week": "1-5",
"day_of_month": "*",
"month": "*",
"hour": "3",
"minute": "30"
},
"is_active": true,
"is_processing": false,
"only_when_online": true,
"last_run_at": "2026-10-10T04:00:00+00:00",
"next_run_at": "2026-10-12T03:30:00+00:00",
"created_at": "2026-09-01T12:00:00+00:00",
"updated_at": "2026-10-10T12:00:00+00:00",
"relationships": {
"tasks": {
"object": "list",
"data": []
}
}
}
}Every field in the response
| Name | Type | Description |
|---|---|---|
| objectrequired | string | |
| attributesrequired | object | |
| attributes.idrequired | integer | |
| attributes.namerequired | string | |
| attributes.cronrequired | object | The five fields of a standard cron expression, in the panel's timezone. |
| attributes.cron.day_of_weekrequired | string | |
| attributes.cron.day_of_monthrequired | string | |
| attributes.cron.monthrequired | string | |
| attributes.cron.hourrequired | string | |
| attributes.cron.minuterequired | string | |
| attributes.is_activerequired | boolean | Whether the schedule runs on its timetable. |
| attributes.is_processingrequired | boolean | True while the schedule's tasks are being worked through. |
| attributes.only_when_onlinerequired | boolean | When true, a timed run is skipped if the server is offline or stopping. Manual runs ignore this. |
| attributes.last_run_atrequired | string (date-time) | null | |
| attributes.next_run_atrequired | string (date-time) | null | |
| attributes.created_atrequired | string (date-time) | |
| attributes.updated_atrequired | string (date-time) | |
| attributes.relationships | object | |
| attributes.relationships.tasks | object | |
| attributes.relationships.tasks.objectrequired | string | |
| attributes.relationships.tasks.datarequired | array of object |
Errors
- 400 The cron fields do not make a valid cron expression.
- 401 No API key was sent, or it is wrong, expired or deleted.
- 403 The key is valid but may not do this: it lacks the permission or account scope, it is limited to other servers or IP addresses, or the account may not do it at all.
- 404 There is no such resource, or the key cannot see it. Features that are switched off answer 404 too.
- 422 Some fields were missing or invalid. There is one error per problem, and
meta.source_fieldnames the field.
Delete a schedule
DELETE/servers/{server}/schedules/{schedule}
Permission schedule.delete
Deletes the schedule and all of its tasks.
Parameters
| Name | Type | Description |
|---|---|---|
| serverrequired | string | The server's 8-character identifier, as shown in the panel, or its full UUID. |
| schedulerequired | integer | The schedule's numeric ID. |
Example
curl -X DELETE "https://sillydev.co.uk/panel/api/client/servers/1a7ce997/schedules/{schedule}" \
-H "Authorization: Bearer $SILLYDEV_API_KEY" \
-H "Accept: application/json"Response 204Done. There is no response body.
Errors
- 401 No API key was sent, or it is wrong, expired or deleted.
- 403 The key is valid but may not do this: it lacks the permission or account scope, it is limited to other servers or IP addresses, or the account may not do it at all.
- 404 There is no such resource, or the key cannot see it. Features that are switched off answer 404 too.
Run a schedule now
POST/servers/{server}/schedules/{schedule}/execute
Permission schedule.update
Runs the schedule straight away, whether or not it is active and ignoring only_when_online. The first task runs during the request, without waiting its time_offset; the rest follow in the background as usual. Command tasks are skipped if the server is offline. A schedule with no tasks cannot be run.
Parameters
| Name | Type | Description |
|---|---|---|
| serverrequired | string | The server's 8-character identifier, as shown in the panel, or its full UUID. |
| schedulerequired | integer | The schedule's numeric ID. |
Example
curl -X POST "https://sillydev.co.uk/panel/api/client/servers/1a7ce997/schedules/{schedule}/execute" \
-H "Authorization: Bearer $SILLYDEV_API_KEY" \
-H "Accept: application/json"Response 202The schedule has started. The body is an empty JSON array.
[]
Errors
- 400 The schedule has no tasks.
- 401 No API key was sent, or it is wrong, expired or deleted.
- 403 The key is valid but may not do this: it lacks the permission or account scope, it is limited to other servers or IP addresses, or the account may not do it at all.
- 404 There is no such resource, or the key cannot see it. Features that are switched off answer 404 too.
Add a task to a schedule
POST/servers/{server}/schedules/{schedule}/tasks
Permission schedule.updatecontrol.consolecontrol.startcontrol.stopcontrol.restartbackup.create
Adds a task to the schedule, at the end or at sequence_id (later tasks move down one). Besides schedule.update you need the permission for what the task does: control.console for a command, backup.create for a backup, and control.start, control.stop or control.restart for a power action (kill needs control.stop). A schedule may hold at most 10 tasks, and a backup task cannot be added to a server that may not keep backups.
Parameters
| Name | Type | Description |
|---|---|---|
| serverrequired | string | The server's 8-character identifier, as shown in the panel, or its full UUID. |
| schedulerequired | integer | The schedule's numeric ID. |
Body
| Name | Type | Description |
|---|---|---|
| actionrequired | one of 'command', 'power', 'backup' | |
| payload | string | null | Required unless action is backup. For command, the console command; for power, one of start, stop, restart or kill; for backup, optional patterns of files to leave out, one per line. |
| time_offsetrequired | integer | Seconds to wait after the previous task before running this one. |
| sequence_id | integer | Where to put the task. Left out, a new task goes at the end and an existing one stays where it is. |
| continue_on_failure | boolean | Carry on with the next task if this one fails to reach the server. False when left out. |
Example
curl -X POST "https://sillydev.co.uk/panel/api/client/servers/1a7ce997/schedules/{schedule}/tasks" \
-H "Authorization: Bearer $SILLYDEV_API_KEY" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{"action":"command","payload":"say Restarting in 1 minute","time_offset":0}'Response 200The new task.
{
"object": "schedule_task",
"attributes": {
"id": 32,
"sequence_id": 2,
"action": "power",
"payload": "restart",
"time_offset": 60,
"is_queued": false,
"continue_on_failure": false,
"created_at": "2026-10-10T12:00:00+00:00",
"updated_at": "2026-10-10T12:00:00+00:00"
}
}Every field in the response
| Name | Type | Description |
|---|---|---|
| objectrequired | string | |
| attributesrequired | object | |
| attributes.idrequired | integer | |
| attributes.sequence_idrequired | integer | The task's place in the schedule, starting at 1. |
| attributes.actionrequired | one of 'command', 'power', 'backup' | |
| attributes.payloadrequired | string | For command, the console command. For power, one of start, stop, restart or kill. For backup, files to leave out of the backup, one pattern per line, or an empty string. |
| attributes.time_offsetrequired | integer | Seconds to wait after the previous task (or after the schedule starts) before running. |
| attributes.is_queuedrequired | boolean | True while the task is waiting to run. |
| attributes.continue_on_failurerequired | boolean | When true, the schedule carries on with the next task if this one fails because the node could not be reached or refused it. Otherwise the schedule stops there. |
| attributes.created_atrequired | string (date-time) | |
| attributes.updated_atrequired | string (date-time) |
Errors
- 400 The schedule already has as many tasks as it may.
- 401 No API key was sent, or it is wrong, expired or deleted.
- 403 The key lacks
schedule.updateor the permission for the task's action, or this is a backup task and the server's backup limit is 0. - 404 There is no such resource, or the key cannot see it. Features that are switched off answer 404 too.
- 422 Some fields were missing or invalid. There is one error per problem, and
meta.source_fieldnames the field.
Update a task
POST/servers/{server}/schedules/{schedule}/tasks/{task}
Permission schedule.updatecontrol.consolecontrol.startcontrol.stopcontrol.restartbackup.create
Replaces the task's action, payload, offset and failure setting; leaving out continue_on_failure sets it to false. Send sequence_id to move the task, and the tasks in between shift to make room. The same action permissions apply as for createScheduleTask.
Parameters
| Name | Type | Description |
|---|---|---|
| serverrequired | string | The server's 8-character identifier, as shown in the panel, or its full UUID. |
| schedulerequired | integer | The schedule's numeric ID. |
| taskrequired | integer | The task's numeric ID, which must belong to the schedule. |
Body
| Name | Type | Description |
|---|---|---|
| actionrequired | one of 'command', 'power', 'backup' | |
| payload | string | null | Required unless action is backup. For command, the console command; for power, one of start, stop, restart or kill; for backup, optional patterns of files to leave out, one per line. |
| time_offsetrequired | integer | Seconds to wait after the previous task before running this one. |
| sequence_id | integer | Where to put the task. Left out, a new task goes at the end and an existing one stays where it is. |
| continue_on_failure | boolean | Carry on with the next task if this one fails to reach the server. False when left out. |
Example
curl -X POST "https://sillydev.co.uk/panel/api/client/servers/1a7ce997/schedules/{schedule}/tasks/{task}" \
-H "Authorization: Bearer $SILLYDEV_API_KEY" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{"action":"command","payload":"say Restarting in 5 minutes","time_offset":0,"sequence_id":1}'Response 200The updated task.
{
"object": "schedule_task",
"attributes": {
"id": 31,
"sequence_id": 1,
"action": "command",
"payload": "say Restarting in 5 minutes",
"time_offset": 0,
"is_queued": false,
"continue_on_failure": false,
"created_at": "2026-09-01T12:00:00+00:00",
"updated_at": "2026-10-10T12:00:00+00:00"
}
}Every field in the response
| Name | Type | Description |
|---|---|---|
| objectrequired | string | |
| attributesrequired | object | |
| attributes.idrequired | integer | |
| attributes.sequence_idrequired | integer | The task's place in the schedule, starting at 1. |
| attributes.actionrequired | one of 'command', 'power', 'backup' | |
| attributes.payloadrequired | string | For command, the console command. For power, one of start, stop, restart or kill. For backup, files to leave out of the backup, one pattern per line, or an empty string. |
| attributes.time_offsetrequired | integer | Seconds to wait after the previous task (or after the schedule starts) before running. |
| attributes.is_queuedrequired | boolean | True while the task is waiting to run. |
| attributes.continue_on_failurerequired | boolean | When true, the schedule carries on with the next task if this one fails because the node could not be reached or refused it. Otherwise the schedule stops there. |
| attributes.created_atrequired | string (date-time) | |
| attributes.updated_atrequired | string (date-time) |
Errors
- 401 No API key was sent, or it is wrong, expired or deleted.
- 403 The key lacks
schedule.updateor the permission for the task's action, or this is a backup task and the server's backup limit is 0. - 404 There is no such resource, or the key cannot see it. Features that are switched off answer 404 too.
- 422 Some fields were missing or invalid. There is one error per problem, and
meta.source_fieldnames the field.
Delete a task
DELETE/servers/{server}/schedules/{schedule}/tasks/{task}
Permission schedule.update
Deletes the task. Tasks after it move up one place.
Parameters
| Name | Type | Description |
|---|---|---|
| serverrequired | string | The server's 8-character identifier, as shown in the panel, or its full UUID. |
| schedulerequired | integer | The schedule's numeric ID. |
| taskrequired | integer | The task's numeric ID, which must belong to the schedule. |
Example
curl -X DELETE "https://sillydev.co.uk/panel/api/client/servers/1a7ce997/schedules/{schedule}/tasks/{task}" \
-H "Authorization: Bearer $SILLYDEV_API_KEY" \
-H "Accept: application/json"Response 204Done. There is no response body.
Errors
- 401 No API key was sent, or it is wrong, expired or deleted.
- 403 The key is valid but may not do this: it lacks the permission or account scope, it is limited to other servers or IP addresses, or the account may not do it at all.
- 404 There is no such resource, or the key cannot see it. Features that are switched off answer 404 too.