Skip to content
Coritan Docs

Let customers run their servers

Build a Container Apps server panel in your storefront, with power and console, files, snapshots, databases, schedules, ports, software and sharing.

View as Markdown

Your storefront's server panel runs on the portal API. It gives a customer the controls that the Container Apps guides describe for the Coritan dashboard, on the servers they bought from you. Every route on this page is under /portal/servers/{uuid}/ or /portal/snapshots/, and takes the customer's token as Authorization: Bearer $CUSTOMER_TOKEN.

Most routes have the same path after {uuid} as the platform's /api/v1/client/servers/{uuid}/ routes and take the same body, so the API sections of the Container Apps guides apply once you change the base path and the token. This page covers what the portal does differently, and the routes those guides do not have.

Shell
curl "https://api.coritan.com/api/v1/orgs/acme/portal/servers/$SERVER_UUID" \
  -H "Authorization: Bearer $CUSTOMER_TOKEN"

The answer is the server as the customer should see it: its name, status, plan limits such as memory_mb and disk_mb, and its join_address. On a free server, ip_address and port are empty and players use the join_address. entitlements lists what the plan includes, and one the plan leaves out has allowed: false with a reason and a detail to show in its place. legacy_backup_count says whether the server has backups worth a tab, sleep holds a free server's sleep state, and lock says whether we have locked the server.

Three fields say what this customer may do:

Field Meaning
is_owner true for the customer whose service it is, and false for a customer the owner shared it with.
permissions ["*"] for the owner. Otherwise, the permissions the owner granted.
capabilities One true or false flag per permission, named with underscores, such as file_read_content. Show or hide each control by these flags.

GET /resources returns the power state and live use of CPU, memory, disk and network, in the shape Use the console and power controls describes. Poll it while the panel is open. GET /status-ping asks a Minecraft server who is online, and never fails: reachable is false when the game does not answer.

The owner can do everything. A customer the owner shared the server with can do what their permissions allow, and a request outside them answers 403 with Insufficient permissions. GET /permissions lists every permission an owner can grant.

Permission Lets the customer
control.console Send console commands.
control.start, control.stop, control.restart Send that power signal. kill needs control.stop. Waking and keeping a free server need control.start.
websocket.connect Open the live console.
file.read, file.read-content List files, and read or download them.
file.create, file.update, file.delete, file.archive Upload, create and copy files, or download one from a URL. Edit, rename and change modes. Delete. Compress and extract.
file.sftp Connect over SFTP.
snapshot.read, snapshot.create, snapshot.restore, snapshot.download, snapshot.delete List, take, restore, download and delete snapshots. Locking one needs snapshot.delete.
backup.read, backup.restore, backup.download, backup.delete List, restore, download and delete old backups. Locking one needs backup.delete.
database.read, database.create, database.update, database.delete List databases, create them, rotate their passwords and delete them.
database.view_password See a database's password, and use the SQL editor and table browser.
schedule.read, schedule.create, schedule.update, schedule.delete See schedules and their runs, create them, change them and their tasks or run them now, and delete them.
allocation.read, allocation.create, allocation.update, allocation.delete See ports, add or request one, choose the primary port or publish one, and release one.
startup.read, startup.update See the Java memory and startup flags, and change them and the startup variables.
settings.rename Rename the server and change its join address subdomain.
settings.reinstall Reinstall the server, change its software, install and remove add-ons, and run world optimization.

Viewing the server, its resources, its sleep state, its software and its custom domain needs no particular permission. Only the owner can share the server, list it in your server directory, and link a custom domain.

Warning

Snapshots belong to the owner's account, not to one server. A customer with snapshot.restore on one server can restore any of the owner's snapshots onto it, including one taken from another server.

The owner shares a server with another customer of your organization by username or email address:

Shell
curl -X POST "https://api.coritan.com/api/v1/orgs/acme/portal/servers/$SERVER_UUID/users" \
  -H "Authorization: Bearer $CUSTOMER_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"username_or_email": "alex@example.com", "permissions": ["control.console", "control.start", "control.stop", "file.read", "file.read-content"]}'

A customer with that username or email gets access at once, and we email them. An email address with no customer behind it gets a pending invite instead, with kind set to invite and an expires_at 14 days away. The invite becomes access when a customer with that address signs in to your storefront.

  • GET /users lists who has access, each with id, kind (grant or invite), status, username, email and permissions. A shared customer sees the others by username only, without emails or invites.
  • PUT /users/{subuser_id} with permissions replaces what a customer may do.
  • DELETE /users/{subuser_id} removes a customer or cancels an invite, and we email a customer who was removed. A shared customer can remove themselves the same way, or with POST /users/leave.

