One call, and the server is live.
Provision real VPS instances straight from your prepaid balance. Every request bills your wholesale price — you resell to your own customers at any markup.
Introduction #
A small REST API over HTTPS. All requests and responses are JSON. Success is {"ok":true, …}; an error is {"ok":false,"error":{"code","message"}} with a matching HTTP status.
Authentication #
Send your secret API key as a bearer token on every request. Your admin issues it — treat it like a password.
Authorization: Bearer pk_live_xxxxxxxxxxxxxxxx
Quickstart #
Create your first server in three steps.
1 — List plans & OS images
curl -H "Authorization: Bearer pk_live_..." \ https://reseller.papiliohost.com/api/v1/catalog
2 — Create a server
curl -X POST https://reseller.papiliohost.com/api/v1/servers \
-H "Authorization: Bearer pk_live_..." \
-H "Content-Type: application/json" \
-d '{"dc":"0","plan":"plid-1","os":"os-1200","hostname":"cust1","billing":"monthly"}'
const res = await fetch("https://reseller.papiliohost.com/api/v1/servers", {
method: "POST",
headers: {
"Authorization": "Bearer pk_live_...",
"Content-Type": "application/json"
},
body: JSON.stringify({
dc: "0", plan: "plid-1", os: "os-1200",
hostname: "cust1", billing: "monthly"
})
});
const data = await res.json();
import requests
res = requests.post("https://reseller.papiliohost.com/api/v1/servers",
headers={"Authorization": "Bearer pk_live_..."},
json={"dc": "0", "plan": "plid-1", "os": "os-1200",
"hostname": "cust1", "billing": "monthly"})
print(res.json())
3 — Response · 201 Created
{
"ok": true,
"server": { "id": 12, "vpsid": "63", "ip": "94.183.218.226",
"ssh_user": "root", "ssh_pass": "s3cr3t", "billing": "monthly", "status": "active" },
"charged": 740000,
"balance": 4260000
}ssh_pass) is returned only in this create response — store it. It never appears in list or get.Endpoints #
Datacenters, plans and OS images available to you, each with your wholesale price (monthly & hourly).
Use the id fields here as the dc, plan and os values when creating a server.
{
"ok": true,
"catalog": [{
"dc": "0", "name": "Tehran",
"plans": [
{ "id": "plid-1", "name": "Skipper", "cpu": 1, "ram_mb": 1024,
"disk_gb": 15, "bandwidth_gb": 100, "monthly": 740000, "hourly": 1100 }
],
"os": [{ "id": "os-1200", "name": "almalinux-9.7-x86-64" }]
}]
}Your wallet balance and credit limit.
{ "ok": true, "balance": 4260000, "credit_limit": 0,
"currency": "toman", "status": "active" }List all your servers. The root password is never included here.
Retrieve a single server by its id.
{ "ok": true, "servers": [
{ "id": 12, "ip": "94.183.218.226", "plan": "plid-1",
"dc_name": "Tehran", "billing": "monthly",
"status": "active", "label": "cust1" }
]}Create a real server. Your wholesale price is charged up front; if provisioning fails it is refunded automatically.
Body parameters
| Field | Type | |
|---|---|---|
dc | string | REQUIRED — datacenter id from /catalog |
plan | string | REQUIRED — plan id (e.g. plid-1) |
os | string | REQUIRED — OS id (e.g. os-1200) |
billing | string | optional — monthly (default) or hourly |
hostname | string | optional — server hostname |
label | string | optional — your own tag (e.g. customer id) |
Idempotency-Key: <unique> header so a retried request returns the same server instead of creating a second one.{
"dc": "0",
"plan": "plid-1",
"os": "os-1200",
"hostname": "cust1",
"billing": "hourly",
"label": "customer-42"
}{ "ok": true,
"server": { "id": 12, "vpsid": "63",
"ip": "94.183.218.226", "ssh_user": "root",
"ssh_pass": "s3cr3t", "billing": "hourly",
"hourly_rate": 1100, "status": "active" },
"charged": 1100, "balance": 4258900 }Power control for a server.
| Field | Type | |
|---|---|---|
action | string | REQUIRED — start · stop · restart · poweroff |
{ "action": "stop" }{ "ok": true, "id": 12, "action": "stop" }Reinstall the OS from scratch. Returns a fresh root password. All data on the server is erased.
| Field | Type | |
|---|---|---|
os | string | REQUIRED — OS id from /catalog |
{ "os": "os-1200" }{ "ok": true, "id": 12, "os": "almalinux-9.7-x86-64",
"ssh_user": "root", "ssh_pass": "n3wp4ss" }Reset the root password. Returns the new one (store it — it is shown once).
{ "ok": true, "id": 12, "ssh_user": "root", "ssh_pass": "n3wp4ss" }Live status & usage — power state, CPU/RAM/disk percent, bandwidth used. Build your customer dashboard on this.
{ "ok": true, "id": 12, "stats": {
"online": true, "ip": "94.183.218.226",
"cpu": 1, "ram_mb": 1024, "disk_gb": 15,
"bandwidth_gb": 100, "bandwidth_used_gb": 12,
"cpu_pct": 8, "ram_pct": 34, "disk_pct": 21 } }Delete a server. For hourly servers the unused part of the current hour is refunded.
delete_failed: VPS Locked — wait, or stop it first, then delete.{ "ok": true, "id": 12 }White-label customer panel #
Give your customers a hosted, branded web panel where they self-serve: view their servers, power on/off, reinstall the OS, reset the root password, and watch live usage — all under your reseller name, with no code from you.
Flow: create a customer → assign one or more of your servers to them → hand them the panel link and their access code.
https://reseller.papiliohost.com/panelaccess codeCreate a customer. Returns a one-time access_code and the panel URL — give both to your customer.
Also: GET /customers (list, with server counts) · DELETE /customers/{id} (remove & unassign their servers).
| Field | Type | |
|---|---|---|
name | string | optional — a label for you |
{ "ok": true,
"customer": { "id": 1, "name": "Ali", "servers": 0, "status": "active" },
"access_code": "cust_9d24…0725",
"panel_url": "https://reseller.papiliohost.com/panel" }Assign a server to one of your customers (so it shows in their panel), or pass null to unassign.
{ "customer": 1 }{ "ok": true, "id": 12, "customer": 1 }Errors #
Every error is {"ok":false,"error":{"code","message"}}. Branch on error.code, not the message.
| Status | Code | Meaning |
|---|---|---|
| 401 | unauthorized | Invalid API key or inactive reseller |
| 402 | insufficient_balance | Not enough wallet balance |
| 403 | dc_forbidden · plan_forbidden · hourly_forbidden | No access to that datacenter / plan / hourly billing |
| 409 | dc_unavailable · plan_unavailable · limit_reached | Out of stock, or active-server limit reached |
| 400 | plan_not_found · os_not_found · bad_action | Invalid input |
| 429 | rate_limited | Too many requests (max 120/min) |
| 502 | provision_failed · delete_failed · action_failed | Panel operation failed (create is auto-refunded) |
Billing #
- Wholesale. Prices in
/catalogare what leaves your balance. Sell to your own customers at any price — the difference is your margin. - Monthly. Full price charged on create; active until the renewal date.
- Hourly. First hour prepaid on create, then each hour billed automatically. Out of balance → the server is suspended; top up and it resumes; unpaid past the grace period → deleted.
- Top up. Ask your admin (send
/chargein the bot).