Table of contents

API

REST API v1 — Public reference for billing integrations and custom automation (WHMCS, Blesta, HostBill, and similar). Covers accounts, domains, apps, databases, cron jobs, and SSO.

Base URL: {APP_URL}/api/v1
Examples: https://panel.example.com/api/v1 · http://203.0.113.10:8443/api/v1
Authentication: Bearer token with scoped abilities
Rate limit: 60 requests/minute per authenticated user (default)
Headers: send Authorization: Bearer YOUR_TOKEN, Accept: application/json, and Content-Type: application/json on write requests
Not in this API: backups, restore, FTP, file manager, terminal, phpMyAdmin — use the MetroPanel UI.

Current: Use GET /auth/me to verify API credentials (for example WHMCS TestConnection). Do not use public GET /health for token checks — it only proves the panel is reachable. Optional per-token IP allowlists can restrict which client IPs may call the API.

Authenticated endpoints require a Bearer token, the matching ability (where listed), and a passing IP allowlist when configured (empty = allow any IP). List endpoints are paginated (current_page, data, per_page, total, …). Packages list returns { "data": [...] } (not paginated).

Full request and response details are in the sections below.

Method Endpoint Ability Description
GET /health public Public liveness (does not check API tokens)
GET /auth/me valid token Authenticated connection / credential check (WHMCS TestConnection)
GET /sso/login/{user_id} signed URL SSO redirect (throttle 30/min)
GET /packages packages:read List packages
GET /packages/{id} packages:read Show package
GET /accounts accounts:read List accounts (?username= exact filter)
POST /accounts accounts:write Create account
GET /accounts/check-username accounts:read Username availability (hosting + panel users)
GET /accounts/usage/bulk accounts:read Bulk resource usage (max 100 IDs)
GET /accounts/{id} accounts:read Show account (?include=apps,usage)
DELETE /accounts/{id} accounts:write Terminate account
PATCH /accounts/{id}/suspend accounts:write Suspend account
PATCH /accounts/{id}/unsuspend accounts:write Unsuspend account
PATCH /accounts/{id}/password accounts:write Change account password
PATCH /accounts/{id}/package accounts:write Change package
PATCH /accounts/{id}/resources accounts:write Update resource / feature limits
GET /accounts/{id}/usage accounts:read Resource usage
POST /accounts/{id}/login-link accounts:write SSO login URL (optional deep-link target)
GET /domains domains:read List domains
POST /domains domains:write Add domain
GET /domains/{id} domains:read Show domain
DELETE /domains/{id} domains:write Remove domain
POST /domains/{id}/ssl domains:write Install SSL
GET /app-templates apps:read List installable app templates
GET /apps apps:read List apps (paginated summary)
POST /apps apps:write Install app
GET /apps/{id} apps:read Show app
DELETE /apps/{id} apps:write Remove app
POST /apps/{id}/deploy-zip apps:write Deploy ZIP into PHP / Node / Static app
POST /apps/{id}/deploy-git apps:write Git pull+rebuild (Node git-sourced apps)
GET /databases databases:read List databases
POST /databases databases:write Create database
GET /databases/{id} databases:read Show database (db_password never returned)
DELETE /databases/{id} databases:write Remove database
PATCH /databases/{id}/password databases:write Reset DB password
POST /databases/{id}/allowed-ips databases:write Allow remote MySQL IP
DELETE /databases/{id}/allowed-ips/{ip} databases:write Revoke remote MySQL IP
GET /cron-jobs cron:read List cron jobs
POST /cron-jobs cron:write Create cron job
GET /cron-jobs/{id} cron:read Show cron job
PATCH /cron-jobs/{id} cron:write Update cron job
DELETE /cron-jobs/{id} cron:write Remove cron job

Async operations: Database create/remove, domain removal, app install, and account termination may complete asynchronously. Poll the resource or list endpoints if status is pending.

💡
Access scope
Results are limited to accounts visible to the token owner (admin sees all; reseller sees their accounts).

All API requests (except the public health check and the signed SSO login URL) require a Bearer token:

Authorization: Bearer YOUR_API_TOKEN Accept: application/json

Create an API token

  1. Sign in to MetroPanel as an admin or reseller
  2. Open Security → API Tokens
  3. Enter a name (optional IP allowlist), then create — the plain-text token is shown once; store it securely

Token presets (panel UI):

Preset What it can do Typical use
Read only View only — list accounts, packages, domains, apps, databases, and cron. Cannot create, change, or delete anything. Monitoring / dashboards, reporting or sync scripts that only pull status, safer testing without write risk
Provisioning Accounts, packages, domains, apps, databases (read + write) WHMCS / billing automation
Full access Same as Provisioning + cron management (cron:read / cron:write) Integrations that also manage cron jobs

