API reference

Files

Read, write, upload and download the files on your server.

← API docs14 endpointsUpdated

Browse the docs

Files

Browse and change the files of a server. The panel passes each request on to the node (Wings) that runs the server, so errors the node reports, such as a missing file (404), a file on the egg's denylist (403) or not enough disk space (400), come back with the node's message in detail. If the node cannot be reached the panel answers 504, and a node error answers 500 or 502.

Paths are relative to the server's root directory, which is /. A path cannot leave it: anything that resolves outside the root is answered as not found.

Downloads and uploads do not go through the panel. You ask the panel for a signed URL on the node, then download from it or upload to it directly. Each signed URL works once and expires 15 minutes after it is made.

While a server is installing, suspended, being transferred, restoring a backup or being deleted, every endpoint here answers 409.

List a directory

GET/servers/{server}/files/list

Permission file.read

Returns the files and folders in one directory of the server, not recursively. The list is not paginated.

Parameters

List a directory: parameters
NameTypeDescription
serverrequiredstringThe server's 8-character identifier, as shown in the panel, or its full UUID.
directorystringThe directory to list. Defaults to the root, /.

Example

curl "https://sillydev.co.uk/panel/api/client/servers/1a7ce997/files/list" \
  -H "Authorization: Bearer $SILLYDEV_API_KEY" \
  -H "Accept: application/json"

Response 200The directory's contents.

{
    "object": "list",
    "data": [
        {
            "object": "file_object",
            "attributes": {
                "name": "src",
                "mode": "drwxr-xr-x",
                "mode_bits": "755",
                "size": 4096,
                "is_file": false,
                "is_symlink": false,
                "mimetype": "inode/directory",
                "created_at": "2026-10-01T09:30:00+00:00",
                "modified_at": "2026-10-09T18:12:45+00:00"
            }
        },
        {
            "object": "file_object",
            "attributes": {
                "name": "main.py",
                "mode": "-rw-r--r--",
                "mode_bits": "644",
                "size": 2318,
                "is_file": true,
                "is_symlink": false,
                "mimetype": "text/x-python",
                "created_at": "2026-10-01T09:30:00+00:00",
                "modified_at": "2026-10-10T11:58:02+00:00"
            }
        }
    ]
}
Every field in the response
List a directory: response
NameTypeDescription
objectrequiredstring
datarequiredarray of object
data[].objectrequiredstring
data[].attributesrequiredobject
data[].attributes.namerequiredstringThe file or folder name, without its directory.
data[].attributes.moderequiredstringThe permissions as ls -l shows them, e.g. -rw-r--r--.
data[].attributes.mode_bitsrequiredstringThe permission bits in octal, e.g. 644.
data[].attributes.sizerequiredintegerSize in bytes. For a folder this is the size of the folder entry, not its contents.
data[].attributes.is_filerequiredbooleanFalse for folders.
data[].attributes.is_symlinkrequiredboolean
data[].attributes.mimetyperequiredstringThe detected MIME type; inode/directory for folders.
data[].attributes.created_atrequiredstring (date-time)
data[].attributes.modified_atrequiredstring (date-time)

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_field names the field.

Read a file

GET/servers/{server}/files/contents

Permission file.read-content

Returns the raw contents of a file as the response body, not JSON. The response is always sent as text/plain, whatever the file holds. Files larger than 4 MiB are refused with 400; use getFileDownloadUrl for those. The read is recorded in the server's activity log.

Parameters

Read a file: parameters
NameTypeDescription
serverrequiredstringThe server's 8-character identifier, as shown in the panel, or its full UUID.
filerequiredstringThe path of the file to read.

Example

curl "https://sillydev.co.uk/panel/api/client/servers/1a7ce997/files/contents" \
  -H "Authorization: Bearer $SILLYDEV_API_KEY" \
  -H "Accept: application/json"

Response 200The file's contents, exactly as stored.

import discord

client = discord.Client(intents=discord.Intents.default())

Errors

  • 400 The file is larger than 4 MiB, is a directory, or is a named pipe.
  • 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_field names the field.

Get a download link for a file

GET/servers/{server}/files/download

Permission file.read-content

Returns a signed URL on the server's node from which the file can be downloaded. This is step one of two: then send a plain GET to the returned URL, with no API key, and the node answers with the file as application/octet-stream and a Content-Disposition: attachment header. The URL works once and expires 15 minutes after it is made; ask for a new one for each download.

Directories cannot be downloaded (the node answers 404); compress them first with compressFiles. Errors from the node come as {"error": "..."}, not the panel's error format. Asking for the link is recorded in the server's activity log.

Parameters

Get a download link for a file: parameters
NameTypeDescription
serverrequiredstringThe server's 8-character identifier, as shown in the panel, or its full UUID.
filerequiredstringThe path of the file to download.