Share a server with other users explains each permission in the words the Coritan dashboard uses.

Send a power signal with POST /power:

Shell
curl -X POST "https://api.coritan.com/api/v1/orgs/acme/portal/servers/$SERVER_UUID/power" \
  -H "Authorization: Bearer $CUSTOMER_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"signal": "restart"}'

signal is start, stop, restart or kill, and the answer confirms only that we sent it, so read GET /resources for the result. POST /command runs a console command, given as command in the body or in the query string, up to 1,000 characters.

For the live console, GET /websocket returns the socket's address as socket, and the customer's token as token. Open the socket with the token in the token query parameter:

JavaScript
const res = await fetch(`https://api.coritan.com/api/v1/orgs/acme/portal/servers/${uuid}/websocket`, {
  headers: { Authorization: `Bearer ${customerToken}` },
});
const { socket, token } = await res.json();
const ws = new WebSocket(`${socket}?token=${encodeURIComponent(token)}`);
ws.onopen = () => ws.send(JSON.stringify({ event: "send logs", args: [null] }));
ws.onmessage = (message) => {
  const { event, args } = JSON.parse(message.data);
  if (event === "console output") showLine(args[0]);
};

The socket speaks the events that Use the console and power controls lists. Send send command and set state only when the customer holds control.console or the power permission, because the socket refuses them otherwise. When the owner removes a customer's access, the socket closes with code 4003. Do not reopen a socket that closed with 4001, 4003, 4008, 4010 or 4011 until something changes: the token expired, access ended, the session ended, or the server is suspended or gone.

A free server sleeps when nobody plays on it, as How free servers work explains. GET /sleep returns its sleep state: the phase (awake, starting, queued or asleep), sleeps_at to count down from, and the customer's place in the start queue. A paid server answers with policy set to none.

  • POST /wake asks for the server to start. When sleep.challenge_required is true, show the Cloudflare Turnstile challenge first, with the site key from GET /storefront/branding, and send its answer as turnstile_token.
  • POST /keep marks a free server as still in use, which resets its count of days without activity. On a server we suspended for inactivity, it also reactivates the server and cancels its deletion. A paid server answers 409.

The file routes are the ones Manage server files describes, under /files/. Upload with a multipart form, one files part per file:

Shell
curl -X POST "https://api.coritan.com/api/v1/orgs/acme/portal/servers/$SERVER_UUID/files/upload?directory=/plugins" \
  -H "Authorization: Bearer $CUSTOMER_TOKEN" \
  -F "files=@EssentialsX.jar"

Each file can be up to 100 MB. When some files of a batch fail after others have landed, the answer lists the uploaded names in files and the others in failed. POST /files/pull downloads a file from a URL onto the server, GET /files/pull/status reports on it and POST /files/pull/cancel?download_id=... stops it.

GET /sftp returns the host, port and username to connect with. The username is the customer's own email address and a short server reference, so a shared customer signs in as themselves. The password is the customer's storefront password. A customer who signed up with a social account has none until they set one; see Social sign-in. Connect to a server with SFTP covers the rest.

A snapshot saves the server's files to the account, and can be restored onto any of the owner's servers. The Snapshots guides explain how they work and what the storage allowance counts.

  1. Check that one fits with GET /snapshots/estimate. It answers estimated_bytes, remaining_bytes, fits and shortfall_bytes. The estimate is the server's disk use before compression, so the snapshot is never larger.
  2. Take it:
Shell
curl -X POST "https://api.coritan.com/api/v1/orgs/acme/portal/servers/$SERVER_UUID/snapshots" \
  -H "Authorization: Bearer $CUSTOMER_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name": "Before the 1.21 update", "ignored_files": ["logs"], "is_locked": true}'

name is up to 191 characters, ignored_files leaves out up to 50 paths, and is_locked keeps the snapshot from being rotated away. With no body, the snapshot is called manual-snapshot.

Route What it does
GET /snapshots Lists this server's snapshots. scope=account lists every snapshot the owner holds, each marked for whether it can restore onto this server. A shared customer gets this server's list either way.
POST /snapshots/{snapshot_uuid}/restore Restores any of the owner's snapshots onto this server. truncate (default true) deletes the current files first, and allow_mismatch confirms a restore from the same game on another loader.
GET /snapshots/{snapshot_uuid}/download Returns a short-lived download url.
POST /snapshots/{snapshot_uuid}/lock Locks or unlocks a snapshot.
DELETE /snapshots/{snapshot_uuid} Deletes a snapshot.
GET /snapshots/seed For a server ordered from a snapshot, the restore it is waiting on or has finished. POST /snapshots/seed/retry runs a failed one again.

