🧑💻 API Documentation
AtomicHost User API
The AtomicHost User API lets you manage your own game services programmatically — the same services you can manage in the web panel, with the same permissions.
- Base URL:
https://atomichost.xyz/api/client/v1 - Auth: Bearer API key (one active key per account)
- Format: JSON request/response (
Accept: application/json) - Credits: every request costs credits from a daily allowance (default 2,500/day)
This is separate from the admin "application" API at
/api/v1.
1. Getting an API key
Generate, view, regenerate or revoke your key from Account → Settings → API Access.
- You may have one active key at a time.
- The full key is shown once, immediately after generation. Store it securely.
- Regenerating immediately invalidates the previous key.
- Keys look like
ah_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx. - We store only a salted SHA‑256 hash of the key — it cannot be recovered if lost.
Authenticating
Send the key as a Bearer token:
Authorization: Bearer ah_your_key_here
Accept: application/json
Every authenticated request is validated server-side for: a valid/active key, an existing non-banned account, ownership/permission of the target service, and rate/credit limits.
2. Credits & rate limiting
Two independent protections apply:
| Protection | Default | Exceeded response |
|---|---|---|
| Daily credits | 2,500/day (admin-configurable per user) | 429 daily_credit_limit_reached |
| Per-key rate limit | 120 requests/minute | 429 rate_limited |
- 1 credit = 1 request by default. Opening a console stream costs 5 credits; reading/sending on an open stream costs nothing extra.
- Credits reset once per day in the server's configured timezone.
- Failed requests caused by a server-side (
5xx) error are refunded.
Every response includes these headers:
X-RateLimit-Limit: 120
X-RateLimit-Remaining: 119
X-Credits-Limit: 2500
X-Credits-Used: 12
X-Credits-Remaining: 2488
X-Credits-Reset: 2026-06-28T00:00:00+00:00
3. Response & error format
Success:
{ "success": true, "data": { ... } }
Error:
{ "success": false, "error": { "code": "forbidden", "message": "..." } }
| Status | Meaning |
|---|---|
| 200 / 201 | OK |
| 401 | Missing / invalid / revoked / expired key |
| 403 | Banned account, or no permission for this service/action |
| 404 | Service not found or not yours (existence is never leaked) |
| 422 | Validation error (e.g. bad path, invalid signal) |
| 429 | Rate limit or daily credits exhausted |
| 502 | The service backend could not be reached |
Common error codes: missing_token, invalid_key, account_banned,
insufficient_service_permission, feature_unavailable, service_inactive,
not_found, validation_failed, rate_limited, daily_credit_limit_reached,
too_many_streams, backend_unavailable.
4. Permission model
The API never grants more than the website. For every service action we re-check, server-side:
- You are the owner, an admin, or a member that the owner granted the
matching permission (
console,files,backups, …). - The service is active and your package enables that feature.
If you were given access to someone else's service, the API only allows what that
owner granted you on that service. IDs in the request are never trusted — changing a
service ID to one that isn't yours returns 404.
5. Endpoints
Account
GET /me
Returns the key owner and current credit standing.
curl https://atomichost.xyz/api/client/v1/me \
-H "Authorization: Bearer ah_your_key" -H "Accept: application/json"
{
"success": true,
"data": {
"user": { "id": 42, "username": "steve", "email": "[email protected]" },
"api_key": { "name": "My Key", "prefix": "ah_ab12cd34", "created_at": "2026-06-27T10:00:00+00:00", "last_used_at": "2026-06-27T12:00:00+00:00" },
"credits": { "limit": 2500, "used": 12, "remaining": 2488, "reset_at": "2026-06-28T00:00:00+00:00", "reset_timezone": "UTC" }
}
}
Services
GET /servers
List every service you can access (owned + shared with you).
{ "success": true, "data": [
{ "id": 101, "name": "My Rust Server", "status": "active", "service": "pterodactyl",
"package": { "id": 5, "name": "Rust 4GB" }, "role": "owner",
"created_at": "2026-06-01T00:00:00+00:00", "due_date": "2026-07-01T00:00:00+00:00" }
] }
GET /servers/{id}
View a single service. (Relationship required.)
GET /servers/{id}/status
Live power state and resource usage.
{ "success": true, "data": {
"id": 101, "state": "running", "is_suspended": false,
"resources": { "memory_bytes": 1073741824, "cpu_absolute": 42.5, "disk_bytes": 5368709120 }
} }
POST /servers/{id}/power
Send a power signal. Requires the console permission.
Body: { "signal": "start" } — one of start, stop, restart, kill.
{ "success": true, "data": { "signal": "start", "accepted": true } }
Console (requires the console permission)
POST /servers/{id}/console/command
Send a single console command. Audited.
Body: { "command": "say hello" }
{ "success": true, "data": { "sent": true } }
GET /servers/{id}/console/stream — live output (SSE)
Opens a Server-Sent Events stream that relays live console output. Costs 5 credits to open.
- The connection is server-controlled: if you are banned or lose access, the stream is closed within ~15s. It also auto-closes after a max duration (default 10 min) — reconnect to continue.
- Up to 3 concurrent streams per account.
SSE events: ready, output (a console line), status (power state),
stats (resource JSON), error, closed.
const es = new EventSource(
"https://atomichost.xyz/api/client/v1/servers/101/console/stream",
// EventSource can't set headers; use a proxy/fetch-stream, or a browser
// extension that adds the Authorization header. See note below.
);
es.addEventListener("output", e => console.log(e.data));
es.addEventListener("closed", e => es.close());
Browsers' native
EventSourcecannot set anAuthorizationheader. Consume the stream from a server, a CLI (curl -N -H "Authorization: Bearer …"), or afetch()reader. Commands are sent over the separateconsole/commandendpoint.
curl -N https://atomichost.xyz/api/client/v1/servers/101/console/stream \
-H "Authorization: Bearer ah_your_key"
Files (requires the files permission)
All paths are validated against directory traversal; .. segments are rejected
with 422 before any backend call.
| Method | Path | Body / Query |
|---|---|---|
GET |
/servers/{id}/files?path=/ |
list a directory |
GET |
/servers/{id}/files/contents?path=/server.properties |
read a file |
POST |
/servers/{id}/files/write |
{ "path": "/a.txt", "content": "..." } |
POST |
/servers/{id}/files/delete |
{ "root": "/", "files": ["a.txt"] } |
POST |
/servers/{id}/files/create-folder |
{ "root": "/", "name": "plugins" } |
PUT |
/servers/{id}/files/rename |
{ "root": "/", "from": "a.txt", "to": "b.txt" } |
GET |
/servers/{id}/files/download?path=/world.zip |
returns a one-time download URL |
GET |
/servers/{id}/files/upload-url?path=/ |
returns a one-time upload URL |
curl "https://atomichost.xyz/api/client/v1/servers/101/files?path=/" \
-H "Authorization: Bearer ah_your_key" -H "Accept: application/json"
{ "success": true, "data": { "path": "/", "files": [
{ "name": "server.properties", "size": 1234, "is_file": true, "mode": "rw-r--r--" }
] } }
Backups (requires the backups permission)
| Method | Path | Body |
|---|---|---|
GET |
/servers/{id}/backups |
list backups |
POST |
/servers/{id}/backups |
{ "name": "pre-update", "ignored": "" } |
GET |
/servers/{id}/backups/{backup} |
view a backup |
DELETE |
/servers/{id}/backups/{backup} |
delete a backup |
curl -X POST https://atomichost.xyz/api/client/v1/servers/101/backups \
-H "Authorization: Bearer ah_your_key" -H "Accept: application/json" \
-d '{"name":"pre-update"}'
{ "success": true, "data": { "backup": { "uuid": "f3...", "name": "pre-update", "is_locked": false } } }
6. Banned / suspended accounts
If your account is banned or suspended, all API keys are revoked immediately,
in-flight console streams are closed, and further requests are rejected (403).
Unbanning does not restore the old key — generate a new one.