Example

curl "https://sillydev.co.uk/panel/api/client/servers/1a7ce997/files/download" \
  -H "Authorization: Bearer $SILLYDEV_API_KEY" \
  -H "Accept: application/json"

Response 200A single-use download link, valid for 15 minutes.

{
    "object": "signed_url",
    "attributes": {
        "url": "https://node1.sillydev.co.uk:8080/download/file?token=eyJhbGciOi..."
    }
}
Every field in the response
Get a download link for a file: response
NameTypeDescription
objectrequiredstring
attributesrequiredobject
attributes.urlrequiredstring (uri)The single-use URL on the server's node, valid for 15 minutes.

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_field names the field.

Rename or move files

PUT/servers/{server}/files/rename

Permission file.update

Renames or moves one or more files or folders. from and to are relative to root, so a to in another directory (such as ../old/main.py) moves the file. The renames run one at a time, in the order given; a from that does not exist is skipped without an error, and a to that already exists stops the request with 400.

Parameters

Rename or move files: parameters
NameTypeDescription
serverrequiredstringThe server's 8-character identifier, as shown in the panel, or its full UUID.

Body

Rename or move files: request body
NameTypeDescription
rootrequiredstring | nullThe directory the paths in files are relative to. Must be sent; null means /.
filesrequiredarray of object
files[].fromrequiredstringThe current name or path.
files[].torequiredstringThe new name or path.

Example

curl -X PUT "https://sillydev.co.uk/panel/api/client/servers/1a7ce997/files/rename" \
  -H "Authorization: Bearer $SILLYDEV_API_KEY" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{"root":"/","files":[{"from":"bot.py","to":"main.py"},{"from":"config.json","to":"config/config.json"}]}'

Response 204Done. There is no response body.

Errors

  • 400 The request could not be carried out as sent. detail says 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_field names the field.

Copy a file

POST/servers/{server}/files/copy

Permission file.create

Makes a copy of a file in the same directory and names it for you: main.py becomes main copy.py, then main copy 2.py and so on. Only files can be copied, not directories. The copy counts towards the server's disk limit.

Parameters

Copy a file: parameters
NameTypeDescription
serverrequiredstringThe server's 8-character identifier, as shown in the panel, or its full UUID.

Body

Copy a file: request body
NameTypeDescription
locationrequiredstringThe path of the file to copy.

Example

curl -X POST "https://sillydev.co.uk/panel/api/client/servers/1a7ce997/files/copy" \
  -H "Authorization: Bearer $SILLYDEV_API_KEY" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{"location":"/main.py"}'

Response 204Done. There is no response body.

Errors

  • 400 The request could not be carried out as sent. detail says 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_field names the field.

Write a file

POST/servers/{server}/files/write

Permission file.create

Creates a file, or replaces an existing one, with the request body. The path goes in the file query parameter and the body is the file's raw contents, not JSON; send it as text/plain (or application/octet-stream for binary data). An empty body empties the file. Missing parent directories are created. The write is recorded in the server's activity log.

Parameters

Write a file: parameters
NameTypeDescription
serverrequiredstringThe server's 8-character identifier, as shown in the panel, or its full UUID.
filerequiredstringThe path of the file to write.

Example

curl -X POST "https://sillydev.co.uk/panel/api/client/servers/1a7ce997/files/write" \
  -H "Authorization: Bearer $SILLYDEV_API_KEY" \
  -H "Accept: application/json" \
  -H "Content-Type: text/plain" \
  --data-binary '{"prefix": "!", "status": "online"}
'

Response 204Done. There is no response body.

Errors

  • 400 The request could not be carried out as sent. detail says 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_field names the field.

Compress files into an archive

POST/servers/{server}/files/compress

Permission file.archive

Puts the given files and folders into a new .tar.gz archive in root, named archive-<date and time>.tar.gz, and returns the archive's details. The request waits until the archive is finished, which can take several minutes for large folders, so allow a long timeout (the panel waits up to 15 minutes). Answers 409 if the server is out of disk space.

Parameters

Compress files into an archive: parameters
NameTypeDescription
serverrequiredstringThe server's 8-character identifier, as shown in the panel, or its full UUID.

Body

Compress files into an archive: request body
NameTypeDescription
rootstring | nullThe directory the names in files are relative to, and where the archive is written. Defaults to /.
filesrequiredarray of stringNames of the files and folders to include.

Example

curl -X POST "https://sillydev.co.uk/panel/api/client/servers/1a7ce997/files/compress" \
  -H "Authorization: Bearer $SILLYDEV_API_KEY" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{"root":"/","files":["src","main.py","requirements.txt"]}'

Response 200The archive that was made.