The account routes under /portal/snapshots/ do the same for the customer's own snapshots without naming a server, so they work after the server has gone. GET /portal/snapshots lists them, GET /portal/snapshots/allowance returns the storage allowance, and GET, DELETE, POST .../lock and GET .../download act on one. POST /portal/snapshots/{snapshot_uuid}/restore needs target_server_uuid, because there is no server in the path to restore onto.

Snapshots have replaced backups, so POST /backups answers 410 with reason set to replaced_by_snapshots. A server that took backups before keeps them: GET /backups lists them, and restore, download, lock and delete work as Manage server backups describes.

POST /databases creates a database on the server's database host. name_suffix names it with lowercase letters, digits and underscores, up to 48 characters (default db), and remote limits where it accepts connections from (default %, anywhere). Send an Idempotency-Key header so a retry does not create two.

Shell
curl -X POST "https://api.coritan.com/api/v1/orgs/acme/portal/servers/$SERVER_UUID/databases" \
  -H "Authorization: Bearer $CUSTOMER_TOKEN" \
  -H "Idempotency-Key: 1f9e6c2a-luckperms" \
  -H "Content-Type: application/json" \
  -d '{"name_suffix": "luckperms"}'
Route What it does
GET /databases Lists the server's databases.
GET /databases/{database_id}/credentials Returns the password and connection details.
POST /databases/{database_id}/rotate-password Sets a new password.
POST /databases/{database_id}/retry Tries a failed creation again.
DELETE /databases/{database_id} Deletes the database.
POST /databases/{database_id}/query Runs the SQL in sql, up to 65,536 characters, as the database's own user.
GET /databases/{database_id}/tables Lists tables. .../tables/{table}/columns describes one.
GET /databases/{database_id}/tables/{table}/rows Reads rows: limit (1–100, default 50), offset, search, sort and direction.
POST, PATCH /databases/{database_id}/tables/{table}/rows Inserts a row from values, or changes the row whose primary key is key.
POST /databases/{database_id}/tables/{table}/rows/delete Deletes the row whose primary key is key.
GET /databases/{database_id}/tables/{table}/export.csv Downloads the table as CSV. X-Export-Truncated: 1 means it holds only part of the table.
POST .../tables/{table}/truncate, DELETE .../tables/{table} Empties or drops a table.

Create and manage server databases explains the database host and the connection details.

Schedules run tasks on a timetable, as Schedule server tasks describes, with the same body under /schedules/:

Shell
curl -X POST "https://api.coritan.com/api/v1/orgs/acme/portal/servers/$SERVER_UUID/schedules" \
  -H "Authorization: Bearer $CUSTOMER_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name": "Nightly restart", "cron_minute": "0", "cron_hour": "4", "cron_day_of_month": "*", "cron_month": "*", "cron_day_of_week": "*", "timezone": "Europe/London", "tasks": [{"action": "command", "payload": {"command": "say Restarting in 60 seconds"}}, {"action": "power", "payload": {"signal": "restart"}, "time_offset": 60}]}'

A shared customer needs schedule.update to change tasks, and also the permission each task's action needs by hand: control.console for a command, the power permission for a power task, and snapshot.create for a snapshot. That way a schedule never does what the customer could not do themselves. GET /schedules/{schedule_uuid}/runs lists recent runs, newest first, and POST /schedules/{schedule_uuid}/execute runs a schedule now.

GET /allocations lists the server's ports and how many it may have, and GET /allocations/available-ports lists free ones. POST /allocations adds a port, with an optional port, notes, and on_dedicated_ip to open it on the server's Floating IP. POST /allocations/{allocation_id}/primary makes a port the one players connect to, POST /allocations/{allocation_id}/publish-port publishes one on the game's default port of a Floating IP, and DELETE /allocations/{allocation_id} releases it. Manage server ports explains each.

Your organization can decide that extra ports on free servers go through a request to your staff instead. GET /allocations/request then answers required: true, with the customer's open_request if they have one, and POST /allocations answers 403 with reason set to request_required. Send the request with a note that says what the port is for:

Shell
curl -X POST "https://api.coritan.com/api/v1/orgs/acme/portal/servers/$SERVER_UUID/allocations/request" \
  -H "Authorization: Bearer $CUSTOMER_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"note": "A second port for the web map plugin"}'

note is 3–500 characters. The request opens a conversation in your support inbox tagged port-request, and a second request while one is open returns the first. Your staff add the port as Manage customer servers in the staff console describes.

