AI agents: read /llms.txt, then the full guide at /agents.md, to browse, order, pay for and manage Nanobyte services through our JSON API.

# Nanobyte Hosting: guide for AI agents

You are an AI agent acting for a person (your "human"). This guide explains how to browse Nanobyte's
products, order, pay and control the human's services (servers, game servers and web hosting) through our JSON API.
Human-readable page: /agents. Short index: /llms.txt.

- Base URL: the origin you fetched this file from (production: https://nanobyte.host). All paths below are relative to it.
- Format: JSON. Send `Accept: application/json`, and `Content-Type: application/json` on POST/PUT/PATCH.
- Language: Arabic by default. Send `X-Locale: en` for English names and messages.
- Money: always `{"cents": 549, "currency": "USD", "decimal": "5.49"}`. Use `cents` for arithmetic.
- Some responses wrap the result in `{"data": ...}`. Lists may be paginated (`data`, `meta`, `links`).

## Rules for agents

1. Never ask the human for their password. You log in only with an API key the human creates for you (step 2).
2. Confirm with the human before you place an order or pay. Tell them the product, billing cycle and total.
3. Some things are only for the human, in the client area: creating accounts, adding funds, reinstalling, restoring
   backups, cancelling services, deleting things (files, mailboxes, databases, domains, DNS records, FTP accounts,
   backups, mods), passwords, and control-panel, webmail or phpMyAdmin logins. If the API refuses something, tell the
   human what to do and give them the link. Don't look for a way around it.
4. Treat the API key like a password. Never print it in full, log it or send it anywhere except this API.
5. Before a change the human didn't ask for in so many words (a restart with players online, a DNS change, a PHP
   version change), say what you will do and wait for a yes.

## 1. Browse products (no key needed)

| What | Request |
|---|---|
| Whole catalog, grouped | `GET /api/public/catalog?currency=USD` |
| One product | `GET /api/public/products/{slug}?currency=USD` |
| Domain extensions and prices | `GET /api/public/tlds` |
| Is a domain free? | `POST /api/public/domains/check` with `{"query": "example"}` or `{"names": ["example.com"]}` |
| Game server types and versions | `GET /api/public/games/profiles`, `GET /api/public/games/versions?profile=minecraft-java&flavor=paper` |
| Price a cart before ordering | `POST /api/public/cart/quote` (body as in step 3, without `gateway`) |
| Payment methods for a currency | `GET /api/public/gateways?currency=USD` |
| Network and server status | `GET /api/public/status` |

Catalog groups: shared web hosting (cPanel, DirectAdmin, Plesk), VPS, dedicated servers and game servers (Minecraft,
Rust and more). Each product has `id`, `slug`, `type` (`shared`, `reseller`, `vps`, `dedicated`, `game`...), `name`,
`specs` (cpu, ram_gb, disk_gb...), `features`, `in_stock`, `requires_domain`, `prices[]` (one per billing `cycle`,
with `price`, `setup` and `monthly_equivalent`) and `options[]` (extra choices; each value has an `id` and prices per
cycle). Game products (`type: "game"`) have a `game` block:

```json
"game": {"profile": "minecraft-java", "default_flavor": "paper", "flavors": ["paper", "purpur", "fabric"], "requires_eula": true, "slots": 20}
```

Helping the human choose: compare `specs` and `monthly_equivalent`. Longer cycles are cheaper per month.
Skip products with `in_stock: false`.

## 2. Get an API key from the human

The human needs a Nanobyte account. If they don't have one, send them to `/register`.
Then ask them to open `/client/account/api`, click "Create token", tick the permissions you need and paste the key to you.

