API reference
Subusers
Share a server with other people, each with their own permissions.
← API docs5 endpointsUpdated
Browse the docs
Subusers
Other accounts given access to a server, each with its own set of permissions. Call GET /permissions (listPermissions) for every permission there is and what each one allows.
List subusers
GET/servers/{server}/users
Permission user.read
Returns every subuser of the server with their permissions. The server's owner is not listed. 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/users" \ -H "Authorization: Bearer $SILLYDEV_API_KEY" \ -H "Accept: application/json"
Response 200The server's subusers.
{
"object": "list",
"data": [
{
"object": "server_subuser",
"attributes": {
"uuid": "5f0c2d8e-3b1a-4c7d-9e2f-6a8b0c1d2e3f",
"identifier": "user_l4gc3dr3djgh3hrpnkfqyhjoh4",
"username": "friend",
"email": "[email protected]",
"image": "https://www.gravatar.com/avatar/0f2c9a7e4b1d8c6a3e5f7b9d1c3e5a7b9d1f3a5c7e9b1d3f5a7c9e1b3d5f7a9c?d=404",
"2fa_enabled": false,
"created_at": "2026-09-15T18:30:00+00:00",
"permissions": [
"websocket.connect",
"control.console",
"control.restart",
"file.read",
"file.read-content"
]
}
}
]
}Every field in the response
| Name | Type | Description |
|---|---|---|
| objectrequired | string | |
| datarequired | array of object | |
| data[].objectrequired | string | |
| data[].attributesrequired | object | |
| data[].attributes.uuidrequired | string (uuid) | The account's UUID, used as {user} in the subuser paths. |
| data[].attributes.identifierrequired | string | The account's public identifier. |
| data[].attributes.usernamerequired | string | |
| data[].attributes.emailrequired | string (email) | |
| data[].attributes.imagerequired | string (uri) | Gravatar URL for the email address; it answers 404 if there is no Gravatar. |
| data[].attributes.2fa_enabledrequired | boolean | |
| data[].attributes.created_atrequired | string (date-time) | When the account was created. |
| data[].attributes.permissionsrequired | array of string | The subuser's permissions on this server. See listPermissions for every one. |
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.
Add a subuser
POST/servers/{server}/users
Permission user.createLimited to 10 per 15 minutes per server
Gives the account with this email access to the server. If no account has the email, one is created and sent an email to set its password. websocket.connect is always added, and unknown permissions are silently dropped. You cannot give permissions you do not have yourself, nor any your API key is not allowed. Limited to 10 every 15 minutes 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 |
|---|---|---|
| emailrequired | string (email) | |
| permissionsrequired | array of string | Permission strings such as control.console or file.read. Unknown ones are dropped and websocket.connect is always added. See listPermissions. |
Example
curl -X POST "https://sillydev.co.uk/panel/api/client/servers/1a7ce997/users" \
-H "Authorization: Bearer $SILLYDEV_API_KEY" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{"email":"[email protected]","permissions":["control.console","control.restart","file.read","file.read-content"]}'Response 200The new subuser.
{
"object": "server_subuser",
"attributes": {
"uuid": "5f0c2d8e-3b1a-4c7d-9e2f-6a8b0c1d2e3f",
"identifier": "user_l4gc3dr3djgh3hrpnkfqyhjoh4",
"username": "friend",
"email": "[email protected]",
"image": "https://www.gravatar.com/avatar/0f2c9a7e4b1d8c6a3e5f7b9d1c3e5a7b9d1f3a5c7e9b1d3f5a7c9e1b3d5f7a9c?d=404",
"2fa_enabled": false,
"created_at": "2026-09-15T18:30:00+00:00",
"permissions": [
"control.console",
"control.restart",
"file.read",
"file.read-content",
"websocket.connect"
]
}
}Every field in the response
| Name | Type | Description |
|---|---|---|
| objectrequired | string | |
| attributesrequired | object | |
| attributes.uuidrequired | string (uuid) | The account's UUID, used as {user} in the subuser paths. |
| attributes.identifierrequired | string | The account's public identifier. |
| attributes.usernamerequired | string | |
| attributes.emailrequired | string (email) | |
| attributes.imagerequired | string (uri) | Gravatar URL for the email address; it answers 404 if there is no Gravatar. |
| attributes.2fa_enabledrequired | boolean | |
| attributes.created_atrequired | string (date-time) | When the account was created. |
| attributes.permissionsrequired | array of string | The subuser's permissions on this server. See listPermissions for every one. |
Errors
- 400 The email belongs to the server's owner or to an existing subuser.
- 401 No API key was sent, or it is wrong, expired or deleted.
- 403 The key lacks
user.create, or you tried to give permissions that you or your API key do not have. - 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 subuser
GET/servers/{server}/users/{user}
Permission user.read
Returns one subuser of the server. You cannot look yourself up here (403).
Parameters
| Name | Type | Description |
|---|---|---|
| serverrequired | string | The server's 8-character identifier, as shown in the panel, or its full UUID. |
| userrequired | string (uuid) | The subuser's account UUID (attributes.uuid from listSubusers). |
Example
curl "https://sillydev.co.uk/panel/api/client/servers/1a7ce997/users/{user}" \
-H "Authorization: Bearer $SILLYDEV_API_KEY" \
-H "Accept: application/json"Response 200The subuser.
{
"object": "server_subuser",
"attributes": {
"uuid": "5f0c2d8e-3b1a-4c7d-9e2f-6a8b0c1d2e3f",
"identifier": "user_l4gc3dr3djgh3hrpnkfqyhjoh4",
"username": "friend",
"email": "[email protected]",
"image": "https://www.gravatar.com/avatar/0f2c9a7e4b1d8c6a3e5f7b9d1c3e5a7b9d1f3a5c7e9b1d3f5a7c9e1b3d5f7a9c?d=404",
"2fa_enabled": false,
"created_at": "2026-09-15T18:30:00+00:00",
"permissions": [
"websocket.connect",
"control.console"
]
}
}Every field in the response
| Name | Type | Description |
|---|---|---|
| objectrequired | string | |
| attributesrequired | object | |
| attributes.uuidrequired | string (uuid) | The account's UUID, used as {user} in the subuser paths. |
| attributes.identifierrequired | string | The account's public identifier. |
| attributes.usernamerequired | string | |
| attributes.emailrequired | string (email) | |
| attributes.imagerequired | string (uri) | Gravatar URL for the email address; it answers 404 if there is no Gravatar. |
| attributes.2fa_enabledrequired | boolean | |
| attributes.created_atrequired | string (date-time) | When the account was created. |
| attributes.permissionsrequired | array of string | The subuser's permissions on this server. See listPermissions for every one. |
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.
Change a subuser's permissions
POST/servers/{server}/users/{user}
Permission user.update
Replaces the subuser's permissions with the list sent (websocket.connect is always kept). If they change, the subuser's open SFTP sessions and console connections are dropped so the new set applies at once (this drops everyone's open console connections to the server, who then reconnect). The same limits on what you can give apply as for createSubuser, and you cannot change your own permissions.
Parameters
| Name | Type | Description |
|---|---|---|
| serverrequired | string | The server's 8-character identifier, as shown in the panel, or its full UUID. |
| userrequired | string (uuid) | The subuser's account UUID (attributes.uuid from listSubusers). |
Body
| Name | Type | Description |
|---|---|---|
| permissionsrequired | array of string | The full new set of permissions. See listPermissions. |
Example
curl -X POST "https://sillydev.co.uk/panel/api/client/servers/1a7ce997/users/{user}" \
-H "Authorization: Bearer $SILLYDEV_API_KEY" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{"permissions":["control.console","control.start","control.stop","control.restart"]}'Response 200The updated subuser.
{
"object": "server_subuser",
"attributes": {
"uuid": "5f0c2d8e-3b1a-4c7d-9e2f-6a8b0c1d2e3f",
"identifier": "user_l4gc3dr3djgh3hrpnkfqyhjoh4",
"username": "friend",
"email": "[email protected]",
"image": "https://www.gravatar.com/avatar/0f2c9a7e4b1d8c6a3e5f7b9d1c3e5a7b9d1f3a5c7e9b1d3f5a7c9e1b3d5f7a9c?d=404",
"2fa_enabled": false,
"created_at": "2026-09-15T18:30:00+00:00",
"permissions": [
"control.console",
"control.start",
"control.stop",
"control.restart",
"websocket.connect"
]
}
}Every field in the response
| Name | Type | Description |
|---|---|---|
| objectrequired | string | |
| attributesrequired | object | |
| attributes.uuidrequired | string (uuid) | The account's UUID, used as {user} in the subuser paths. |
| attributes.identifierrequired | string | The account's public identifier. |
| attributes.usernamerequired | string | |
| attributes.emailrequired | string (email) | |
| attributes.imagerequired | string (uri) | Gravatar URL for the email address; it answers 404 if there is no Gravatar. |
| attributes.2fa_enabledrequired | boolean | |
| attributes.created_atrequired | string (date-time) | When the account was created. |
| attributes.permissionsrequired | array of string | The subuser's permissions on this server. See listPermissions for every one. |
Errors
- 401 No API key was sent, or it is wrong, expired or deleted.
- 403 The key lacks
user.update, this is your own account, or you tried to give permissions that you or your API key do not have. - 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.
Remove a subuser
DELETE/servers/{server}/users/{user}
Permission user.delete
Takes away the account's access to the server and ends its open SFTP sessions; open console connections to the server are dropped and reconnect. The account itself is not deleted. You cannot remove yourself here.
Parameters
| Name | Type | Description |
|---|---|---|
| serverrequired | string | The server's 8-character identifier, as shown in the panel, or its full UUID. |
| userrequired | string (uuid) | The subuser's account UUID (attributes.uuid from listSubusers). |
Example
curl -X DELETE "https://sillydev.co.uk/panel/api/client/servers/1a7ce997/users/{user}" \
-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.