Getting started
- Sign in to your ServerPrism account.
- Open Account → API Credentials and create a token.
- Pick the smallest set of scopes your integration needs.
- Copy the token once when it's shown — we never store it in cleartext and cannot recover it.
- Use the token as a Bearer credential against the endpoints below.
All requests go to https://serverprism.com. All responses are JSON. All timestamps are UTC ISO-8601.
Authentication
Pass the token in an Authorization: Bearer header. Tokens are personal — each one belongs to a single ServerPrism customer and can only act on services that customer owns.
curl https://serverprism.com/api/v1/client/servers \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Accept: application/json"
Tokens you create through the dashboard are personal access tokens. The OAuth client-credentials and authorization-code flows are not currently exposed for customer integrations.
Scopes
Each token carries one or more scopes. An endpoint requires a specific scope to be present — missing scope returns 403.
| Scope | Allows |
|---|---|
servers:read |
View your servers (status, resources, basic info) |
servers:control |
Send power signals (start/stop/restart/kill) and console commands to your servers |
backups:create |
Create new backups of your servers (counts against your backup slots) |
billing:read |
View your services' billing details and your invoices (including PDF download) |
tickets:read |
View your support tickets and their replies |
tickets:write |
Open new support tickets and reply to your existing tickets |
account:read |
View your basic account details (name, email address) |
Rate limits
Limits are per minute and apply twice: once per token and once across all tokens on your account (whichever runs out first). They are deliberately conservative. If you need more, open a ticket and tell us about your integration.
| Bucket | Limit | Endpoints |
|---|---|---|
read |
60 per token, 120 per account | All GET endpoints except the invoice PDF |
control |
20 per token, 30 per account | Power, command, create backup, invoice PDF |
tickets |
5 per token, 10 per account; plus 1 new ticket per 30 seconds | Open ticket, reply to ticket |
Exceeding a limit returns 429 Too Many Requests with a Retry-After header. Every response carries X-RateLimit-Limit and X-RateLimit-Remaining for the token bucket. Back off and retry; never tight-loop on a 429.
Errors
Error bodies are JSON with a human-readable message and, for API-specific errors, a stable machine-readable error code such as service_not_active. Validation errors (422) also include an errors object keyed by field.
| Status | Meaning |
|---|---|
| 401 | Missing or invalid token. |
| 403 | Token does not include the required scope. |
| 404 | Not found, or it does not belong to you (both look the same on purpose). |
| 409 | The server is in a state that doesn't allow this: service_not_active (suspended, cancelled, pending), service_paused (cold storage), server_offline, server_busy, backup_limit_reached, backup_in_progress. |
| 422 | Request body failed validation. |
| 429 | Rate limit exceeded. |
| 503 | Upstream node temporarily unavailable. Retry after a short delay. |
Endpoints
Server ID in URLs is the numeric Service ID, the same one in your /services/{id} URL. All paths below are relative to https://serverprism.com/api/v1/client. List endpoints accept page and per_page (max 100) and return a meta block with total and last_page.
/api/v1/client/servers
scope: servers:read
Lists every active or suspended service owned by the token holder. Cheap to poll: it does not contact the server.
Request
curl https://serverprism.com/api/v1/client/servers \
-H "Authorization: Bearer YOUR_TOKEN"
Response
{
"data": [
{
"id": 1234,
"product": "Minecraft 4 GB",
"service_status": "active",
"name": "Fred's Minecraft",
"paused": false,
"game": { "slug": "minecraft", "name": "Minecraft", "runtime": "paper", "version": "1.21.4" },
"expires_at": "2026-11-01T00:00:00+00:00"
}
]
}
/api/v1/client/servers/{id}
scope: servers:read
Everything from the list endpoint plus the connection address players use, the server's ports, its limits, and best-effort live resource usage.
Response
{
"data": {
"id": 1234,
"name": "Fred's Minecraft",
"service_status": "active",
"paused": false,
"game": { "slug": "minecraft", "name": "Minecraft", "runtime": "paper", "version": "1.21.4" },
"expires_at": "2026-11-01T00:00:00+00:00",
"address": "fredcraft.example.com",
"allocations": [
{ "ip": "203.0.113.7", "port": 25565, "primary": true, "notes": null }
],
"limits": {
"memory_mb": 4096,
"disk_mb": 25600,
"cpu_percent": 200
},
"resources": {
"current_state": "running",
"memory_bytes": 2147483648,
"cpu_absolute": 18.5,
"disk_bytes": 7300000000,
"network_rx_bytes": 12345678,
"network_tx_bytes": 87654321,
"uptime_ms": 3600000
}
}
}
The resources block may be null if the node was briefly unreachable. Retry, or fall back to the panel UI's status indicator.
/api/v1/client/servers/{id}/power
scope: servers:control
Sends a power signal to the server. Only works while the service is active: suspended, cancelled or paused services return 409.
Request body
{
"signal": "start" // one of: "start", "stop", "restart", "kill"
}
kill hard-terminates the process without giving the game a chance to save. Use stop for graceful shutdowns of survival/save-state games.
Example
curl -X POST https://serverprism.com/api/v1/client/servers/1234/power \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"signal":"restart"}'
Response
{ "data": { "signal": "restart", "sent": true } }
/api/v1/client/servers/{id}/command
scope: servers:control
Sends a single console command to the running server (e.g. say hello, stop, whitelist add Notch). The server must be running; if it isn't you get 409 server_offline.
Request body
{
"command": "say Server restarting in 5 minutes"
}
One line, maximum 1024 characters. Newlines and other control characters are rejected with 422: send one request per command.
Response
{ "data": { "command": "say Server restarting in 5 minutes", "sent": true } }
/api/v1/client/servers/{id}/backups
scope: servers:read
Lists the server's backups and your backup slots. Slots are shared across all your servers and scale with your plan RAM.
Response
{
"data": [
{
"uuid": "6f1c0e2a-...",
"name": "nightly",
"status": "completed", // "in_progress" | "completed" | "failed"
"size_bytes": 734003200,
"locked": false,
"created_at": "2026-09-30T03:00:00+00:00",
"completed_at": "2026-09-30T03:04:12+00:00"
}
],
"meta": { "quota": { "used": 2, "total": 3, "can_create_more": true, "is_trial": false } }
}
/api/v1/client/servers/{id}/backups
scope: backups:create
Starts a backup and returns 202 straight away. Backups run in the background: poll the list endpoint until status is completed or failed. Each backup uses one slot; when you are out of slots you get 409 backup_limit_reached. Trial plans don't include backups (403). Restoring and deleting backups is only available in the dashboard.
Request body (optional)
{ "name": "before-1.21-update" }
Response (202)
{ "data": { "uuid": "9a2b...", "name": "before-1.21-update", "status": "in_progress", "size_bytes": 0, "locked": false, "created_at": "2026-10-01T12:00:00+00:00", "completed_at": null } }
/api/v1/client/account
scope: account:read
Response
{ "data": { "id": 42, "first_name": "Fred", "last_name": "Smith", "email": "[email protected]", "email_verified": true, "created_at": "2025-03-01T10:00:00+00:00" } }
/api/v1/client/services
scope: billing:read
All your services in every status, with billing details. Optional filter ?status= one of pending, provisioning, active, suspended, cancelled, failed.
Response
{
"data": [
{
"id": 1234,
"name": "Fred's Minecraft",
"product": "Minecraft 4 GB",
"status": "active",
"paused": false,
"plan": { "name": "Monthly", "type": "recurring", "billing_period": 1, "billing_unit": "month" },
"quantity": 1,
"price": { "amount": "8.00", "currency": "EUR", "formatted": "€8.00" },
"next_due_date": "2026-11-01T00:00:00+00:00",
"cancellation_requested": false,
"cancellation_type": null,
"created_at": "2026-05-01T09:12:00+00:00"
}
],
"meta": { "current_page": 1, "per_page": 25, "total": 1, "last_page": 1 }
}
/api/v1/client/invoices
scope: billing:read
Your invoices, newest first. Optional filter ?status=pending|paid|cancelled.
Response
{
"data": [
{
"id": 5512,
"number": "SP-2026-05512",
"status": "pending",
"currency": "EUR",
"total": { "amount": "8.00", "currency": "EUR", "formatted": "€8.00" },
"tax": { "amount": "1.60", "currency": "EUR", "formatted": "€1.60" },
"remaining": { "amount": "8.00", "currency": "EUR", "formatted": "€8.00" },
"due_at": "2026-10-04T00:00:00+00:00",
"created_at": "2026-09-27T00:00:00+00:00",
"pdf_url": "https://serverprism.com/api/v1/client/invoices/5512/pdf",
"dashboard_url": "https://serverprism.com/invoices/SP-2026-05512"
}
],
"meta": { "current_page": 1, "per_page": 25, "total": 1, "last_page": 1 }
}
To pay an invoice, open its dashboard_url. The API never moves money.
/api/v1/client/invoices/{id}
scope: billing:read
Same fields as the list plus the line items. {id} is the numeric id, not the invoice number.
Response (excerpt)
{
"data": {
"id": 5512,
"status": "pending",
"items": [
{ "description": "Minecraft 4 GB (Oct 01, 2026 - Nov 01, 2026)", "quantity": 1, "unit_price": "8.00", "total": "8.00", "service_id": 1234 }
]
}
}
/api/v1/client/invoices/{id}/pdf
scope: billing:read
Downloads the invoice as a PDF (application/pdf), the same document as the dashboard's download button. Counts against the control rate-limit bucket.
curl -o invoice.pdf https://serverprism.com/api/v1/client/invoices/5512/pdf \
-H "Authorization: Bearer YOUR_TOKEN"
/api/v1/client/tickets
scope: tickets:read
Your support tickets, most recently updated first. Optional filter ?status=open|replied|closed. replied means our team answered and is waiting for you.
Response
{
"data": [
{
"id": 1301,
"subject": "Server lagging in the evening",
"status": "replied",
"priority": "medium",
"department": "Support",
"service_id": 1234,
"messages_count": 3,
"last_message_at": "2026-10-01T09:30:00+00:00",
"created_at": "2026-09-30T18:02:00+00:00",
"updated_at": "2026-10-01T09:30:00+00:00",
"dashboard_url": "https://serverprism.com/tickets/1301"
}
],
"meta": { "current_page": 1, "per_page": 25, "total": 1, "last_page": 1 }
}
/api/v1/client/tickets/{id}
scope: tickets:read
The ticket plus its conversation, oldest message first. author is you or staff. Attachments are listed by name; download them from the dashboard.
Response (excerpt)
{
"data": {
"id": 1301,
"status": "replied",
"messages": [
{ "id": 9001, "author": "you", "author_name": "Fred Smith", "message": "TPS drops every evening", "attachments": [], "created_at": "2026-09-30T18:02:00+00:00" },
{ "id": 9007, "author": "staff", "author_name": "ServerPrism Support", "message": "We moved you to a quieter host...", "attachments": [], "created_at": "2026-10-01T09:30:00+00:00" }
]
}
}
/api/v1/client/tickets
scope: tickets:write
Opens a ticket. department is required and must be one of the departments shown on the dashboard's new-ticket form. priority is low (default), medium or high. service_id is optional and must be one of your services. One new ticket per 30 seconds per account. Returns 201 with the same body as Get ticket.
Request body
{
"subject": "Server lagging in the evening",
"message": "TPS drops to ~12 between 19:00 and 22:00 CET.",
"department": "Support",
"priority": "medium",
"service_id": 1234
}
/api/v1/client/tickets/{id}/messages
scope: tickets:write
Adds your reply to one of your tickets (up to 20,000 characters). Replying to a closed ticket reopens it, same as on the dashboard. Returns 201 with the new message.
Request body
{ "message": "Still happening tonight, see the timings report." }
Not available via the API
On purpose, the API cannot pay, cancel, upgrade or downgrade services, apply coupons, delete or restore backups, or delete files. Those actions are available in the dashboard, where you can see exactly what they will do before confirming.
Versioning
The v1 namespace is stable. Breaking changes will only happen in a new namespace (v2); we may add new fields to existing responses without warning, so write your client to ignore unknown keys.
Feature requests and bug reports: open a ticket and mention "API".