| Permission | Lets you |
|---|---|
| `read` (always on) | see services, invoices, domains, tickets and the account; see game servers (state, settings, backups, file list, mods) and web hosting (domains, email, databases, file list, DNS, SSL, PHP, cron, logs, stats, backups) |
| `orders:place` | place orders |
| `services:manage` | safe server controls: start/stop/restart, status, graphs, snapshot and backup create |
| `billing:pay` | pay invoices from the account's credit balance, up to the monthly limit the human set on the key |
| `tickets:write` | open and reply to support tickets |
| `games:control` | game servers: start/stop/restart, console commands and console session, change settings, take backups |
| `games:files` | game servers: read and edit files, upload, make folders, rename, copy, zip and unzip (no delete) |
| `games:mods` | game servers: install mods and plugins, switch them on or off (no remove) |
| `hosting:manage` | web hosting: add domains, redirects, forwarders, autoresponders, catch-all, spam filter, databases and grants, DNS records, SSL, cron jobs, PHP settings, take backups, install WordPress |
| `hosting:files` | web hosting files: write files, upload, make folders, rename, copy, move, zip and unzip (no read of file contents, no delete, no chmod) |

Send the key on every request: `Authorization: Bearer <key>`.

Check the key: `GET /api/client/api-key`

```json
{
  "key": {"name": "my agent", "abilities": ["read", "games:control"], "expires_at": "2027-01-01T00:00:00+00:00",
          "spend_limit_monthly": null, "spent_this_month": {"cents": 0, "currency": "USD", "decimal": "0.00"},
          "spend_remaining": {"cents": 0, "currency": "USD", "decimal": "0.00"}},
  "account": {"id": 7, "name": "Acme", "currency": "USD", "credit": {"cents": 2500, "currency": "USD", "decimal": "25.00"}},
  "safe_service_actions": ["power_status", "graphs", "..."],
  "safe_file_ops": {"game": ["mkdir", "rename", "copy", "compress", "decompress"], "hosting": ["mkdir", "rename", "copy", "move"]},
  "docs": "https://nanobyte.host/agents.md"
}
```

## 3. Order (needs `orders:place`)

1. Price the cart with `POST /api/public/cart/quote`. Fix everything listed in `errors[]` before ordering.
2. Show the human the lines and `total_due_today`, and ask them to confirm.
3. Place the order:

```http
POST /api/client/orders
Authorization: Bearer <key>
Content-Type: application/json

{
  "items": [
    {"type": "product", "product_id": 12, "cycle": "monthly", "label": "web1.example.com", "options": {"os": 31}},
    {"type": "domain", "name": "example.com", "action": "register", "years": 1}
  ],
  "gateway": "bank_transfer",
  "promo_code": null
}
```

