REST API
Scripts and other programs can manage a Reqad server over HTTPS: list, create, change and delete hosting accounts, databases and mailboxes, start Git deployments, and read what needs attention. They send JSON, get JSON back and use the same code as the panel and the command line, so an account created through the API is set up the same way as one created in the browser.
api=1 in /usr/local/reqad/etc/server-software.ini: the Settings > API access page then appears in the panel. Turn the API on there, or run reqad api on as root. While the API is off, every request is refused. Your tokens are kept. With api=0 (the default) the page, reqad api and every request are refused; Git deploy webhooks keep working.To manage the server from an AI assistant, you do not need the API: see AI assistants (MCP).
Access tokens
Each request carries a token in the Authorization header. The panel login is never used, so the API keeps working with two-factor authentication, passkeys and browser sessions as they are. Make tokens under Settings > API access > New token, after confirming your password, or with reqad api new. A token has:
| Setting | What it does |
|---|---|
| For | The whole server, or one hosting account. An account token sees and changes only what that account owns: its own databases, mailboxes and problems. It cannot create or delete accounts, turn mail on or off, or change the shell type. |
| Permissions | Every token can read. Create and change (write) and Delete (delete) are added one at a time, so a monitoring script can only read and a billing system can create accounts without being able to delete them. |
| Expires after | 30 days, 90 days (the default), a year, or never. |
| Allowed from | Optional: addresses or networks the token works from, e.g. 203.0.113.7, 198.51.100.0/24. Requests from anywhere else are refused. |
The token is shown only once, when you make it. The server keeps a fingerprint of the token, not the token itself, so it cannot show it again. If you lose a token, revoke it and make a new one. Revoke takes effect at once.
First request
TOKEN=rqd_... # the token from Settings > API access curl -H "Authorization: Bearer $TOKEN" https://server.example.com:2087/api/v1/
The reply describes the server and your token, and lists every endpoint. Every reply has the same shape, the same as reqad ... --json on the command line:
{
"ok": true,
"message": "Account bob successfully created.",
"warnings": [],
"error": "",
"data": { ... }
}When ok is false, error says why. A change that went through but needs attention, for example a certificate that could not be issued yet, comes back with ok: true and a note in warnings.
Endpoints
All paths start with https://<your server>:2087/api/v1. Send request bodies as JSON or as form fields.
| Request | Permission | What it does |
|---|---|---|
GET / | read | This server, your token and the list of endpoints. |
GET /server | read, server | The server: OS, Reqad version, uptime, load, memory, disks, web server, PHP versions, number of accounts, mail queue size and the Needs attention counts. |
GET /services | read, server | The services and timers of the Services page, each with its state, whether it starts at boot, and since when it runs. |
POST /services/{name}/restart | write, server | Restart one of those services. If it does not start again, the answer has its last journal lines. |
GET /accounts | read | Hosting accounts. |
POST /accounts | write, server | Create an account. Body: user, domain, password, quota (MB), php, shell (full, jailed or none), and dns, letsencrypt, email, www as true/false. |
GET /accounts/{user} | read | One account: PHP version, shell, mailboxes, databases and limits. |
PATCH /accounts/{user} | write | Change password or php ("8.3", or "off"). With a server token you can also change email (true/false) and shell. |
DELETE /accounts/{user} | delete, server | Delete an account with its files, mail and databases. |
GET /databases | read | MySQL/MariaDB databases with their owner, size and users. ?account=bob shows one account's. |
POST /databases | write | Create <account>_<name> and its user. Body: account, name, dbuser (default: the name), password. |
DELETE /databases/{name} | delete | Drop a database, and its users that have no other database. |
POST /database-users/{user}/password | write | Set a database user's password. Body: password. |
GET /mailboxes | read | Mailboxes. ?domain=example.com shows one domain's. |
POST /mailboxes | write | Create a mailbox. Body: email, password. |
PATCH /mailboxes/{email} | write | Change password, or block or allow login with enabled (true/false). Mail is still delivered while login is blocked. |
DELETE /mailboxes/{email} | delete | Delete a mailbox and its mail. |
GET /mail-queue | read, server | The outgoing mail queue: total, frozen, the senders and recipient domains with the most messages, and the oldest messages with their subjects. ?filter=frozen, ?search= (sender or recipient), ?limit= (default 50). |
POST /mail-queue/{id}/deliver | write, server | Try to deliver one queued message now; the answer has what the mail server said. |
DELETE /mail-queue/{id} | delete, server | Remove a message from the queue without delivering it. |
GET /logs | read | The logs you can read: a domain's web requests and errors (site) and PHP errors (php), and with a server token the web server, mail (mail, mail-reject, mail-panic), IMAP/POP3, firewall, SSH, cron, system and panel logs. |
GET /logs/{name} | read | The last lines of a log. ?lines= (default 100, at most 1000), ?grep= only lines containing that text, ?domain= for site and php. A token for one account reads only its own domains' site and PHP logs. |
GET /wordpress | read | WordPress sites with the version the last check saw. ?account=bob shows one account's. |
GET /wordpress/{site} | read | One site (its id, domain or account) read live: WordPress version and whether it is the latest, core updates, and every plugin and theme with its version and available update. ?refresh=1 asks wordpress.org again first. |
POST /wordpress/{site}/update | write | Update what: core, plugins or themes; items names plugins or themes (default: all with an update). The site's database is saved to ~/wp-backups/ first (compressed). |
POST /wordpress/{site}/plugins/{plugin}/activate, /deactivate | write | Turn a plugin on or off. |
POST /wordpress/{site}/purge-cache | write | Empty the site's caches: nginx page cache, OPcache, the object cache, cache plugins (WP Rocket, LiteSpeed, W3 Total Cache, WP Super Cache and others) and Elementor's CSS. Updates and plugin changes do this on their own. |
GET /wordpress/{site}/verify | read | Compare core and plugin files with the wordpress.org checksums. |
GET /deployments | read | Git deployments. ?account=bob shows one account's. |
GET /deployments/{id} | read | One deployment (its id or domain) with the releases on disk and the latest runs. |
POST /deployments/{id}/deploy | write | Deploy the branch now, e.g. from CI. Returns the run id. |
POST /deployments/{id}/rollback | write | Switch back to an earlier release. Body: release (default: the one before the current). |
GET /deploy-runs/{run} | read | A run's status and output; ?offset= returns only what was added since. |
GET /apps | read | Node.js and Python apps with their state. ?account=bob shows one account's. |
GET /apps/{id} | read | One app (its id or domain): settings, state, memory, restarts. |
POST /apps/{id}/start, /stop, /restart | write | Start, stop or restart an app. |
GET /apps/{id}/logs | read | What the app printed lately; ?lines= (default 200). |
GET /health | read | What needs attention, most serious first. ?account=bob shows one account's problems, ?account=- the server's own. ?all=1 includes hidden problems. |
GET /health/checks | read | The checks that run. |
POST /health/run | write, server | Run the checks now. This takes a few seconds. |
POST /health/dismiss | write | Hide a problem. Body: id, and days (default 7) or forever: true. |
POST /health/restore | write | Show a hidden problem again. Body: id. |
server means a token for the whole server is required. A token for one account gets 403.
Passwords: when you create an account, database or mailbox, or set a database user's password, and leave password out, the server generates a strong password and returns it once in data.password.
Examples
API=https://server.example.com:2087/api/v1
AUTH="Authorization: Bearer $TOKEN"
# create an account with a generated password, PHP 8.3 and a certificate
curl -H "$AUTH" -d '{"user":"bob","domain":"bob.example","php":"8.3","letsencrypt":true}' $API/accounts
# a database for it
curl -H "$AUTH" -d '{"account":"bob","name":"wp"}' $API/databases
# a mailbox, then block its login
curl -H "$AUTH" -d '{"email":"info@bob.example"}' $API/mailboxes
curl -H "$AUTH" -X PATCH -d '{"enabled":false}' $API/mailboxes/info@bob.example
# anything critical? (for monitoring)
curl -s -H "$AUTH" $API/health | jq '.data.counts.critical'Status codes
| Code | Meaning |
|---|---|
200 / 201 | Done (201: something was created). |
400 | The request was understood, but the change was refused. For example, the name is taken or the password is too short. error says why. |
401 | No token, a wrong token, or one that was revoked or has expired. |
403 | The token is valid but may not do this: a missing permission, another account's resource, an address not on its list. Also returned while the API is off. |
404 / 405 | No such resource or endpoint, or the wrong method for it. |
409 | The feature is turned off on this server (e.g. email). |
429 | Too many requests, or too many wrong tokens, from your address. See Retry-After. |
Security
- A wrong token counts as a failed login. After 5, the address is locked out of the API and the panel login for 15 minutes; after more, the firewall blocks it, as for the login page. A revoked or expired token is refused without counting, so a forgotten script does not get your own address blocked.
- The API accepts tokens only, never browser cookies. A web page you visit while logged in to the panel cannot use your session to call the API.
- Each address may make about 120 requests a minute.
- Settings > API access shows the latest calls (kept for 30 days) and when and from where each token was last used. The security log records tokens being made and revoked, wrong tokens, and a token used from a new address.
- When the panel's IP restriction is on (Settings > Security), port 2087 answers only the listed addresses. Add the addresses your scripts call from.
- Give each program its own token with the fewest permissions it needs. Use an account token when a program works for one customer.
On the command line
reqad api status # on or off, the address, active tokens reqad api on # or: off reqad api new monitoring # read-only, expires in 90 days reqad api new billing --write --days=365 --ip=203.0.113.7 reqad api new bob-deploy --account=bob --write reqad api tokens # --all also lists revoked tokens reqad api revoke billing reqad api log --lines=50
See Command line (CLI) for every option.
Need a hand? Create a free account or contact us.