{
    "object": "file_object",
    "attributes": {
        "name": "archive-2026-10-10T120000Z.tar.gz",
        "mode": "-rw-r--r--",
        "mode_bits": "644",
        "size": 48213,
        "is_file": true,
        "is_symlink": false,
        "mimetype": "application/tar+gzip",
        "created_at": "2026-10-10T12:00:00+00:00",
        "modified_at": "2026-10-10T12:00:00+00:00"
    }
}
Every field in the response
Compress files into an archive: response
NameTypeDescription
objectrequiredstring
attributesrequiredobject
attributes.namerequiredstringThe file or folder name, without its directory.
attributes.moderequiredstringThe permissions as ls -l shows them, e.g. -rw-r--r--.
attributes.mode_bitsrequiredstringThe permission bits in octal, e.g. 644.
attributes.sizerequiredintegerSize in bytes. For a folder this is the size of the folder entry, not its contents.
attributes.is_filerequiredbooleanFalse for folders.
attributes.is_symlinkrequiredboolean
attributes.mimetyperequiredstringThe detected MIME type; inode/directory for folders.
attributes.created_atrequiredstring (date-time)
attributes.modified_atrequiredstring (date-time)

Errors

  • 400 The request could not be carried out as sent. detail says 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_field names the field.

Extract an archive

POST/servers/{server}/files/decompress

Permission file.create

Unpacks an archive (zip, tar, tar.gz and other common formats) into root, overwriting files with the same names. The request waits until extraction is finished, so allow a timeout of several minutes. The node first checks that the unpacked files fit in the server's disk limit. Answers 400 for a format it does not understand, or if a file being overwritten is in use; stop the server and try again.

Parameters

Extract an archive: parameters
NameTypeDescription
serverrequiredstringThe server's 8-character identifier, as shown in the panel, or its full UUID.

Body

Extract an archive: request body
NameTypeDescription
rootstring | nullThe directory holding the archive, which is also where it is unpacked. Defaults to /.
filerequiredstringThe archive's name, relative to root.

Example

curl -X POST "https://sillydev.co.uk/panel/api/client/servers/1a7ce997/files/decompress" \
  -H "Authorization: Bearer $SILLYDEV_API_KEY" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{"root":"/","file":"bot.zip"}'

Response 204Done. There is no response body.

Errors

  • 400 The request could not be carried out as sent. detail says 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_field names the field.

Delete files

POST/servers/{server}/files/delete

Permission file.delete

Deletes files and folders, including everything inside the folders. This cannot be undone. If one deletion fails the request stops with an error, and some of the other files may already be gone.

Parameters

Delete files: parameters
NameTypeDescription
serverrequiredstringThe server's 8-character identifier, as shown in the panel, or its full UUID.

Body

Delete files: request body
NameTypeDescription
rootrequiredstring | nullThe directory the names in files are relative to. Must be sent; null means /.
filesrequiredarray of stringNames of the files and folders to delete.

Example

curl -X POST "https://sillydev.co.uk/panel/api/client/servers/1a7ce997/files/delete" \
  -H "Authorization: Bearer $SILLYDEV_API_KEY" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{"root":"/","files":["__pycache__","old_bot.py"]}'

Response 204Done. There is no response body.

Errors

  • 400 The request could not be carried out as sent. detail says 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_field names the field.

Create a folder

POST/servers/{server}/files/create-folder

Permission file.create

Creates a folder called name inside root. name may hold slashes, and any missing folders along the way are created too. Creating a folder that already exists is not an error.

Parameters

Create a folder: parameters
NameTypeDescription
serverrequiredstringThe server's 8-character identifier, as shown in the panel, or its full UUID.

Body

Create a folder: request body
NameTypeDescription
rootstringThe directory to create the folder in. Defaults to /; leave it out rather than sending null.
namerequiredstringThe new folder's name.

Example

curl -X POST "https://sillydev.co.uk/panel/api/client/servers/1a7ce997/files/create-folder" \
  -H "Authorization: Bearer $SILLYDEV_API_KEY" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{"root":"/","name":"cogs"}'

Response 204Done. There is no response body.

Errors

  • 400 The request could not be carried out as sent. detail says 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_field names the field.

Change file permissions

POST/servers/{server}/files/chmod

Permission file.update

Sets the Unix permissions of one or more files or folders. Send each mode as a string of octal digits, such as "755"; a JSON number is rejected by the node with 400, and so is a string that is not valid octal. Files that do not exist are skipped without an error.

Parameters

Change file permissions: parameters
NameTypeDescription
serverrequiredstringThe server's 8-character identifier, as shown in the panel, or its full UUID.

Body

Change file permissions: request body
NameTypeDescription
rootrequiredstring | nullThe directory the names in files are relative to. Must be sent; null means /.
filesrequiredarray of object
files[].filerequiredstringThe file or folder name.
files[].moderequiredstringThe new permissions in octal, as a string.