Item fields:
- Product: `product_id`, `cycle` (one of the product's `prices[].cycle`), optional `options` (`{option key: value id}`),
  `label` (domain or hostname; required when `requires_domain` is true).
- Web hosting plan (`type: "shared"` or `"reseller"`): `label` is the site's main domain (`"label": "example.com"`).
  Add a `domain` item in the same order if the human still needs to register or transfer it.
- Game server plan (`type: "game"`): also `game_slug` (the address: `myserver` gives `myserver.play.nanobyte.host`;
  check it first with `GET /api/client/games/slug-check?slug=myserver` → `{"data": {"available": true}}` or
  `{"data": {"available": false, "reason": "taken"}}`), `game_flavor` (one of `game.flavors`), `game_version`
  (from `GET /api/public/games/versions`, default `latest`), `eula: true` when `game.requires_eula` (ask the human
  first: they accept the game's licence), and `game_inputs` if the profile asks for any. Example:

```json
{"type": "product", "product_id": 41, "cycle": "monthly", "game_slug": "myserver", "game_flavor": "paper", "game_version": "1.21.4", "eula": true}
```

- Domain: `name`, `action` (`register`, `transfer` or `renew`), `years`, and `epp` (the transfer code) for transfers.
- `gateway`: one `key` from `GET /api/public/gateways?currency=<account currency>`. It only sets how the invoice is paid
  if nobody pays it from credit.

The response (201) contains `order`, `invoice_id`, `invoice_status` and `payment_url`.
Services start once the invoice is paid. Game errors in `errors[]`/422: `eula_required`, `slug_invalid`,
`slug_reserved`, `slug_taken`, `flavor_invalid`, `version_invalid`, `node_out_of_capacity` (the message says which).

## 4. Pay (needs `billing:pay`)

- Pay from credit: `POST /api/client/invoices/{invoice_id}/apply-credit`. This pays the whole invoice or nothing.
  It works only if the account credit covers the balance and the payment fits in the key's monthly limit.
- If it is refused (HTTP 422, `code` starting with `agent_payment_`), give the human the `payment_url` from the
  response. They pay there by card, PayPal or bank transfer. Codes: `agent_payment_credit` (not enough credit),
  `agent_payment_limit` (over the monthly limit), `agent_payment_no_limit` (this key may not pay),
  `agent_payment_currency`, `agent_payment_not_payable`.
- Invoices: `GET /api/client/invoices`, `GET /api/client/invoices/{id}`, PDF at `GET /api/client/invoices/{id}/pdf`.
- You cannot add funds. The human does that at `/client/add-funds`.

## 5. Control services

| What | Request | Permission |
|---|---|---|
| Dashboard summary | `GET /api/client/dashboard` | read |
| List services | `GET /api/client/services` | read |
| Service details (`actions[]` = what it supports) | `GET /api/client/services/{id}` | read |
| Live status | `GET /api/client/services/{id}/status` | read |
| Run an action | `POST /api/client/services/{id}/actions/{action}` | services:manage |
| Follow a queued action | `GET /api/client/services/{id}/actions/{action_id}` | read |
| Domains | `GET /api/client/domains`, `GET /api/client/domains/{id}` | read |

Actions you may run: `start`, `stop`, `shutdown`, `reboot`, `restart`, `power`, `wol`, `power_status`, `graphs`,
`usage`, `snapshots`, `snapshots_list`, `snapshot_create`, `backup_create`, `rdns_list`, `subaccounts_list`,
`hostname_available`. Each service lists the ones it supports in `actions[]`, with their parameters.
Changing actions answer `202` with an action to poll. Read-only ones answer at once.

Queued work (here, on game servers and on web hosting) answers **202** with:

```json
{"action": {"id": 812, "action": "power", "status": "queued", "error": null, "result": {}, "created_at": "2026-10-03T10:00:00+00:00", "finished_at": null}}
```

Poll `GET /api/client/services/{id}/actions/812` every few seconds until `status` is `succeeded`, `failed` or `dry_run`.
Only one action runs per service at a time: a second one while it is busy answers 422.

## 6. Game servers

Find them in `GET /api/client/services` (`product.type: "game"`). Paths below start with
`/api/client/services/{id}/game`. Changes need an active, installed server (else 422).

| What | Request | Permission |
|---|---|---|
| State, address, players, resources | `GET /game` | read |
| Settings (values and schema) | `GET /game/settings` | read |
| Backups | `GET /game/backups` | read |
| List files | `GET /game/files?path=/` | read |
| Installed mods / what the Mods tab offers / search | `GET /game/mods`, `GET /game/mods/info`, `GET /game/mods/search?q=worldedit&page=1` | read |
| Preview a Steam Workshop item | `GET /game/mods/workshop?id=<link or id>` | read |
| Start / stop / restart / kill | `POST /game/power` | games:control |
| Console command | `POST /game/command` | games:control |
| Live console (WebSocket token) | `POST /game/session` with `{"scopes": ["console"]}` | games:control |
| Change settings | `PUT /game/settings` | games:control |
| Take a backup | `POST /game/backups` | games:control |
| Read / write a text file | `GET /game/files/content?path=...`, `PUT /game/files/content` | games:files |
| File operations | `POST /game/files/{op}`, op = `mkdir`, `rename`, `copy`, `compress`, `decompress` | games:files |
| Upload a file | `POST /game/uploads`, or `POST /game/session` with `{"scopes": ["files"]}` for downloads | games:files |
| Install a mod or plugin | `POST /game/mods` | games:mods |
| Switch a mod on or off (Factorio) | `PATCH /game/mods` | games:mods |

Server state:

```http
GET /api/client/services/58/game
```
```json
{"data": {"profile": "minecraft-java", "flavor": "paper", "version": "1.21.4", "slug": "myserver",
  "address": {"host": "myserver.play.nanobyte.host", "port": null, "display": "myserver.play.nanobyte.host"},
  "state": "running", "node": "Atlas", "players": {"online": 3, "max": 20},
  "resources": {"cpu": 25, "ram_used": 1073741824, "ram_total": 4294967296, "disk_used": 2147483648, "disk_total": 21474836480},
  "capabilities": ["power", "console", "files", "settings", "backups", "reinstall", "address", "mods"], "provisioning_step": null}}
```

`state` is `installing`, `failed`, `suspended`, or the game's own state (`running`, `stopped`, `starting`...).

Power (`action`: `start`, `stop`, `restart` or `kill`), answers 202 with an action to poll:

```http
POST /api/client/services/58/game/power
{"action": "restart"}
```

Console command (one line, at most 500 characters):

```http
POST /api/client/services/58/game/command
{"line": "say Restart in 5 minutes"}
```
```json
{"data": {"ok": true}}
```

Live console: `POST /game/session` with `{"scopes": ["console"]}` returns
`{"data": {"agent_url": "https://atlas.example", "token": "sess-...", "expires_at": "..."}}`. Open
`wss://<agent_url host>/v1/ws/console?token=<token>` before `expires_at` (at most 15 minutes), from the same IP.
Most agents only need `POST /game/command` and `GET /game` (players and state).

Settings: `GET /game/settings` returns `{"data": {"values": {"motd": "Hello", "max-players": 20, "pvp": true}, "schema": [{"key": "max-players", "type": "int", "min": 1, "max": 200, "label_key": "games.settings.max-players"}, ...]}}`
(`type`: `string`, `int`, `bool` or `enum` with `options`).
Change only keys listed in `schema`, within its limits (unknown or out-of-range values → 422). Most changes need a restart.

```http
PUT /api/client/services/58/game/settings
{"values": {"motd": "Welcome!", "max-players": 30}}
```

Backups: `GET /game/backups` → `{"data": [{"id": "b-1", "name": "auto", "size": 1000, "created_at": "2026-10-01T00:00:00Z"}]}`.
`POST /game/backups` (no body) takes a new one (202).

Files: paths are relative to the server folder (`""` or `/` is the top). `GET /game/files?path=plugins` →
`{"data": [{"name": "server.properties", "type": "file", "size": 1200, "mtime": 1700000000}]}`.
Text files up to 2 MB:

```http
GET /api/client/services/58/game/files/content?path=server.properties
```
```json
{"data": {"content": "motd=Hello\n"}}
```
```http
PUT /api/client/services/58/game/files/content
{"path": "server.properties", "content": "motd=Hi\n"}
```

File operations: `mkdir {"path"}`, `rename {"path", "to"}`, `copy {"path" or "paths", "to"}`,
`compress {"path" or "paths", "to": "archive.zip"}`, `decompress {"path", "to"?}` → `{"data": {"ok": true}}`.
Upload: `POST /game/uploads` with `{"path": "plugins/My.jar", "size": 1234, "sha256": "<hex>"}` →
`{"data": {"agent_url", "upload_id", "chunk_size", "token"}}`; send the chunks with
`PUT <agent_url>/v1/uploads/<upload_id>/<n>` (`Authorization: Bearer <token>`), then `POST <agent_url>/v1/uploads/<upload_id>/complete`.

Mods: search the server's catalogue, then install by id. The server picks the right file for the game version and
installs dependencies. A URL in the body is refused.

```http
GET /api/client/services/58/game/mods/search?q=worldedit
```
```json
{"data": {"items": [{"project_id": "1u6JkXh5", "title": "WorldEdit", "description": "...", "icon_url": "...", "downloads": 1000, "author": "enginehub", "source": "modrinth"}], "total": 1}}
```
```http
POST /api/client/services/58/game/mods
{"source": "modrinth", "project_id": "1u6JkXh5"}
```
```json
{"data": {"file": "worldedit.jar", "name": "WorldEdit", "source": "modrinth", "installed": [{"file": "worldedit.jar", "name": "WorldEdit"}], "needs_restart": true}}
```

Steam Workshop games: `{"source": "steam_workshop", "workshop_id": "<link or id>", "mod_ids": ["..."]}`.
Restart the server after installing (`needs_restart: true`).

Only the human can, at `/client/services/{id}`: reinstall or change the game/version, change the server address,
restore or delete backups, delete files, remove mods, and cancel the server.

## 7. Web hosting

Find hosting accounts in `GET /api/client/services` (`product.type: "shared"` or `"reseller"`). Paths below start with
`/api/client/services/{id}/hosting`.

- `GET /hosting` first. Its `capabilities` say which sections this account's panel supports
  (`{"email": {"read": true, "write": true, "actions": [...]}, ...}`); a section or action it lacks answers 409
  `{"error": "unsupported"}`.
- Every change answers `{"data": {..., "dry_run": false}}`. `dry_run: true` means it was checked but not applied
  (test systems). Long jobs (SSL, backup, zip/unzip, app install) answer 202 with an action to poll.
- File paths are relative to the account's home: `public_html/index.php`. Absolute paths and `..` → 422.
- Names that are not in this account (a mailbox, database, domain, record...) → 404 `{"error": "not_found"}`.
- 422 `{"error": "panel_error"}`: the panel refused (reason in `message`). 503 `{"error": "panel_unavailable"}`: try later.

| What | Request | Permission |
|---|---|---|
| Overview: panel, usage, limits, capabilities | `GET /hosting` | read |
| Domains, redirects | `GET /hosting/domains`, `GET /hosting/redirects` | read |
| Mailboxes, forwarders, autoresponders, catch-all, spam filter | `GET /hosting/email`, `/forwarders`, `/autoresponders`, `/catchall`, `/spam` | read |
| Databases and database users | `GET /hosting/databases`, `GET /hosting/db-users` | read |
| List files | `GET /hosting/files?path=public_html` | read |
| FTP accounts | `GET /hosting/ftp` | read |
| DNS records | `GET /hosting/dns?domain=example.com` | read |
| SSL certificates (no keys) | `GET /hosting/ssl` | read |
| Backups, cron jobs, PHP, logs, stats, apps | `GET /hosting/backups`, `/cron`, `/php`, `/logs?type=error&lines=200`, `/stats`, `/apps` | read |
| Add an addon domain, alias or subdomain | `POST /hosting/domains` | hosting:manage |
| Add a redirect | `POST /hosting/redirects` | hosting:manage |
| Add a forwarder | `POST /hosting/forwarders` | hosting:manage |
| Set an autoresponder | `PUT /hosting/autoresponders/{address}` | hosting:manage |
| Set the catch-all, spam filter | `PUT /hosting/catchall`, `PUT /hosting/spam` | hosting:manage |
| Create a database, set a user's grants | `POST /hosting/databases`, `PUT /hosting/databases/{name}/grants` | hosting:manage |
| Add or change a DNS record | `POST /hosting/dns`, `PUT /hosting/dns/{id}` | hosting:manage |
| Issue a free SSL certificate, install your own | `POST /hosting/ssl/issue`, `PUT /hosting/ssl/custom` | hosting:manage |
| Add or change a cron job | `POST /hosting/cron`, `PUT /hosting/cron/{id}` | hosting:manage |
| PHP version and settings | `PUT /hosting/php` | hosting:manage |
| Take a backup | `POST /hosting/backups` | hosting:manage |
| Install WordPress | `POST /hosting/apps` | hosting:manage |
| Write a text file, upload | `PUT /hosting/files/content`, `POST /hosting/files/upload` (multipart `file`, `path`) | hosting:files |
| File operations | `POST /hosting/files/{op}`, op = `mkdir`, `rename`, `copy`, `move` | hosting:files |
| Zip, unzip | `POST /hosting/files/compress`, `POST /hosting/files/extract` | hosting:files |

Overview:

```http
GET /api/client/services/77/hosting
```
```json
{"data": {"panel": "cpanel", "os": "linux", "live": true,
  "account": {"username": "alice", "domain": "example.com", "ip": "192.0.2.10", "nameservers": ["ns1.example.net"], "home": "/home/alice"},
  "usage": {"disk": {"used": 104857600, "limit": null}, "bandwidth": {"used": 52428800, "limit": 1073741824},
            "mailboxes": {"used": 1, "limit": 10}, "databases": {"used": 1, "limit": null}, "domains": {"used": 2, "limit": 6}},
  "capabilities": {"email": {"read": true, "write": true, "actions": ["create", "update", "delete"]}, "...": {}}}}
```

Disk and bandwidth are bytes. `limit: null` means unlimited.

Request bodies:
- `POST /domains`: `{"type": "addon" | "alias" | "sub", "name": "shop.example.com", "docroot": "shop"}`
- `POST /redirects`: `{"source_domain": "example.com", "path": "/old", "target": "https://example.com/new", "type": 301}`
- `POST /forwarders`: `{"address": "[email protected]", "to": "[email protected]"}`
- `PUT /autoresponders/[email protected]`: `{"subject": "Away", "body": "Back on Monday", "start": "2026-10-03", "stop": "2026-10-06"}`
- `PUT /catchall`: `{"domain": "example.com", "action": "fail" | "blackhole" | "forward", "to": "[email protected]"}`
- `PUT /spam`: `{"enabled": true, "score": 5}`
- `POST /databases`: `{"name": "alice_shop"}`. `PUT /databases/alice_shop/grants`: `{"user": "alice_wp", "privileges": "ALL"}` (or a list like `["SELECT", "INSERT"]`)
- `POST /dns`, `PUT /dns/{id}`: `{"domain": "example.com", "type": "A", "name": "www", "value": "192.0.2.10", "ttl": 300}` (`priority` for MX/SRV).
  Check `zone_managed_here` in `GET /dns?domain=` first: when false, the domain's DNS is elsewhere and edits do nothing.
- `POST /ssl/issue`: `{"domain": "example.com"}` (202). `PUT /ssl/custom`: `{"domain", "cert", "key", "ca"?}` (PEM)
- `POST /cron`, `PUT /cron/{id}`: `{"minute": "*/15", "hour": "*", "day": "*", "month": "*", "weekday": "*", "command": "php ~/public_html/cron.php"}`
- `PUT /php`: `{"domain": "example.com", "version": "ea-php83", "ini": {"memory_limit": "256M"}}` (versions from `GET /php`)
- `POST /apps`: `{"app": "wordpress", "domain": "example.com", "path": "", "title": "My blog", "admin_user": "owner", "admin_email": "[email protected]"}` (202).
  The WordPress admin password goes to the human in the client area, never to you.
- `PUT /files/content`: `{"path": "public_html/index.html", "content": "<h1>Hi</h1>"}` (UTF-8 text, at most 2 MB)
- `POST /files/mkdir`: `{"path": "public_html/new"}`. `rename`: `{"path", "to"}`. `copy`, `move`: `{"path" or "paths", "to": "<folder>"}`
- `POST /files/compress`: `{"paths": ["public_html"], "to": "site.zip"}`. `POST /files/extract`: `{"path": "site.zip", "to": "public_html"}`

Example, add a forwarder:

```http
POST /api/client/services/77/hosting/forwarders
{"address": "[email protected]", "to": "[email protected]"}
```
```json
{"data": {"ok": true, "dry_run": false}}
```

Only the human can, at `/client/services/{id}`: create mailboxes, FTP accounts or database users (they come with
passwords), change any password, open webmail or phpMyAdmin, read or download file contents (they hold database
passwords), download or restore backups, change file permissions, and delete anything (domains, redirects, mailboxes,
forwarders, autoresponders, databases, database users, files, FTP accounts, DNS records, cron jobs).

## 8. Support (needs `tickets:write` to write)

- Departments: `GET /api/client/departments`
- Tickets: `GET /api/client/tickets`, `GET /api/client/tickets/{id}`
- Open: `POST /api/client/tickets` with `{"department_id": 1, "subject": "...", "message": "...", "service_id": 42}`
- Reply: `POST /api/client/tickets/{id}/reply` with `{"message": "..."}`. Close: `POST /api/client/tickets/{id}/close`

## Errors

| Status | Meaning | What to do |
|---|---|---|
| 401 | Key missing, wrong, expired or revoked | Ask the human for a new key |
| 403 `api_key_scope` | The key lacks a permission (`required_ability`), or keys can't do this at all (`required_ability: null`) | Tell the human; they can do it in the client area or make a key with that permission |
| 403 `api_key_client` | The key's account is no longer reachable | Ask for a new key |
| 403 (other) | The service belongs to another account | Check the id |
| 404 | Not found, not on this account, or not this kind of service | Check the id |
| 409 `unsupported` | This hosting panel doesn't offer that section or action | Tell the human |
| 422 | Validation or business rule: `message`, plus `errors{field: [..]}` | Fix the input, or explain the message to the human |
| 429 | Too many requests | Wait and retry later. Don't loop |
| 503 `panel_unavailable` | The hosting panel didn't answer | Try again in a few minutes |

Every response message is safe to show to the human.

## Appendix: every endpoint a key can call

Anything not in this list answers 403 `api_key_scope` with `required_ability: null`, whatever the key's permissions.
`{service}` is a service id. File operations are limited to the ops listed in sections 6 and 7, and service actions to
the list in section 5.

```text
GET    /api/auth/me                                                        read
GET    /api/client/api-key                                                 read
GET    /api/client/dashboard                                               read
GET    /api/client/services                                                read
GET    /api/client/services/{service}                                      read
GET    /api/client/services/{service}/status                               read
GET    /api/client/services/{service}/actions/{serviceAction}              read
POST   /api/client/services/{service}/actions/{action}                     services:manage
GET    /api/client/services/{service}/hostname/check                       read
GET    /api/client/games/slug-check                                        read
GET    /api/client/services/{service}/game                                 read
GET    /api/client/services/{service}/game/settings                        read
GET    /api/client/services/{service}/game/backups                         read
GET    /api/client/services/{service}/game/files                           read
GET    /api/client/services/{service}/game/mods                            read
GET    /api/client/services/{service}/game/mods/info                       read
GET    /api/client/services/{service}/game/mods/search                     read
GET    /api/client/services/{service}/game/mods/workshop                   read
POST   /api/client/services/{service}/game/power                           games:control
POST   /api/client/services/{service}/game/command                         games:control
POST   /api/client/services/{service}/game/session                         games:control
PUT    /api/client/services/{service}/game/settings                        games:control
POST   /api/client/services/{service}/game/backups                         games:control
GET    /api/client/services/{service}/game/files/content                   games:files
PUT    /api/client/services/{service}/game/files/content                   games:files
POST   /api/client/services/{service}/game/files/{op}                      games:files
POST   /api/client/services/{service}/game/uploads                         games:files
POST   /api/client/services/{service}/game/mods                            games:mods
PATCH  /api/client/services/{service}/game/mods                            games:mods
GET    /api/client/services/{service}/hosting                              read
GET    /api/client/services/{service}/hosting/domains                      read
GET    /api/client/services/{service}/hosting/redirects                    read
GET    /api/client/services/{service}/hosting/email                        read
GET    /api/client/services/{service}/hosting/forwarders                   read
GET    /api/client/services/{service}/hosting/autoresponders               read
GET    /api/client/services/{service}/hosting/catchall                     read
GET    /api/client/services/{service}/hosting/spam                         read
GET    /api/client/services/{service}/hosting/databases                    read
GET    /api/client/services/{service}/hosting/db-users                     read
GET    /api/client/services/{service}/hosting/files                        read
GET    /api/client/services/{service}/hosting/ftp                          read
GET    /api/client/services/{service}/hosting/dns                          read
GET    /api/client/services/{service}/hosting/ssl                          read
GET    /api/client/services/{service}/hosting/backups                      read
GET    /api/client/services/{service}/hosting/cron                         read
GET    /api/client/services/{service}/hosting/php                          read
GET    /api/client/services/{service}/hosting/logs                         read
GET    /api/client/services/{service}/hosting/stats                        read
GET    /api/client/services/{service}/hosting/apps                         read
POST   /api/client/services/{service}/hosting/domains                      hosting:manage
POST   /api/client/services/{service}/hosting/redirects                    hosting:manage
POST   /api/client/services/{service}/hosting/forwarders                   hosting:manage
PUT    /api/client/services/{service}/hosting/autoresponders/{address}     hosting:manage
PUT    /api/client/services/{service}/hosting/catchall                     hosting:manage
PUT    /api/client/services/{service}/hosting/spam                         hosting:manage
POST   /api/client/services/{service}/hosting/databases                    hosting:manage
PUT    /api/client/services/{service}/hosting/databases/{name}/grants      hosting:manage
POST   /api/client/services/{service}/hosting/dns                          hosting:manage
PUT    /api/client/services/{service}/hosting/dns/{id}                     hosting:manage
POST   /api/client/services/{service}/hosting/ssl/issue                    hosting:manage
PUT    /api/client/services/{service}/hosting/ssl/custom                   hosting:manage
POST   /api/client/services/{service}/hosting/cron                         hosting:manage
PUT    /api/client/services/{service}/hosting/cron/{id}                    hosting:manage
PUT    /api/client/services/{service}/hosting/php                          hosting:manage
POST   /api/client/services/{service}/hosting/backups                      hosting:manage
POST   /api/client/services/{service}/hosting/apps                         hosting:manage
PUT    /api/client/services/{service}/hosting/files/content                hosting:files
POST   /api/client/services/{service}/hosting/files/upload                 hosting:files
POST   /api/client/services/{service}/hosting/files/{op}                   hosting:files
POST   /api/client/services/{service}/hosting/files/compress               hosting:files
POST   /api/client/services/{service}/hosting/files/extract                hosting:files
GET    /api/client/domains                                                 read
GET    /api/client/domains/{domain}                                        read
POST   /api/client/orders                                                  orders:place
GET    /api/client/invoices                                                read
GET    /api/client/invoices/{invoice}                                      read
GET    /api/client/invoices/{invoice}/pdf                                  read
GET    /api/client/transactions                                            read
POST   /api/client/invoices/{invoice}/apply-credit                         billing:pay
POST   /api/client/invoices/{invoice}/pay                                  billing:pay
GET    /api/client/departments                                             read
GET    /api/client/tickets                                                 read
GET    /api/client/tickets/{ticket}                                        read
GET    /api/client/tickets/{ticket}/attachments/{reply}/{index}            read
POST   /api/client/tickets                                                 tickets:write
POST   /api/client/tickets/{ticket}/reply                                  tickets:write
POST   /api/client/tickets/{ticket}/close                                  tickets:write
```