Read only is for viewing data only — it cannot create, change, or delete anything. Prefer it for monitoring, reporting, or connection checks when you do not need writes.

For WHMCS module setup (username/password fields, Provisioning preset, and IP pinning), see WHMCS Module.

⚠️
Important
Treat the token like a password. Revoke it from Security → API Tokens if it is leaked. Do not share billing tokens with hosting end users.

Access scope: The token acts as the owning user. Admins see all accounts; resellers see accounts they manage. Abilities control which endpoints work; visibility controls which records are returned.

Per-token IP allowlist

You can optionally restrict a token so only listed client IPs may use it. This applies to all authenticated API calls, including GET /auth/me.

  • Empty — allow any client IP (default)
  • Set — up to 20 IPv4 / IPv6 / CIDR entries (comma, space, or semicolon separated)
  • Denied — HTTP 403 with This API token is not allowed from your IP address.

Configure the allowlist when creating the token under Security → API Tokens.

Examples: 203.0.113.10, 10.0.0.0/24, 2001:db8::/32.

💡
Billing automation
If you lock a token to IPs, include your billing server egress address(es). Otherwise connection tests and provisioning fail with 403 even with a valid token.

Most endpoints require a matching ability on the token. GET /auth/me only needs a valid token (any abilities).

Ability Endpoints
(any valid token) GET /auth/me
accounts:read GET /accounts, GET /accounts/check-username, GET /accounts/usage/bulk, GET /accounts/{id}, GET /accounts/{id}/usage
accounts:write Create, delete, suspend, unsuspend, password, package, resources, login-link
packages:read GET /packages, GET /packages/{id}
domains:read GET /domains, GET /domains/{id}
domains:write Create, delete, install SSL
apps:read GET /apps, GET /apps/{id}, GET /app-templates
apps:write Install, remove, ZIP/Git deploy
databases:read GET /databases, GET /databases/{id}
databases:write Create, delete, reset password, allowed IPs
cron:read GET /cron-jobs, GET /cron-jobs/{id}
cron:write Create, update, delete
* Full ability pass (wildcard)
💡
Note
Tokens with an empty abilities list are denied. Prefer tokens created in the panel UI so abilities are set correctly.

Missing ability response:

{ "message": "This API token does not have the required permission." }
  • Authenticated endpoints: 60 requests per minute per user (default), including GET /auth/me
  • Public GET /health: 60/min
  • SSO login URL: 30/min

When exceeded, the API returns 429 Too Many Requests.

GET /health (Public) — Check if panel is running

No authentication required. Use this only to verify the panel process is reachable. It does not validate API tokens — a revoked or fake Bearer token still returns 200. For credential checks (WHMCS TestConnection), call GET /auth/me instead.

Response

{ "status": "ok", "time": "2026-07-03T17:00:00+00:00" }

GET /auth/me (Auth) — Verify API token (WHMCS TestConnection)

Requires a valid Bearer token and a passing IP allowlist (if configured). No special ability is required. Invalid or revoked tokens return 401. Disallowed client IP returns 403.

Example

curl https://panel.example.com/api/v1/auth/me \ -H "Authorization: Bearer YOUR_TOKEN" \ -H "Accept: application/json"

Response

{ "status": "ok", "authenticated": true, "user": { "id": 1, "username": "admin", "role": "admin" }, "token": { "id": 12, "name": "WHMCS", "purpose": "billing", "preset": "full", "abilities": ["accounts:read", "accounts:write", "packages:read"] } }

All errors return appropriate HTTP status codes with a JSON body:

Status Meaning Example
401 Unauthenticated Missing or invalid token
403 Forbidden Missing token ability, policy denial, unauthorized package/app, or token IP allowlist denial
404 Not Found Resource does not exist or not visible to token
422 Validation / business rule error Invalid FQDN, cron metacharacters, quota exceeded
429 Too Many Requests API rate limit exceeded (default 60/min)
500 Server Error Unexpected server error

IP allowlist denial example:

{ "message": "This API token is not allowed from your IP address." }

Validation Error Response

{ "message": "The username has already been taken.", "errors": { "username": ["The username has already been taken."] } }

Typical account-create validation failures: username already used (hosting or panel user), invalid package, weak password. Contact email is not rejected for “already taken” when reused across end-user accounts.

General Error Response

{ "message": "This account is already on that package." }

Service Error Response (422)

Some endpoints (databases, cron) return a simple error object for business-rule failures:

{ "error": "Database limit reached (3)." }

For WHMCS provisioning, use the official module guide: WHMCS Module.

For Packages, Accounts, Domains, Apps, Databases, Cron, and related endpoints, see API Reference.