The software routes are the ones Change the server software and the guides after it describe, under /software/. Reading them needs only access to the server. Changing what the server runs, installing, updating and removing add-ons, resource packs, safe mode and Bedrock packs need settings.reinstall, and the Java memory and startup flags at GET and PATCH /software/jvm need startup.read and startup.update.

  • GET /software/context says what the server runs now. GET /software/catalog, .../catalog/{key}/versions and .../versions/{version}/builds list what it can change to, and POST /software/change changes it. A change that wipes the server needs confirm_server_name.
  • POST /software/search finds add-ons, GET /software/versions/{source_uuid}/{identifier} lists an add-on's versions and GET /software/dependencies/{source_uuid}/{identifier} what one needs. POST /software/install installs one; mode set to replace wipes the server first and needs confirm_server_name.
  • GET /software lists what we installed, GET /software/addons every add-on on disk, and GET /software/updates newer builds. GET /software/installs follows install jobs, which .../cancel and .../retry act on.
  • POST /software/bedrock with enabled turns Bedrock crossplay on or off for a Java server.

Import files from another host

Section titled Import files from another host

POST /import/test-connection and POST /import/start take the body Import a server from another host describes. Testing needs file.read and starting needs file.create. truncate set to true wipes the server first, so it also needs file.delete. GET /import/current returns the running import, GET /import/status/{import_id} reports on one, and DELETE /import/{import_id} stops it.

Route What it does
PATCH /settings name renames the server: 2–48 characters with at least one letter or number. world_optimization_enabled turns world optimization on or off. A free server can turn it on but not off.
PATCH /subdomain Changes the first part of the join address: 3–28 lowercase letters, digits and hyphens, not only digits.
PATCH /startup-variables Changes the startup variables the game allows, as variables. They apply at the next restart.
POST /reinstall Deletes every file and installs the server again. Send the server's name as confirm_server_name; case does not matter. A server whose install never finished needs no name.
GET /world-optimization What removing unused chunks has done to the world, with its recent runs.
POST /world-optimization Runs world optimization now, once a day, on a stopped server with the setting on.

The owner can give the join address a name on their own domain, such as play.example.com.

  1. Read GET /custom-domain. expected_cname_target is the address the customer's DNS record must point at.
  2. Ask the customer to add a CNAME record for their name, pointing at that address. For a domain's root, use a DNS provider that flattens CNAME records or offers ALIAS records.
  3. Link it:
Shell
curl -X POST "https://api.coritan.com/api/v1/orgs/acme/portal/servers/$SERVER_UUID/custom-domain" \
  -H "Authorization: Bearer $CUSTOMER_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"domain": "example.com", "subdomain": "play", "include_in_list": true}'

subdomain defaults to @, the domain itself. The answer has verification_status: verified when we can see the record, or pending until we can. We keep checking, and POST /custom-domain/verify checks now. When the record stays missing across several checks, the status becomes failed, the name stops working and we email the owner once. It works again by itself when the record returns.

include_in_list shows the custom name in your server directory in place of the join address; change it later with PATCH /custom-domain. DELETE /custom-domain unlinks the name. Changing the server's subdomain moves the address the record must point at, so we email the owner the new one and the name waits as pending until the record moves.

List the server in your directory

Section titled List the server in your directory

When your organization runs a public server directory, the owner decides whether their server appears in it. GET /listing returns hidden, the chosen tags, the available_tags and max_tags, and feature_enabled. PATCH /listing with hidden and tags changes them. Listing a server needs at least one of your tags and a join address. Run a community with a server list, forum and guides covers the directory itself.

Your storefront shows each server with the controls its customer may use, and every request is checked against the owner's grant, so a control your panel shows by mistake still cannot do more than the grant allows.

401 on every call
The customer token is missing, expired or belongs to another organization. See Troubleshooting for customer sign-in.
403 with Access denied
The customer neither owns the server nor has it shared with them. Check the uuid against their services.
403 with Insufficient permissions
The owner has not granted the permission this route needs. Hide the control when its capabilities flag is false.
Only the server owner can manage subusers
A shared customer tried to share the server or change its directory listing. Only the owner can.
409 with reason set to server_deleting
The server is being deleted. Every route refuses it from then on.
423 with reason set to server_locked
We locked the server while we review activity that broke our acceptable use policy. Its files stay. Show the message.
Type the server name to confirm a wipe and reinstall
confirm_server_name is missing or does not match the server's name.
409 with reason set to world_optimization_running
We are removing unused chunks and the server cannot start until that ends. Try again after retry_after_seconds.
File exceeds maximum upload size of 100 MB
Upload the file over SFTP, or download it onto the server from a URL.
Downloading a snapshot is not included on the free plan. …
Free plans leave out snapshot downloads. The customer can still restore the snapshot, or download files one by one from the file routes.
403 with reason set to request_required
Your organization asks for port requests on free servers. Send one with POST /allocations/request.
Extra ports on this server are added from the Network tab, not requested
Port requests are off for this server. Add the port with POST /allocations.
No matching account in this organization
No customer has that username. Use their email address instead, which sends an invite when they have no account yet.
This server does not sleep; use the power action to start it.
The server is on a paid plan. Start it with POST /power.