Example

curl -X POST "https://sillydev.co.uk/panel/api/client/servers/1a7ce997/files/chmod" \
  -H "Authorization: Bearer $SILLYDEV_API_KEY" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{"root":"/","files":[{"file":"start.sh","mode":"755"}]}'

Response 204Done. There is no response body.

Errors

  • 400 The request could not be carried out as sent. detail says 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_field names the field.

Download a file from a URL onto the server

POST/servers/{server}/files/pull

Permission file.createLimited to 5 per 10 minutes per server

Has the node download a file from a public http or https URL into the server's files. By default the download runs in the background and this request returns at once; set foreground to wait until the file is saved, so that failures are reported to you.

Limits: 5 requests per 10 minutes per server, shared by everyone using it; at most 3 downloads running at once per server; the file must fit in the server's disk limit. The URL must answer 200 with a Content-Length header. Redirects are not followed, and URLs that resolve to private or local addresses (such as 127.0.0.0/8, 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16 and 169.254.0.0/16) are refused.

Parameters

Download a file from a URL onto the server: parameters
NameTypeDescription
serverrequiredstringThe server's 8-character identifier, as shown in the panel, or its full UUID.

Body

Download a file from a URL onto the server: request body
NameTypeDescription
urlrequiredstring (uri)The URL to download.
directorystring | nullThe directory to save the file in. Defaults to /.
filenamestring | nullThe name to save the file as. Defaults to the last part of the URL's path.
use_headerbooleanName the file from the response's Content-Disposition header when it has one, in preference to filename.
foregroundbooleanWait for the download to finish before answering, and report a failed download as an error.

Example

curl -X POST "https://sillydev.co.uk/panel/api/client/servers/1a7ce997/files/pull" \
  -H "Authorization: Bearer $SILLYDEV_API_KEY" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{"url":"https://example.com/releases/bot-1.4.0.zip","directory":"/","filename":"bot.zip","foreground":true}'

Response 204The download has started, or with `foreground` has finished. There is no response body.

Errors

  • 400 The server already has 3 downloads running, is out of disk space, or the URL could not be downloaded (with foreground). Also returned if remote downloads are switched off on the node.
  • 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_field names the field.
  • 429 Too many requests. Wait for the number of seconds in the Retry-After header, then try again.

Get an upload link

GET/servers/{server}/files/upload

Permission file.create

Returns a signed URL on the server's node that files can be uploaded to. This is step one of two: then POST to the returned URL, with no API key, a multipart/form-data body with one or more files in the field named files. Add a directory query parameter to the URL (for example &directory=/cogs) to upload somewhere other than /. The node answers 200 with an empty body when the upload is saved.

The URL works once and expires 15 minutes after it is made. Each file may be up to the node's upload limit. Errors from the node come as {"error": "..."}, not the panel's error format. Folders cannot be uploaded this way; upload an archive and use decompressFile.

Parameters

Get an upload link: parameters
NameTypeDescription
serverrequiredstringThe 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/files/upload" \
  -H "Authorization: Bearer $SILLYDEV_API_KEY" \
  -H "Accept: application/json"

Response 200A single-use upload link, valid for 15 minutes.

{
    "object": "signed_url",
    "attributes": {
        "url": "https://node1.sillydev.co.uk:8080/upload/file?token=eyJhbGciOi..."
    }
}
Every field in the response
Get an upload link: response
NameTypeDescription
objectrequiredstring
attributesrequiredobject
attributes.urlrequiredstring (uri)The single-use URL on the server's node, valid for 15 minutes.

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.

Check whether files are deployed from Git

GET/servers/{server}/files/git

Permission file.read

Says whether a Git repository is linked to the server, so a file editor can warn that changes in the deploy directory may be overwritten by the next deploy. It only needs file.read and so deliberately leaves out the repository, branch and account; read the server's Git settings for those, which needs the Git permissions. This is not a plain JSON envelope: it is a bare object.

Parameters

Check whether files are deployed from Git: parameters
NameTypeDescription
serverrequiredstringThe 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/files/git" \
  -H "Authorization: Bearer $SILLYDEV_API_KEY" \
  -H "Accept: application/json"

Response 200Whether a repository is linked, and if so where it deploys.

{
    "linked": true,
    "provider": "github",
    "directory": "/",
    "auto_deploy": true
}
Every field in the response
Check whether files are deployed from Git: response
NameTypeDescription
linkedrequiredbooleanWhether a Git repository is linked to the server.
providerone of 'github', 'gitlab', 'url'Where the repository is hosted; url is any other Git URL. Only when linked.
directorystringThe folder the repository deploys into, e.g. / or /bot. Only when linked.
auto_deploybooleanWhether pushes deploy automatically. Only when linked.

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.