API reference
Servers, power and console
List your servers, start and stop them, send console commands, watch the console live, and change how they start.
← API docs20 endpointsUpdated
Browse the docs
Servers
List the servers your key can reach, read one server's details, resource use and activity, and delete a server you own.
List servers
GET/
Lists the servers the key's user owns or is a subuser of, 50 a page by default and at most 100. A key limited to some servers only lists those. The default includes allocations and variables are always present, and egg and subusers can be added with include. If the account can buy paid servers, meta.pending_orders lists paid servers that have been bought but do not exist yet.
Parameters
| Name | Type | Description |
|---|---|---|
| page | integer | The page of results to return, starting at 1. |
| per_page | integer | How many servers to return on each page. Values above 100 are treated as 100. |
| type | one of 'owner', 'admin', 'admin-all' | Which servers to list. Leave it out for every server you own or are a subuser of; owner lists only the servers you own. admin (servers you can reach only as an administrator) and admin-all (every server) are for administrators: anyone else gets an empty list, and a key limited to some servers or permissions ignores them. |
| filter[*] | string | A general search. An IPv4 address, ip:port or :port matches the server's allocations; anything else matches the start of the UUID, the 8-character identifier, the external ID, or part of the name (case-insensitive). |
| filter[uuid] | string | Servers whose UUID contains this text. |
| filter[name] | string | Servers whose name contains this text. |
| filter[description] | string | Servers whose description contains this text. |
| filter[external_id] | string | Servers whose external ID contains this text. |
| include | string | Extra relationships to add to each server, comma-separated: egg and/or subusers. subusers comes back as a null_resource on servers where you lack user.read. |
Example
curl "https://sillydev.co.uk/panel/api/client/" \ -H "Authorization: Bearer $SILLYDEV_API_KEY" \ -H "Accept: application/json"
Response 200A page of servers.
{
"object": "list",
"data": [
{
"object": "server",
"attributes": {
"server_owner": true,
"identifier": "1a7ce997",
"__deprecated_uuid_short": "1a7ce997",
"server_identifier": "serv_DJ5MXFRFJ5JFFDSOJZHE5RQCUU",
"internal_id": 4127,
"uuid": "1a7ce997-259b-452e-8b4e-cecc464142ca",
"name": "My Discord bot",
"node": "London 3",
"is_node_under_maintenance": false,
"sftp_details": {
"ip": "lon3.sillydev.co.uk",
"port": 2022
},
"description": "",
"limits": {
"memory": 256,
"swap": 0,
"disk": 512,
"io": 500,
"cpu": 25,
"threads": null,
"oom_disabled": true
},
"invocation": "node /home/container/index.js",
"docker_image": "ghcr.io/pterodactyl/yolks:nodejs_22",
"egg_features": null,
"feature_limits": {
"allocations": 1,
"backups": 2
},
"status": null,
"is_paid": false,
"is_suspended": false,
"is_installing": false,
"is_transferring": false,
"skip_scripts": false,
"relationships": {
"allocations": {
"object": "list",
"data": [
{
"object": "allocation",
"attributes": {
"id": 9921,
"ip": "203.0.113.10",
"ip_alias": null,
"port": 25565,
"notes": null,
"is_default": true
}
}
]
},
"variables": {
"object": "list",
"data": [
{
"object": "egg_variable",
"attributes": {
"name": "Main file",
"description": "The file the bot is started from.",
"env_variable": "MAIN_FILE",
"default_value": "index.js",
"server_value": "index.js",
"is_editable": true,
"rules": "required|string|max:64"
}
}
]
}
}
}
}
],
"meta": {
"pagination": {
"total": 1,
"count": 1,
"per_page": 50,
"current_page": 1,
"total_pages": 1,
"links": []
},
"pending_orders": [
{
"uuid": "6f1d0c2e-8a7b-4c33-9b1e-2f0a5d4c7e91",
"name": "My paid bot",
"runtime": "python",
"status": "provisioning",
"attempts": 1,
"limits": {
"memory": 1024,
"disk": 2048,
"cpu": 100
},
"created_at": "2026-10-10T12:00:00+00:00"
}
]
}
}Every field in the response
| Name | Type | Description |
|---|---|---|
| objectrequired | string | |
| datarequired | array of object | |
| data[].objectrequired | string | |
| data[].attributesrequired | object | A server, as the key's user sees it. |
| data[].attributes.server_ownerrequired | boolean | Whether the key's user owns this server (rather than being a subuser or administrator). |
| data[].attributes.identifierrequired | string | The 8-character identifier used in panel URLs and accepted by the {server} path parameter. |
| data[].attributes.__deprecated_uuid_shortrequired | string | The same as identifier. |
| data[].attributes.server_identifierrequired | string | A prefixed internal identifier (serv_...). Not accepted in paths; use identifier or uuid. |
| data[].attributes.internal_idrequired | integer | The server's numeric database ID. |
| data[].attributes.uuidrequired | string (uuid) | |
| data[].attributes.namerequired | string | |
| data[].attributes.noderequired | string | The name of the node the server runs on. |
| data[].attributes.is_node_under_maintenancerequired | boolean | While true, most endpoints for the server answer 409. |
| data[].attributes.sftp_detailsrequired | object | |
| data[].attributes.sftp_details.iprequired | string | The SFTP host name. |
| data[].attributes.sftp_details.portrequired | integer | |
| data[].attributes.descriptionrequired | string | null | |
| data[].attributes.limitsrequired | object | |
| data[].attributes.limits.memoryrequired | integer | Memory limit in MiB. 0 means unlimited. |
| data[].attributes.limits.swaprequired | integer | Swap in MiB. 0 means none and -1 unlimited. |
| data[].attributes.limits.diskrequired | integer | Disk limit in MiB. 0 means unlimited. |
| data[].attributes.limits.iorequired | integer | Block IO weight, 10 to 1000. |
| data[].attributes.limits.cpurequired | integer | CPU limit as a percentage of one core (100 is one core). 0 means unlimited. |
| data[].attributes.limits.threadsrequired | string | null | The CPU cores the server is pinned to, e.g. 0-1,3, or null for any. |
| data[].attributes.limits.oom_disabledrequired | boolean | Whether the out-of-memory killer is disabled for the server. |
| data[].attributes.invocationrequired | string | The startup command with variables filled in. Without startup.read the variable values are hidden. |
| data[].attributes.docker_imagerequired | string | |
| data[].attributes.egg_featuresrequired | array of string | null | Panel features the server's egg turns on. |
| data[].attributes.feature_limitsrequired | object | |
| data[].attributes.feature_limits.allocationsrequired | integer | The most allocations (ports) the server may have. |
| data[].attributes.feature_limits.backupsrequired | integer | The most backups the server may keep. |
| data[].attributes.statusrequired | one of null, 'installing', 'install_failed', 'reinstall_failed', 'suspended', 'billing_suspended', 'restoring_backup', 'deleting' | What the server is doing, or null when it is installed and available.
- installing: the install script is running.
- install_failed / reinstall_failed: the install script failed. A server whose first install failed can still be reinstalled.
- suspended: suspended by an administrator.
- billing_suspended: paused because its subscription is unpaid.
- restoring_backup: a backup is being restored.
- deleting: deletion has been accepted and the node is removing it. |
| data[].attributes.is_paidrequired | boolean | Whether someone is currently paying for the server. |
| data[].attributes.is_suspendedrequired | boolean | True when status is suspended or billing_suspended. Use status. |
| data[].attributes.is_installingrequired | boolean | True when status is installing or install_failed. Use status. |
| data[].attributes.is_transferringrequired | boolean | Whether the server is being moved to another node. Most endpoints answer 409 while it is. |
| data[].attributes.skip_scriptsrequired | boolean | Whether the egg's install script is skipped for this server. |
| data[].attributes.relationships | object | |
| data[].attributes.relationships.allocations | object | The server's allocations. Always included. Without allocation.read only the primary allocation is listed, with notes null. |
| data[].attributes.relationships.variables | any | The startup variables you can see. Always included; a null_resource without startup.read. |
| data[].attributes.relationships.egg | object | The egg (runtime template) the server uses. Only with include=egg. |
| data[].attributes.relationships.subusers | any | The server's subusers. Only with include=subusers; a null_resource without user.read. |
| metarequired | object | |
| meta.paginationrequired | object | |
| meta.pagination.total | integer | |
| meta.pagination.count | integer | |
| meta.pagination.per_page | integer | |
| meta.pagination.current_page | integer | |
| meta.pagination.total_pages | integer | |
| meta.pagination.links | object | |
| meta.pagination.links.previous | string (uri) | |
| meta.pagination.links.next | string (uri) | |
| meta.pending_orders | array of object | Paid servers you have bought that do not exist yet. Only present when the account can buy paid servers. |
| meta.pending_orders[].uuidrequired | string (uuid) | The order's UUID (not a server UUID). |
| meta.pending_orders[].namerequired | string | |
| meta.pending_orders[].runtimerequired | string | null | The runtime chosen, e.g. nodejs, python or bun. |
| meta.pending_orders[].statusrequired | one of 'provisioning', 'pending_deployment' | provisioning while the server is being created, pending_deployment while it waits for room on a node. |
| meta.pending_orders[].attemptsrequired | integer | How many times creating the server has been tried. |
| meta.pending_orders[].limitsrequired | object | The paid plan's limits. |
| meta.pending_orders[].limits.memoryrequired | integer | MiB. |
| meta.pending_orders[].limits.diskrequired | integer | MiB. |
| meta.pending_orders[].limits.cpurequired | integer | Percent of one core. |
| meta.pending_orders[].created_atrequired | string (date-time) | null |
Errors
- 401 No API key was sent, or it is wrong, expired or deleted.
- 429 Too many requests. Wait for the number of seconds in the
Retry-Afterheader, then try again.
List subuser permissions
GET/permissions
Returns every server permission that exists, grouped, with a description of each. Use it to build a permission picker or to check the strings used in x-permission and in subuser and API key permission lists; a permission is written group.key, e.g. control.start.
Example
curl "https://sillydev.co.uk/panel/api/client/permissions" \ -H "Authorization: Bearer $SILLYDEV_API_KEY" \ -H "Accept: application/json"
Response 200All server permissions.
{
"object": "system_permissions",
"attributes": {
"permissions": {
"websocket": {
"description": "Allows the user to connect to the server websocket, giving them access to view console output and realtime server stats.",
"keys": {
"connect": "Allows a user to connect to the websocket instance for a server to stream the console."
}
},
"control": {
"description": "Permissions that control a user's ability to control the power state of a server, or send commands.",
"keys": {
"console": "Allows a user to send commands to the server instance via the console.",
"start": "Allows a user to start the server if it is stopped.",
"stop": "Allows a user to stop a server if it is running.",
"restart": "Allows a user to perform a server restart. This allows them to start the server if it is offline, but not put the server in a completely stopped state."
}
}
}
}
}Every field in the response
| Name | Type | Description |
|---|---|---|
| objectrequired | string | |
| attributesrequired | object | |
| attributes.permissionsrequired | object | Permission groups by name (e.g. control, file). |
Errors
- 401 No API key was sent, or it is wrong, expired or deleted.
Get resource use of several servers
GET/resources
Returns the live resource use of up to 100 servers in one request, keyed by server UUID. A server is silently left out if you could not read it on its own, if it is suspended, installing, being transferred, restoring a backup, being deleted or on a node under maintenance, or if its node did not answer. Answers are cached for up to 20 seconds (3 seconds while a server is booting), so polling faster gains nothing.
Parameters
| Name | Type | Description |
|---|---|---|
| serversrequired | string | Comma-separated full server UUIDs (not 8-character identifiers). Duplicates are ignored and only the first 100 are used. |
Example
curl "https://sillydev.co.uk/panel/api/client/resources" \ -H "Authorization: Bearer $SILLYDEV_API_KEY" \ -H "Accept: application/json"
Response 200The usage of each server that could be read, keyed by UUID. When none could be read, `data` is an empty object.
{
"object": "server_stats_list",
"data": {
"1a7ce997-259b-452e-8b4e-cecc464142ca": {
"object": "stats",
"attributes": {
"current_state": "running",
"is_suspended": false,
"is_booting": false,
"resources": {
"memory_bytes": 83886080,
"cpu_absolute": 1.25,
"disk_bytes": 41943040,
"network_rx_bytes": 102400,
"network_tx_bytes": 51200,
"uptime": 3600000
}
}
}
}
}Every field in the response
| Name | Type | Description |
|---|---|---|
| objectrequired | string | |
| datarequired | object |
Errors
- 401 No API key was sent, or it is wrong, expired or deleted.
- 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 server
GET/servers/{server}
Returns one server with its allocations and startup variables. This works whatever state the server is in (installing, suspended, being transferred or being deleted), so it is the endpoint to poll while waiting for a state to change. meta says whether you own the server and which permissions you (as limited by your key) have on it; * means all of them.
Parameters
| Name | Type | Description |
|---|---|---|
| serverrequired | string | The server's 8-character identifier, as shown in the panel, or its full UUID. |
| include | string | Extra relationships, comma-separated: egg and/or subusers. subusers comes back as a null_resource if you lack user.read. |
Example
curl "https://sillydev.co.uk/panel/api/client/servers/1a7ce997" \ -H "Authorization: Bearer $SILLYDEV_API_KEY" \ -H "Accept: application/json"
Response 200The server.
{
"object": "server",
"attributes": {
"server_owner": true,
"identifier": "1a7ce997",
"__deprecated_uuid_short": "1a7ce997",
"server_identifier": "serv_DJ5MXFRFJ5JFFDSOJZHE5RQCUU",
"internal_id": 4127,
"uuid": "1a7ce997-259b-452e-8b4e-cecc464142ca",
"name": "My Discord bot",
"node": "London 3",
"is_node_under_maintenance": false,
"sftp_details": {
"ip": "lon3.sillydev.co.uk",
"port": 2022
},
"description": "Moderation bot for my server",
"limits": {
"memory": 256,
"swap": 0,
"disk": 512,
"io": 500,
"cpu": 25,
"threads": null,
"oom_disabled": true
},
"invocation": "python /home/container/bot.py",
"docker_image": "ghcr.io/pterodactyl/yolks:python_3.12",
"egg_features": null,
"feature_limits": {
"allocations": 1,
"backups": 2
},
"status": null,
"is_paid": false,
"is_suspended": false,
"is_installing": false,
"is_transferring": false,
"skip_scripts": false,
"relationships": {
"allocations": {
"object": "list",
"data": [
{
"object": "allocation",
"attributes": {
"id": 9921,
"ip": "203.0.113.10",
"ip_alias": null,
"port": 25565,
"notes": null,
"is_default": true
}
}
]
},
"variables": {
"object": "list",
"data": [
{
"object": "egg_variable",
"attributes": {
"name": "Bot file",
"description": "The Python file the bot is started from.",
"env_variable": "BOT_PY_FILE",
"default_value": "bot.py",
"server_value": "bot.py",
"is_editable": true,
"rules": "required|string|max:64"
}
}
]
},
"egg": {
"object": "egg",
"attributes": {
"uuid": "3e9d5a1c-7f42-4b8e-a1d6-0c5b9f2e8d47",
"name": "Python"
}
}
}
},
"meta": {
"is_server_owner": true,
"user_permissions": [
"*"
]
}
}Every field in the response
| Name | Type | Description |
|---|---|---|
| objectrequired | string | |
| attributesrequired | object | A server, as the key's user sees it. |
| attributes.server_ownerrequired | boolean | Whether the key's user owns this server (rather than being a subuser or administrator). |
| attributes.identifierrequired | string | The 8-character identifier used in panel URLs and accepted by the {server} path parameter. |
| attributes.__deprecated_uuid_shortrequired | string | The same as identifier. |
| attributes.server_identifierrequired | string | A prefixed internal identifier (serv_...). Not accepted in paths; use identifier or uuid. |
| attributes.internal_idrequired | integer | The server's numeric database ID. |
| attributes.uuidrequired | string (uuid) | |
| attributes.namerequired | string | |
| attributes.noderequired | string | The name of the node the server runs on. |
| attributes.is_node_under_maintenancerequired | boolean | While true, most endpoints for the server answer 409. |
| attributes.sftp_detailsrequired | object | |
| attributes.sftp_details.iprequired | string | The SFTP host name. |
| attributes.sftp_details.portrequired | integer | |
| attributes.descriptionrequired | string | null | |
| attributes.limitsrequired | object | |
| attributes.limits.memoryrequired | integer | Memory limit in MiB. 0 means unlimited. |
| attributes.limits.swaprequired | integer | Swap in MiB. 0 means none and -1 unlimited. |
| attributes.limits.diskrequired | integer | Disk limit in MiB. 0 means unlimited. |
| attributes.limits.iorequired | integer | Block IO weight, 10 to 1000. |
| attributes.limits.cpurequired | integer | CPU limit as a percentage of one core (100 is one core). 0 means unlimited. |
| attributes.limits.threadsrequired | string | null | The CPU cores the server is pinned to, e.g. 0-1,3, or null for any. |
| attributes.limits.oom_disabledrequired | boolean | Whether the out-of-memory killer is disabled for the server. |
| attributes.invocationrequired | string | The startup command with variables filled in. Without startup.read the variable values are hidden. |
| attributes.docker_imagerequired | string | |
| attributes.egg_featuresrequired | array of string | null | Panel features the server's egg turns on. |
| attributes.feature_limitsrequired | object | |
| attributes.feature_limits.allocationsrequired | integer | The most allocations (ports) the server may have. |
| attributes.feature_limits.backupsrequired | integer | The most backups the server may keep. |
| attributes.statusrequired | one of null, 'installing', 'install_failed', 'reinstall_failed', 'suspended', 'billing_suspended', 'restoring_backup', 'deleting' | What the server is doing, or null when it is installed and available.
- installing: the install script is running.
- install_failed / reinstall_failed: the install script failed. A server whose first install failed can still be reinstalled.
- suspended: suspended by an administrator.
- billing_suspended: paused because its subscription is unpaid.
- restoring_backup: a backup is being restored.
- deleting: deletion has been accepted and the node is removing it. |
| attributes.is_paidrequired | boolean | Whether someone is currently paying for the server. |
| attributes.is_suspendedrequired | boolean | True when status is suspended or billing_suspended. Use status. |
| attributes.is_installingrequired | boolean | True when status is installing or install_failed. Use status. |
| attributes.is_transferringrequired | boolean | Whether the server is being moved to another node. Most endpoints answer 409 while it is. |
| attributes.skip_scriptsrequired | boolean | Whether the egg's install script is skipped for this server. |
| attributes.relationships | object | |
| attributes.relationships.allocations | object | The server's allocations. Always included. Without allocation.read only the primary allocation is listed, with notes null. |
| attributes.relationships.allocations.objectrequired | string | |
| attributes.relationships.allocations.datarequired | array of object | |
| attributes.relationships.variables | any | The startup variables you can see. Always included; a null_resource without startup.read. |
| attributes.relationships.egg | object | The egg (runtime template) the server uses. Only with include=egg. |
| attributes.relationships.egg.objectrequired | string | |
| attributes.relationships.egg.attributesrequired | object | |
| attributes.relationships.egg.attributes.uuidrequired | string (uuid) | |
| attributes.relationships.egg.attributes.namerequired | string | |
| attributes.relationships.subusers | any | The server's subusers. Only with include=subusers; a null_resource without user.read. |
| metarequired | object | |
| meta.is_server_ownerrequired | boolean | Whether the key's user owns this server. |
| meta.user_permissionsrequired | array of string | The permissions you have on this server. Owners and administrators get ["*"] (administrators also get admin.websocket.* entries), subusers get their list, and a key limited to some permissions only gets those. |
Errors
- 401 No API key was sent, or it is wrong, expired or deleted.
- 404 There is no such resource, or the key cannot see it. Features that are switched off answer 404 too.
- 429 Too many requests. Wait for the number of seconds in the
Retry-Afterheader, then try again.
Delete a server
DELETE/servers/{server}
Permanently deletes the server and its files. Only the server's owner can do this, with a key that is not limited to a set of permissions; subusers cannot, and it cannot be delegated. Deletion is asynchronous: once the node accepts it the server's status becomes deleting and every other endpoint for it answers 409 until the node has removed it, after which it is gone (GET returns 404). If the node cannot be reached nothing is deleted and the error is returned. A paid server whose subscription is still set to renew is refused with 400: schedule a downgrade first.
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 | The server's current name, as a confirmation. It must match exactly, including case; surrounding spaces are ignored. |
Example
curl -X DELETE "https://sillydev.co.uk/panel/api/client/servers/1a7ce997" \
-H "Authorization: Bearer $SILLYDEV_API_KEY" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{"name":"My Discord bot"}'Response 204Done. There is no response body.
Errors
- 400 The request could not be carried out as sent.
detailsays why. - 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.
- 409 The resource is busy or in a state that does not allow this right now.
- 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 server's resource use
GET/servers/{server}/resources
Returns the server's power state and current memory, CPU, disk and network use, as reported by its node. The answer is cached for up to 20 seconds (3 seconds while the server is booting); for a live feed use the websocket's stats events instead. Any server permission is enough to read it.
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/resources" \ -H "Authorization: Bearer $SILLYDEV_API_KEY" \ -H "Accept: application/json"
Response 200The server's resource use.
{
"object": "stats",
"attributes": {
"current_state": "running",
"is_suspended": false,
"is_booting": false,
"resources": {
"memory_bytes": 83886080,
"cpu_absolute": 1.25,
"disk_bytes": 41943040,
"network_rx_bytes": 102400,
"network_tx_bytes": 51200,
"uptime": 3600000
}
}
}Every field in the response
| Name | Type | Description |
|---|---|---|
| objectrequired | string | |
| attributesrequired | object | |
| attributes.current_staterequired | one of 'offline', 'starting', 'running', 'stopping' | |
| attributes.is_suspendedrequired | boolean | |
| attributes.is_bootingrequired | boolean | True while the node is still loading the server after a restart. |
| attributes.resourcesrequired | object | |
| attributes.resources.memory_bytesrequired | integer | |
| attributes.resources.cpu_absoluterequired | number | CPU use as a percentage of one core, e.g. 150 is one and a half cores. |
| attributes.resources.disk_bytesrequired | integer | |
| attributes.resources.network_rx_bytesrequired | integer | Bytes received since the server started. |
| attributes.resources.network_tx_bytesrequired | integer | Bytes sent since the server started. |
| attributes.resources.uptimerequired | integer | Milliseconds since the server started. 0 when offline. |
Errors
- 401 No API key was sent, or it is wrong, expired or deleted.
- 404 There is no such resource, or the key cannot see it. Features that are switched off answer 404 too.
- 409 The resource is busy or in a state that does not allow this right now.
- 429 Too many requests. Wait for the number of seconds in the
Retry-Afterheader, then try again.
List a server's activity
GET/servers/{server}/activity
Permission activity.read
Lists what has been done to the server and by whom: power actions, commands, file changes, settings changes and so on, 25 a page by default. Actions taken by administrators are left out. IP addresses are only shown for your own actions.
Parameters
| Name | Type | Description |
|---|---|---|
| serverrequired | string | The server's 8-character identifier, as shown in the panel, or its full UUID. |
| page | integer | The page of results to return, starting at 1. |
| per_page | integer | How many entries to return on each page. Values above 100 are treated as 100. |
| sort | one of 'timestamp', '-timestamp' | -timestamp for newest first or timestamp for oldest first. Without it the order is not guaranteed. |
| filter[event] | string | Only entries whose event name contains this text, e.g. server:power. |
| include | one of 'actor' | actor adds the user who did each thing as relationships.actor. |
Example
curl "https://sillydev.co.uk/panel/api/client/servers/1a7ce997/activity" \ -H "Authorization: Bearer $SILLYDEV_API_KEY" \ -H "Accept: application/json"
Response 200A page of activity entries.
{
"object": "list",
"data": [
{
"object": "activity_log",
"attributes": {
"id": "3f786850e387550fdab836ed7e6dc881de23001b",
"batch": null,
"event": "server:power.start",
"is_api": true,
"ip": "198.51.100.7",
"description": null,
"properties": [],
"has_additional_metadata": false,
"timestamp": "2026-10-10T12:00:00+00:00",
"relationships": {
"actor": {
"object": "user",
"attributes": {
"uuid": "0b9c4e2a-6d1f-4f8a-9c3e-5a7b2d1e8f60",
"identifier": "user_BFZ4QKTPNVHU7HUYLUOHRH4QMA",
"username": "you",
"email": "[email protected]",
"image": "https://gravatar.com/avatar/00000000000000000000000000000000",
"2fa_enabled": true,
"created_at": "2026-01-15T09:30:00+00:00"
}
}
}
}
}
],
"meta": {
"pagination": {
"total": 1,
"count": 1,
"per_page": 25,
"current_page": 1,
"total_pages": 1,
"links": []
}
}
}Every field in the response
| Name | Type | Description |
|---|---|---|
| objectrequired | string | |
| datarequired | array of object | |
| data[].objectrequired | string | |
| data[].attributesrequired | object | One thing that was done, by whom and when. |
| data[].attributes.idrequired | string | A stable unique key for the entry (a hash, not a database ID). |
| data[].attributes.batchrequired | string (uuid) | null | Shared by entries logged together as part of one action. |
| data[].attributes.eventrequired | string | The event name, e.g. server:power.start or server:file.write. |
| data[].attributes.is_apirequired | boolean | Whether it was done with an API key. |
| data[].attributes.iprequired | string | null | The IP address it came from. Only shown for your own actions (or to administrators). |
| data[].attributes.descriptionrequired | string | null | |
| data[].attributes.propertiesrequired | object | Details of the event, which vary by event. List values also get a <key>_count entry (or count, if there is only one list). An ip property is [hidden] unless it was your action. |
| data[].attributes.has_additional_metadatarequired | boolean | Whether properties holds anything beyond what the event's description already says. |
| data[].attributes.timestamprequired | string (date-time) | |
| data[].attributes.relationships | object | |
| data[].attributes.relationships.actor | any | Who did it. Only with include=actor; a null_resource if it was not a user (e.g. the system or a schedule). |
| metarequired | object | |
| meta.paginationrequired | object | |
| meta.pagination.total | integer | |
| meta.pagination.count | integer | |
| meta.pagination.per_page | integer | |
| meta.pagination.current_page | integer | |
| meta.pagination.total_pages | integer | |
| meta.pagination.links | object | |
| meta.pagination.links.previous | string (uri) | |
| meta.pagination.links.next | string (uri) |
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.
- 409 The resource is busy or in a state that does not allow this right now.
- 429 Too many requests. Wait for the number of seconds in the
Retry-Afterheader, then try again.
Power and console
Start, stop, restart and kill a server, send console commands, share console output, and get a token for the live console websocket.
Get console websocket credentials
GET/servers/{server}/websocket
Permission websocket.connectLimited to 5 per minute per server (shared by all users of the server)
Returns a short-lived token and the URL of the server's live console websocket, which streams console output, status changes and resource use, and accepts commands and power actions. The token lasts 10 minutes and carries your permissions on the server at the time it was issued.
Connecting. Open a websocket to data.socket. The node checks the Origin
header, so clients outside a browser must send Origin: https://sillydev.co.uk.
Every message in both directions is a JSON text frame {"event": "<name>", "args":
["..."]}, where args is always a list of strings (and may be left out). First send
{"event": "auth", "args": ["<token>"]}. The node answers auth success, then sends
the current status (and, if the server is offline, a stats message). Nothing else
is sent or accepted until you have authenticated.
Main events. Send send logs to get recent console history (only while the
server is running; each line arrives as a console output event), send command
with the command as args[0] (needs control.console, ignored while the server is
offline), set state with start, stop, restart or kill as args[0] (needs
the matching control.* permission), and send stats for an immediate stats
message. You receive console output (one line per message), status (offline,
starting, running or stopping), stats (whose args[0] is a JSON string with
memory_bytes, memory_limit_bytes, cpu_absolute, network.rx_bytes,
network.tx_bytes, uptime in milliseconds, state and disk_bytes), and
daemon message (notes from the node, e.g. about installation).
Keeping the token fresh. About a minute before the token expires the node sends
token expiring, and token expired once it has. Call this endpoint again and send
a new auth message on the same connection; there is no need to reconnect. A
problem with the token arrives as jwt error, other failures as daemon error, and
sending too fast as throttled (with the event name as args[0]). The node limits
auth and send logs to 2 every 5 seconds, send command to 10 a second and other
events to 4 a second.
Close codes. The node closes the connection with code 4409 if the server is suspended (do not reconnect) and 4410 while it is still loading the server after a node restart (wait a few seconds and connect again).
This endpoint itself is limited to 5 requests a minute per server, shared by everyone using that server.
Parameters
| Name | Type | Description |
|---|---|---|
| serverrequired | string | The server's 8-character identifier, as shown in the panel, or its full UUID. |
Messages
| Name | Type | Description |
|---|---|---|
| auth | you send | Authenticate, or re-authenticate with a fresh token. args[0] is the token from this endpoint. |
| send logs | you send | Ask for recent console history. Lines arrive as console output events. Ignored while the server is not running. |
| send command | you send | Type a command into the console. args[0] is the command. Needs control.console; ignored while the server is offline. |
| set state | you send | Send a power action. args[0] is start, stop, restart or kill. Needs control.start, control.stop (also for kill) or control.restart. |
| send stats | you send | Ask for a stats message straight away. |
| auth success | you receive | The token was accepted. |
| console output | you receive | One line of console output in args[0]. |
| status | you receive | The server's power state changed. args[0] is offline, starting, running or stopping. |
| stats | you receive | Resource use. args[0] is a JSON string with memory_bytes, memory_limit_bytes, cpu_absolute, network (rx_bytes, tx_bytes), uptime (milliseconds), state and disk_bytes. |
| daemon message | you receive | A message from the node rather than the server's own output, such as installation progress. |
| install started | you receive | The server's install script has started. |
| install output | you receive | One line of install script output. Only sent to administrators. |
| install completed | you receive | The server's install script has finished. |
| backup completed | you receive | A backup finished. The event name is backup completed:<backup uuid> and args[0] is a JSON string describing the result. Needs backup.read. |
| backup restore completed | you receive | Restoring a backup finished. |
| transfer status | you receive | The status of a transfer of the server to another node. |
| transfer logs | you receive | Transfer log output. Only sent to administrators. |
| token expiring | you receive | The token expires within about a minute. Get a new one from this endpoint and send auth again. |
| token expired | you receive | The token has expired. Get a new one and send auth again. |
| jwt error | you receive | The token is missing, expired, for another server or otherwise invalid. args[0] says why. |
| daemon error | you receive | Handling a message failed. args[0] is an error message with a reference ID. |
| throttled | you receive | Messages of the event named in args[0] are being dropped because they were sent too fast. |
Example
curl "https://sillydev.co.uk/panel/api/client/servers/1a7ce997/websocket" \ -H "Authorization: Bearer $SILLYDEV_API_KEY" \ -H "Accept: application/json"
Response 200A websocket token and address.
{
"data": {
"token": "eyJhbGciOi...",
"socket": "wss://lon3.sillydev.co.uk:8080/api/servers/1a7ce997-259b-452e-8b4e-cecc464142ca/ws"
}
}Every field in the response
| Name | Type | Description |
|---|---|---|
| datarequired | object | |
| data.tokenrequired | string | A signed token valid for 10 minutes. Send it in the auth event. |
| data.socketrequired | string (uri) | The websocket URL (wss://) on the server's node. |
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.
- 409 The resource is busy or in a state that does not allow this right now.
- 429 Too many requests. Wait for the number of seconds in the
Retry-Afterheader, then try again.
Send a console command
POST/servers/{server}/command
Permission control.console
Types a command into the server's console, as if entered in the panel. The server must be running: if it is not, the request fails with 502. The command's output is not returned; read it from the websocket.
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 |
|---|---|---|
| commandrequired | string | The command, without a trailing newline. |
Example
curl -X POST "https://sillydev.co.uk/panel/api/client/servers/1a7ce997/command" \
-H "Authorization: Bearer $SILLYDEV_API_KEY" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{"command":"reload"}'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.
- 409 The resource is busy or in a state that does not allow this right now.
- 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. - 502 The server is not running, or its node could not be reached.
Share console output
POST/servers/{server}/logs/share
Permission websocket.connectLimited to 6 per minute per user
Uploads console text you send to mclo.gs, a public paste site, and returns its link. Email addresses, tokens, passwords, credentials in URLs, IP addresses and private keys are replaced with placeholders such as [token] first, but check before sharing the link: the paste is public. Text over mclo.gs's limits (25,000 lines or 10 MiB) is cut from the start, keeping the latest output.
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 |
|---|---|---|
| contentrequired | string | The console text to share. The panel does not fetch it from the server; you send it. |
Example
curl -X POST "https://sillydev.co.uk/panel/api/client/servers/1a7ce997/logs/share" \
-H "Authorization: Bearer $SILLYDEV_API_KEY" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{"content":"Logged in as My Discord bot#1234\nError: Missing Access\n at RequestHandler.execute"}'Response 200The public link to the shared log.
{
"url": "https://mclo.gs/aB3dE5f"
}Every field in the response
| Name | Type | Description |
|---|---|---|
| urlrequired | string (uri) |
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.
- 409 The resource is busy or in a state that does not allow this right now.
- 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. - 502 mclo.gs could not take the log. Try again in a moment.
Start, stop, restart or kill a server
POST/servers/{server}/power
Permission control.startcontrol.stopcontrol.restart
Sends a power action to the server. The node accepts it straight away and carries it
out in the background, so a 204 means the action was accepted, not that it has
finished: watch status on the websocket or poll the resources endpoint.
- start starts the server if it is stopped.
- stop stops it gracefully with the egg's stop command, and also cancels a start
that has not yet started the container.
- restart stops it gracefully and starts it again (or just starts it if stopped).
- kill stops the container immediately, which can lose unsaved data. It skips the
queue below and cancels any start or restart in progress.
A server runs one power action at a time; one sent while another is running waits, and only the most recent waiting action is kept. Starts also wait their turn in the node's start queue when many servers are starting at once (paid servers go first), and the console says so while they wait. Suspended servers cannot be started.
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 |
|---|---|---|
| signalrequired | one of 'start', 'stop', 'restart', 'kill' |
Example
curl -X POST "https://sillydev.co.uk/panel/api/client/servers/1a7ce997/power" \
-H "Authorization: Bearer $SILLYDEV_API_KEY" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{"signal":"restart"}'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.
- 409 The resource is busy or in a state that does not allow this right now.
- 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.
Settings
Rename a server, reinstall it, and change the Docker image it runs on.
Rename a server
POST/servers/{server}/settings/rename
Permission settings.rename
Changes the server's name and, optionally, its description. Leave description out to keep the current one; send null or an empty string to clear it. On a paid server the new name is also shown on invoices.
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 | |
| description | string | null |
Example
curl -X POST "https://sillydev.co.uk/panel/api/client/servers/1a7ce997/settings/rename" \
-H "Authorization: Bearer $SILLYDEV_API_KEY" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{"name":"My Discord bot","description":"Moderation bot for my server"}'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.
- 409 The resource is busy or in a state that does not allow this right now.
- 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.
Reinstall a server
POST/servers/{server}/settings/reinstall
Permission settings.reinstall
Stops the server and runs its install script again. The server's status becomes installing until the script finishes, and most endpoints answer 409 meanwhile. This is also the one thing you can still do to a server whose install failed (status install_failed). Servers set to skip install scripts cannot be reinstalled (400) unless their install failed.
Parameters
| Name | Type | Description |
|---|---|---|
| serverrequired | string | The server's 8-character identifier, as shown in the panel, or its full UUID. |
Example
curl -X POST "https://sillydev.co.uk/panel/api/client/servers/1a7ce997/settings/reinstall" \ -H "Authorization: Bearer $SILLYDEV_API_KEY" \ -H "Accept: application/json"
Response 202The reinstall has started. The body is an empty JSON array.
[]
Errors
- 400 The request could not be carried out as sent.
detailsays why. - 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.
- 409 The resource is busy or in a state that does not allow this right now.
- 429 Too many requests. Wait for the number of seconds in the
Retry-Afterheader, then try again.
Change the Docker image
PUT/servers/{server}/settings/docker-image
Permission startup.docker-image
Switches the server to another of the Docker images its egg offers, for example a newer Node.js or Python version. The list of choices is meta.docker_images from the startup endpoint. It takes effect the next time the server starts. If an administrator set a custom image, it cannot be changed here (400).
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 |
|---|---|---|
| docker_imagerequired | string | One of the image values (not the display names) in the startup endpoint's meta.docker_images. |
Example
curl -X PUT "https://sillydev.co.uk/panel/api/client/servers/1a7ce997/settings/docker-image" \
-H "Authorization: Bearer $SILLYDEV_API_KEY" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{"docker_image":"ghcr.io/pterodactyl/yolks:nodejs_22"}'Response 204Done. There is no response body.
Errors
- 400 The request could not be carried out as sent.
detailsays why. - 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.
- 409 The resource is busy or in a state that does not allow this right now.
- 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 the status badge
GET/servers/{server}/settings/badge
Permission settings.rename
Whether the server's public status badge is on, and if so its image address and a Markdown snippet for a README. The badge is an image that says online, starting, offline or unknown, refreshed at most once a minute, and nothing else about the server. Owner only, with a key that has settings.rename; subusers cannot see or change it.
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/settings/badge" \ -H "Authorization: Bearer $SILLYDEV_API_KEY" \ -H "Accept: application/json"
Response 200The badge's settings. `url` and `markdown` are null while it is off.
{
"object": "server_badge",
"attributes": {
"enabled": true,
"show_name": false,
"url": "https://sillydev.co.uk/badge/k3Q9vX2mL7pR4tW8zB1nC6dF0gH5jS2aE9uY3iO7.svg",
"link": "https://sillydev.co.uk/?ref=badge",
"markdown": "[](https://sillydev.co.uk/?ref=badge)"
}
}Every field in the response
| Name | Type | Description |
|---|---|---|
| objectrequired | string | |
| attributesrequired | object | |
| attributes.enabledrequired | boolean | Whether the badge is on. |
| attributes.show_namerequired | boolean | Whether the badge shows the server's name rather than "bot". |
| attributes.urlrequired | string | null | The badge image's address, or null while it is off. Anyone with it can see the server's state, so share it only where you mean to. |
| attributes.linkrequired | string | Where the badge should link to. |
| attributes.markdownrequired | string | null | A Markdown snippet for a README, or null while the badge is off. |
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.
- 409 The resource is busy or in a state that does not allow this right now.
- 429 Too many requests. Wait for the number of seconds in the
Retry-Afterheader, then try again.
Turn on the status badge
PUT/servers/{server}/settings/badge
Permission settings.renameLimited to 20 per minute
Turns the badge on, giving it a new random address (201), or changes whether it shows the server's name (200). Off by default; until it is turned on there is no badge to find. With show_name false or left out the badge's label is just "bot". Owner only, with a key that has settings.rename.
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 |
|---|---|---|
| show_name | boolean | Show the server's name on the badge instead of "bot". Left out, the current setting is kept (off for a new badge). |
Example
curl -X PUT "https://sillydev.co.uk/panel/api/client/servers/1a7ce997/settings/badge" \
-H "Authorization: Bearer $SILLYDEV_API_KEY" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{"show_name":false}'Response 201The badge is now on, at a new address.
{
"object": "server_badge",
"attributes": {
"enabled": true,
"show_name": false,
"url": "https://sillydev.co.uk/badge/k3Q9vX2mL7pR4tW8zB1nC6dF0gH5jS2aE9uY3iO7.svg",
"link": "https://sillydev.co.uk/?ref=badge",
"markdown": "[](https://sillydev.co.uk/?ref=badge)"
}
}Every field in the response
| Name | Type | Description |
|---|---|---|
| objectrequired | string | |
| attributesrequired | object | |
| attributes.enabledrequired | boolean | Whether the badge is on. |
| attributes.show_namerequired | boolean | Whether the badge shows the server's name rather than "bot". |
| attributes.urlrequired | string | null | The badge image's address, or null while it is off. Anyone with it can see the server's state, so share it only where you mean to. |
| attributes.linkrequired | string | Where the badge should link to. |
| attributes.markdownrequired | string | null | A Markdown snippet for a README, or null while the badge is off. |
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.
- 409 The resource is busy or in a state that does not allow this right now.
- 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.
Turn off the status badge
DELETE/servers/{server}/settings/badge
Permission settings.rename
Turns the badge off and forgets its address, which then shows unknown with a 404 (copies cached elsewhere can last up to a minute). Turning it on again makes a new address. Owner only, with a key that has settings.rename.
Parameters
| Name | Type | Description |
|---|---|---|
| serverrequired | string | The server's 8-character identifier, as shown in the panel, or its full UUID. |
Example
curl -X DELETE "https://sillydev.co.uk/panel/api/client/servers/1a7ce997/settings/badge" \ -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.
- 409 The resource is busy or in a state that does not allow this right now.
- 429 Too many requests. Wait for the number of seconds in the
Retry-Afterheader, then try again.
Replace the status badge's address
POST/servers/{server}/settings/badge/regenerate
Permission settings.renameLimited to 10 per minute
Gives the badge a new random address. The old one stops working at once, though copies cached elsewhere can last up to a minute, so update your README. 404 while the badge is off. Owner only, with a key that has settings.rename.
Parameters
| Name | Type | Description |
|---|---|---|
| serverrequired | string | The server's 8-character identifier, as shown in the panel, or its full UUID. |
Example
curl -X POST "https://sillydev.co.uk/panel/api/client/servers/1a7ce997/settings/badge/regenerate" \ -H "Authorization: Bearer $SILLYDEV_API_KEY" \ -H "Accept: application/json"
Response 200The badge, at its new address.
{
"object": "server_badge",
"attributes": {
"enabled": true,
"show_name": false,
"url": "https://sillydev.co.uk/badge/Zt5Yh2Kq8Wm3Np6Rs9Vb1Xc4Df7Gj0Lk2Pa5Qe8U.svg",
"link": "https://sillydev.co.uk/?ref=badge",
"markdown": "[](https://sillydev.co.uk/?ref=badge)"
}
}Every field in the response
| Name | Type | Description |
|---|---|---|
| objectrequired | string | |
| attributesrequired | object | |
| attributes.enabledrequired | boolean | Whether the badge is on. |
| attributes.show_namerequired | boolean | Whether the badge shows the server's name rather than "bot". |
| attributes.urlrequired | string | null | The badge image's address, or null while it is off. Anyone with it can see the server's state, so share it only where you mean to. |
| attributes.linkrequired | string | Where the badge should link to. |
| attributes.markdownrequired | string | null | A Markdown snippet for a README, or null while the badge is off. |
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.
- 409 The resource is busy or in a state that does not allow this right now.
- 429 Too many requests. Wait for the number of seconds in the
Retry-Afterheader, then try again.
Startup
The startup command and the startup variables a server runs with.
Get startup settings
GET/servers/{server}/startup
Permission startup.read
Returns the startup variables you can see, the startup command with their values filled in, and the Docker images you can choose from. If a linked repository's sillydev.conf also sets some of these, meta.sillydev names them and says whether a change made here is written back to the file or will be undone by the next deploy.
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/startup" \ -H "Authorization: Bearer $SILLYDEV_API_KEY" \ -H "Accept: application/json"
Response 200The server's startup variables and command.
{
"object": "list",
"data": [
{
"object": "egg_variable",
"attributes": {
"name": "Main file",
"description": "The file the bot is started from.",
"env_variable": "MAIN_FILE",
"default_value": "index.js",
"server_value": "bot.js",
"is_editable": true,
"rules": "required|string|max:64"
}
}
],
"meta": {
"startup_command": "node /home/container/bot.js",
"raw_startup_command": "node /home/container/{{MAIN_FILE}}",
"docker_images": {
"Node.js 20": "ghcr.io/pterodactyl/yolks:nodejs_20",
"Node.js 22": "ghcr.io/pterodactyl/yolks:nodejs_22"
},
"sillydev": null
}
}Every field in the response
| Name | Type | Description |
|---|---|---|
| objectrequired | string | |
| datarequired | array of object | |
| data[].objectrequired | string | |
| data[].attributesrequired | object | A startup variable of the server's egg. |
| data[].attributes.namerequired | string | |
| data[].attributes.descriptionrequired | string | null | |
| data[].attributes.env_variablerequired | string | The environment variable name, used as key when changing it. |
| data[].attributes.default_valuerequired | string | null | |
| data[].attributes.server_valuerequired | string | null | This server's value. |
| data[].attributes.is_editablerequired | boolean | Whether you may change it. |
| data[].attributes.rulesrequired | string | Laravel validation rules the value must satisfy, e.g. required|string|max:64. |
| metarequired | object | |
| meta.startup_commandrequired | string | The startup command with variable values filled in. |
| meta.raw_startup_commandrequired | string | The startup command with {{VARIABLE}} placeholders. |
| meta.docker_imagesrequired | object | The images you can switch to, as display name to image. |
| meta.sillydevrequired | any | Set when the linked repository's sillydev.conf also sets some of these settings, otherwise null. |
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.
- 409 The resource is busy or in a state that does not allow this right now.
- 429 Too many requests. Wait for the number of seconds in the
Retry-Afterheader, then try again.
Change a startup variable
PUT/servers/{server}/startup/variable
Permission startup.update
Sets one startup variable and returns it with the updated startup command. The value is checked against the variable's own rules. Variables you cannot see or that are read-only (is_editable false) are refused with 400. The change takes effect the next time the server starts, and is written to the linked repository's sillydev.conf too if that file sets this variable and write-back is on.
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 |
|---|---|---|
| keyrequired | string | The variable's env_variable, e.g. MAIN_FILE. |
| valuerequired | string | null | The new value. It must be present; whether it may be null or empty depends on the variable's rules. Null is stored as an empty string. |
Example
curl -X PUT "https://sillydev.co.uk/panel/api/client/servers/1a7ce997/startup/variable" \
-H "Authorization: Bearer $SILLYDEV_API_KEY" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{"key":"MAIN_FILE","value":"bot.js"}'Response 200The updated variable.
{
"object": "egg_variable",
"attributes": {
"name": "Main file",
"description": "The file the bot is started from.",
"env_variable": "MAIN_FILE",
"default_value": "index.js",
"server_value": "bot.js",
"is_editable": true,
"rules": "required|string|max:64"
},
"meta": {
"startup_command": "node /home/container/bot.js",
"raw_startup_command": "node /home/container/{{MAIN_FILE}}"
}
}Every field in the response
| Name | Type | Description |
|---|---|---|
| objectrequired | string | |
| attributesrequired | object | A startup variable of the server's egg. |
| attributes.namerequired | string | |
| attributes.descriptionrequired | string | null | |
| attributes.env_variablerequired | string | The environment variable name, used as key when changing it. |
| attributes.default_valuerequired | string | null | |
| attributes.server_valuerequired | string | null | This server's value. |
| attributes.is_editablerequired | boolean | Whether you may change it. |
| attributes.rulesrequired | string | Laravel validation rules the value must satisfy, e.g. required|string|max:64. |
| metarequired | object | |
| meta.startup_commandrequired | string | |
| meta.raw_startup_commandrequired | string |
Errors
- 400 The request could not be carried out as sent.
detailsays why. - 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.
- 409 The resource is busy or in a state that does not allow this right now.
- 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.