API operations on this page

MethodPathWhat it does
GET/api/v1/orgs/{org_slug}/portal/servers/{uuid}Get server
GET/api/v1/orgs/{org_slug}/portal/servers/{uuid}/allocationsList allocations
POST/api/v1/orgs/{org_slug}/portal/servers/{uuid}/allocationsCreate allocation
GET/api/v1/orgs/{org_slug}/portal/servers/{uuid}/allocations/available-portsAvailable ports
GET/api/v1/orgs/{org_slug}/portal/servers/{uuid}/allocations/requestGet port request
POST/api/v1/orgs/{org_slug}/portal/servers/{uuid}/allocations/requestAsk staff for an extra port on a free server whose brand requires it
DELETE/api/v1/orgs/{org_slug}/portal/servers/{uuid}/allocations/{allocation_id}Delete allocation
POST/api/v1/orgs/{org_slug}/portal/servers/{uuid}/allocations/{allocation_id}/primaryMake one of the server's ports the one players type
POST/api/v1/orgs/{org_slug}/portal/servers/{uuid}/allocations/{allocation_id}/publish-portPublish a port on the game's default port of the attached floating IP
GET/api/v1/orgs/{org_slug}/portal/servers/{uuid}/backupsList backups
POST/api/v1/orgs/{org_slug}/portal/servers/{uuid}/backupsCreate backup
DELETE/api/v1/orgs/{org_slug}/portal/servers/{uuid}/backups/{backup_uuid}Delete backup
GET/api/v1/orgs/{org_slug}/portal/servers/{uuid}/backups/{backup_uuid}/downloadA short-lived signed URL the browser fetches the archive from directly
POST/api/v1/orgs/{org_slug}/portal/servers/{uuid}/backups/{backup_uuid}/lockKeep a backup, or release it
POST/api/v1/orgs/{org_slug}/portal/servers/{uuid}/backups/{backup_uuid}/restoreRestore backup
POST/api/v1/orgs/{org_slug}/portal/servers/{uuid}/commandCommand
GET/api/v1/orgs/{org_slug}/portal/servers/{uuid}/custom-domainVanity CNAME state for this server's join address
POST/api/v1/orgs/{org_slug}/portal/servers/{uuid}/custom-domainLink a customer hostname
PATCH/api/v1/orgs/{org_slug}/portal/servers/{uuid}/custom-domainShow the vanity hostname, or the hosted one, in the public server list
DELETE/api/v1/orgs/{org_slug}/portal/servers/{uuid}/custom-domainUnlink custom domain
POST/api/v1/orgs/{org_slug}/portal/servers/{uuid}/custom-domain/verifyCheck the CNAME now rather than waiting for the next maintenance pass
GET/api/v1/orgs/{org_slug}/portal/servers/{uuid}/databasesList databases
POST/api/v1/orgs/{org_slug}/portal/servers/{uuid}/databasesCreate database
DELETE/api/v1/orgs/{org_slug}/portal/servers/{uuid}/databases/{database_id}Delete database
GET/api/v1/orgs/{org_slug}/portal/servers/{uuid}/databases/{database_id}/credentialsGet database credentials
POST/api/v1/orgs/{org_slug}/portal/servers/{uuid}/databases/{database_id}/queryQuery database
POST/api/v1/orgs/{org_slug}/portal/servers/{uuid}/databases/{database_id}/retryRetry database
POST/api/v1/orgs/{org_slug}/portal/servers/{uuid}/databases/{database_id}/rotate-passwordRotate database password
GET/api/v1/orgs/{org_slug}/portal/servers/{uuid}/databases/{database_id}/tablesList database tables
DELETE/api/v1/orgs/{org_slug}/portal/servers/{uuid}/databases/{database_id}/tables/{table}Drop database table
GET/api/v1/orgs/{org_slug}/portal/servers/{uuid}/databases/{database_id}/tables/{table}/columnsDescribe database table
GET/api/v1/orgs/{org_slug}/portal/servers/{uuid}/databases/{database_id}/tables/{table}/export.csvExport database table
GET/api/v1/orgs/{org_slug}/portal/servers/{uuid}/databases/{database_id}/tables/{table}/rowsRead database rows
POST/api/v1/orgs/{org_slug}/portal/servers/{uuid}/databases/{database_id}/tables/{table}/rowsInsert database row
PATCH/api/v1/orgs/{org_slug}/portal/servers/{uuid}/databases/{database_id}/tables/{table}/rowsUpdate database row
POST/api/v1/orgs/{org_slug}/portal/servers/{uuid}/databases/{database_id}/tables/{table}/rows/deleteDelete database row
POST/api/v1/orgs/{org_slug}/portal/servers/{uuid}/databases/{database_id}/tables/{table}/truncateTruncate database table
POST/api/v1/orgs/{org_slug}/portal/servers/{uuid}/files/chmodChmod files
POST/api/v1/orgs/{org_slug}/portal/servers/{uuid}/files/compressCompress files
GET/api/v1/orgs/{org_slug}/portal/servers/{uuid}/files/contentsFile contents
POST/api/v1/orgs/{org_slug}/portal/servers/{uuid}/files/copyCopy file
POST/api/v1/orgs/{org_slug}/portal/servers/{uuid}/files/decompressDecompress file
POST/api/v1/orgs/{org_slug}/portal/servers/{uuid}/files/deleteDelete files
GET/api/v1/orgs/{org_slug}/portal/servers/{uuid}/files/downloadDownload file
GET/api/v1/orgs/{org_slug}/portal/servers/{uuid}/files/listList files
POST/api/v1/orgs/{org_slug}/portal/servers/{uuid}/files/mkdirMkdir
POST/api/v1/orgs/{org_slug}/portal/servers/{uuid}/files/pullPull file
POST/api/v1/orgs/{org_slug}/portal/servers/{uuid}/files/pull/cancelCancel pull
GET/api/v1/orgs/{org_slug}/portal/servers/{uuid}/files/pull/statusPull status
POST/api/v1/orgs/{org_slug}/portal/servers/{uuid}/files/renameRename files
POST/api/v1/orgs/{org_slug}/portal/servers/{uuid}/files/uploadUpload files
POST/api/v1/orgs/{org_slug}/portal/servers/{uuid}/files/writeWrite file
GET/api/v1/orgs/{org_slug}/portal/servers/{uuid}/import/currentCurrent server import
POST/api/v1/orgs/{org_slug}/portal/servers/{uuid}/import/startStart server import
GET/api/v1/orgs/{org_slug}/portal/servers/{uuid}/import/status/{import_id}Polled while an import runs
POST/api/v1/orgs/{org_slug}/portal/servers/{uuid}/import/test-connectionTest import connection
DELETE/api/v1/orgs/{org_slug}/portal/servers/{uuid}/import/{import_id}Cancel server import
POST/api/v1/orgs/{org_slug}/portal/servers/{uuid}/keepTell us this world is still wanted, and lift a hold if one is on
GET/api/v1/orgs/{org_slug}/portal/servers/{uuid}/listingPublic-list visibility and tags for the Server Settings tab
PATCH/api/v1/orgs/{org_slug}/portal/servers/{uuid}/listingToggle public-list visibility and replace the listing tags
GET/api/v1/orgs/{org_slug}/portal/servers/{uuid}/permissionsList grantable permissions
POST/api/v1/orgs/{org_slug}/portal/servers/{uuid}/powerPower
POST/api/v1/orgs/{org_slug}/portal/servers/{uuid}/reinstallWipe server files and re-run the template install script + verify
GET/api/v1/orgs/{org_slug}/portal/servers/{uuid}/resourcesGet resources
GET/api/v1/orgs/{org_slug}/portal/servers/{uuid}/schedulesList schedules
POST/api/v1/orgs/{org_slug}/portal/servers/{uuid}/schedulesCreate schedule
GET/api/v1/orgs/{org_slug}/portal/servers/{uuid}/schedules/{schedule_uuid}Get schedule
PUT/api/v1/orgs/{org_slug}/portal/servers/{uuid}/schedules/{schedule_uuid}Update schedule
DELETE/api/v1/orgs/{org_slug}/portal/servers/{uuid}/schedules/{schedule_uuid}Delete schedule
POST/api/v1/orgs/{org_slug}/portal/servers/{uuid}/schedules/{schedule_uuid}/executeQueue a run now
GET/api/v1/orgs/{org_slug}/portal/servers/{uuid}/schedules/{schedule_uuid}/runsRecent runs of a schedule, newest first, with the outcome of every step
POST/api/v1/orgs/{org_slug}/portal/servers/{uuid}/schedules/{schedule_uuid}/tasksAdd schedule task
POST/api/v1/orgs/{org_slug}/portal/servers/{uuid}/schedules/{schedule_uuid}/tasks/reorderReorder schedule tasks
PUT/api/v1/orgs/{org_slug}/portal/servers/{uuid}/schedules/{schedule_uuid}/tasks/{task_id}Update schedule task
DELETE/api/v1/orgs/{org_slug}/portal/servers/{uuid}/schedules/{schedule_uuid}/tasks/{task_id}Delete schedule task
PATCH/api/v1/orgs/{org_slug}/portal/servers/{uuid}/settingsPatch settings
GET/api/v1/orgs/{org_slug}/portal/servers/{uuid}/sftpConnection details for this server's SFTP login
GET/api/v1/orgs/{org_slug}/portal/servers/{uuid}/sleepSleep and start-queue state for a free server
GET/api/v1/orgs/{org_slug}/portal/servers/{uuid}/snapshotsList snapshots
POST/api/v1/orgs/{org_slug}/portal/servers/{uuid}/snapshotsCreate snapshot
GET/api/v1/orgs/{org_slug}/portal/servers/{uuid}/snapshots/estimateHow much of the allowance a snapshot of this server would use
GET/api/v1/orgs/{org_slug}/portal/servers/{uuid}/snapshots/seedThe restore a server ordered from a snapshot is waiting on, or got
POST/api/v1/orgs/{org_slug}/portal/servers/{uuid}/snapshots/seed/retryRun a failed seed again
DELETE/api/v1/orgs/{org_slug}/portal/servers/{uuid}/snapshots/{snapshot_uuid}Delete snapshot
GET/api/v1/orgs/{org_slug}/portal/servers/{uuid}/snapshots/{snapshot_uuid}/downloadDownload snapshot
POST/api/v1/orgs/{org_slug}/portal/servers/{uuid}/snapshots/{snapshot_uuid}/lockKeep a snapshot, or release it
POST/api/v1/orgs/{org_slug}/portal/servers/{uuid}/snapshots/{snapshot_uuid}/restoreRestore onto this server, from any snapshot this customer owns
GET/api/v1/orgs/{org_slug}/portal/servers/{uuid}/softwareList installed software
GET/api/v1/orgs/{org_slug}/portal/servers/{uuid}/software/addonsEvery addon in the folders the server loads from, tracked or hand-uploaded
DELETE/api/v1/orgs/{org_slug}/portal/servers/{uuid}/software/addons/records/{record_uuid}Drop a tracking record whose files are gone, without touching the disk
POST/api/v1/orgs/{org_slug}/portal/servers/{uuid}/software/addons/removeDelete one addon from disk, through the tracked uninstall when it has a record
POST/api/v1/orgs/{org_slug}/portal/servers/{uuid}/software/addons/toggleSwitch one addon file on or off (Foo.jar <- Foo.jar.disabled)
POST/api/v1/orgs/{org_slug}/portal/servers/{uuid}/software/bedrockTurn Bedrock crossplay on or off for a Java server
GET/api/v1/orgs/{org_slug}/portal/servers/{uuid}/software/bedrock/packsBehavior and resource packs on disk, which are active in the world, and importable uploads
POST/api/v1/orgs/{org_slug}/portal/servers/{uuid}/software/bedrock/packs/disable-allEmpty the world's activation lists so it boots on vanilla content; folders stay
POST/api/v1/orgs/{org_slug}/portal/servers/{uuid}/software/bedrock/packs/importQueue an import of an uploaded .mcaddon / .mcpack / .zip already on the server
POST/api/v1/orgs/{org_slug}/portal/servers/{uuid}/software/bedrock/packs/{pack_uuid}/activeAdd a pack to, or drop it from, the world's activation list
POST/api/v1/orgs/{org_slug}/portal/servers/{uuid}/software/bedrock/packs/{pack_uuid}/removeDeactivate a pack, delete its folder, and drop its tracking row
PUT/api/v1/orgs/{org_slug}/portal/servers/{uuid}/software/bedrock/texturepack-requiredTexturepack-required: players must accept the resource packs to join
GET/api/v1/orgs/{org_slug}/portal/servers/{uuid}/software/catalogSoftware catalog
GET/api/v1/orgs/{org_slug}/portal/servers/{uuid}/software/catalog/{key}/versionsSoftware catalog versions
GET/api/v1/orgs/{org_slug}/portal/servers/{uuid}/software/catalog/{key}/versions/{version}/buildsPublisher builds of one game version: the loader versions for Fabric/Forge
POST/api/v1/orgs/{org_slug}/portal/servers/{uuid}/software/changeChange server software
GET/api/v1/orgs/{org_slug}/portal/servers/{uuid}/software/contextSoftware context
GET/api/v1/orgs/{org_slug}/portal/servers/{uuid}/software/dependencies/{source_uuid}/{identifier}What a version requires, named, with what is already installed marked
POST/api/v1/orgs/{org_slug}/portal/servers/{uuid}/software/installInstall software
GET/api/v1/orgs/{org_slug}/portal/servers/{uuid}/software/installsList software installs
GET/api/v1/orgs/{org_slug}/portal/servers/{uuid}/software/installs/{install_uuid}Get software install
POST/api/v1/orgs/{org_slug}/portal/servers/{uuid}/software/installs/{install_uuid}/cancelCancel software install
POST/api/v1/orgs/{org_slug}/portal/servers/{uuid}/software/installs/{install_uuid}/retryRetry software install
GET/api/v1/orgs/{org_slug}/portal/servers/{uuid}/software/jvmThe heap slider and the allowlisted startup flags, as the panel shows them
PATCH/api/v1/orgs/{org_slug}/portal/servers/{uuid}/software/jvmMove the heap, pick startup flags from the catalog, or reset both
GET/api/v1/orgs/{org_slug}/portal/servers/{uuid}/software/resource-packThe server resource pack as server.properties declares it
PUT/api/v1/orgs/{org_slug}/portal/servers/{uuid}/software/resource-packPoint players at a pack, from a URL or a marketplace resource pack version
DELETE/api/v1/orgs/{org_slug}/portal/servers/{uuid}/software/resource-packStop offering a server resource pack
POST/api/v1/orgs/{org_slug}/portal/servers/{uuid}/software/safe-modeArm a one-shot --safeMode start (vanilla datapack only), optionally starting now
POST/api/v1/orgs/{org_slug}/portal/servers/{uuid}/software/searchSearch software
GET/api/v1/orgs/{org_slug}/portal/servers/{uuid}/software/sourcesSoftware sources
GET/api/v1/orgs/{org_slug}/portal/servers/{uuid}/software/updatesNewer compatible builds for the addons the marketplace installed
GET/api/v1/orgs/{org_slug}/portal/servers/{uuid}/software/versions/{source_uuid}/{identifier}Software versions
DELETE/api/v1/orgs/{org_slug}/portal/servers/{uuid}/software/{record_uuid}Uninstall software
POST/api/v1/orgs/{org_slug}/portal/servers/{uuid}/software/{record_uuid}/updateQueue an in-place update: the old file is removed, the new build installed
PATCH/api/v1/orgs/{org_slug}/portal/servers/{uuid}/startup-variablesUpdate allowlisted startup env vars for the server's game
GET/api/v1/orgs/{org_slug}/portal/servers/{uuid}/status-pingAsk the game itself who is online
PATCH/api/v1/orgs/{org_slug}/portal/servers/{uuid}/subdomainRename the gameproxy join-address subdomain for this server
GET/api/v1/orgs/{org_slug}/portal/servers/{uuid}/usersList org subusers
POST/api/v1/orgs/{org_slug}/portal/servers/{uuid}/usersAdd org subuser
POST/api/v1/orgs/{org_slug}/portal/servers/{uuid}/users/leaveA subuser drops their own grant
PUT/api/v1/orgs/{org_slug}/portal/servers/{uuid}/users/{subuser_id}Update org subuser
DELETE/api/v1/orgs/{org_slug}/portal/servers/{uuid}/users/{subuser_id}Delete org subuser
POST/api/v1/orgs/{org_slug}/portal/servers/{uuid}/wakeAsk for a sleeping free server to be started
GET/api/v1/orgs/{org_slug}/portal/servers/{uuid}/websocketReturn panel WS URL + the caller's bearer token for WS query auth
GET/api/v1/orgs/{org_slug}/portal/servers/{uuid}/world-optimizationWhat unused-chunk cleanup has done to this world, and when
POST/api/v1/orgs/{org_slug}/portal/servers/{uuid}/world-optimizationQueue an unused-chunk trim now, once per minintervalhours
GET/api/v1/orgs/{org_slug}/portal/snapshotsEvery snapshot this customer holds, across every server they have had
GET/api/v1/orgs/{org_slug}/portal/snapshots/allowanceSnapshot allowance
GET/api/v1/orgs/{org_slug}/portal/snapshots/{snapshot_uuid}One snapshot, for the order form that was handed its uuid in a link
DELETE/api/v1/orgs/{org_slug}/portal/snapshots/{snapshot_uuid}Delete a snapshot the account owns, with or without its source server
GET/api/v1/orgs/{org_slug}/portal/snapshots/{snapshot_uuid}/downloadA signed URL for an archive whose server may no longer exist
POST/api/v1/orgs/{org_slug}/portal/snapshots/{snapshot_uuid}/lockKeep or release a snapshot the account owns, with or without its server
POST/api/v1/orgs/{org_slug}/portal/snapshots/{snapshot_uuid}/restoreRestore an account snapshot onto one of the customer's servers