HF PanelDocsv1.0.0

API: MySQL and PostgreSQL

Create and drop MySQL and PostgreSQL databases, manage MySQL users and their privileges through the token API.

These endpoints manage one hosting account's MySQL and PostgreSQL databases, like the MySQL databases and PostgreSQL databases screens in Control Panel, with the same name rules, package limits and activity log. MongoDB has its own endpoints.

bash
A=https://api.yourdomain.com:2087/v1
H="Authorization: Bearer hf_xxx"

The path names the account (/v1/accounts/{username}/mysql/…, /v1/accounts/{username}/postgres/…); the rules are those of every per-account endpoint.

Names. Database and user names always start with the account's username and _: sarahbakes_shop. You can send them in full or without that part (shop); the part after it is 1–15 lower-case letters, numbers or _. MySQL and PostgreSQL databases count together towards the package's database limit.

MySQL: list

GET /v1/accounts/{username}/mysql

json
{
    "ok": true,
    "data": {
        "host": "localhost",
        "limit": 5,
        "used": 2,
        "databases": [
            {
                "name": "sarahbakes_shop",
                "created_at": "2026-05-02 09:40:00"
            }
        ],
        "users": [
            {
                "name": "sarahbakes_shop",
                "created_at": "2026-05-02 09:40:00"
            }
        ]
    }
}

limit 0 means no limit.

MySQL: create a database

POST /v1/accounts/{username}/mysql/databases. 201.

bash
curl -s -X POST -H "$H" -H "Content-Type: application/json" -d '{"name":"shop","user":true}' \
  $A/accounts/sarahbakes/mysql/databases
Field What it does
name required
user true also makes a user of the same name with all privileges on it, and a random password
json
{
    "ok": true,
    "data": {
        "database": "sarahbakes_shop",
        "user": "sarahbakes_shop",
        "password": "Xq7…",
        "host": "localhost"
    }
}

The password is shown only in this answer. Without user the answer has only database.

MySQL: users and privileges

bash
# a user (password empty = a random one, returned once)
curl -s -X POST -H "$H" -H "Content-Type: application/json" -d '{"name":"app"}' $A/accounts/sarahbakes/mysql/users
# let it use a database: every privilege, or a list
curl -s -X POST -H "$H" -H "Content-Type: application/json" -d '{"user":"app","privileges":["SELECT","INSERT","UPDATE","DELETE"]}' \
  $A/accounts/sarahbakes/mysql/databases/shop/grant
# take its rights away
curl -s -X POST -H "$H" -H "Content-Type: application/json" -d '{"user":"app"}' $A/accounts/sarahbakes/mysql/databases/shop/revoke
# a new password, and delete the user
curl -s -X POST -H "$H" -H "Content-Type: application/json" -d '{}' $A/accounts/sarahbakes/mysql/users/app/password
curl -s -X DELETE -H "$H" $A/accounts/sarahbakes/mysql/users/app

privileges left out (or ["ALL"]) gives every privilege. The names are those of the MySQL databases screen, written in capitals with _ for spaces (CREATE_TEMPORARY_TABLES); an unknown one answers 422 "Unknown privilege."

MySQL: drop a database

DELETE /v1/accounts/{username}/mysql/databases/{database} drops the database and everything in it.

PostgreSQL

bash
curl -s -H "$H" $A/accounts/sarahbakes/postgres
curl -s -X POST -H "$H" -H "Content-Type: application/json" -d '{"name":"app"}' $A/accounts/sarahbakes/postgres
curl -s -X POST -H "$H" -H "Content-Type: application/json" -d '{}' $A/accounts/sarahbakes/postgres/app/password
curl -s -X DELETE -H "$H" $A/accounts/sarahbakes/postgres/app

Creating a PostgreSQL database also makes its owner user, with the same name and a random password (201):

json
{
    "ok": true,
    "data": {
        "database": "sarahbakes_app",
        "user": "sarahbakes_app",
        "password": "pR3…",
        "host": "127.0.0.1",
        "port": 5432
    }
}

…/password sets a new password for the owner user (password empty = a random one) and returns it.

Dumps and slow queries

These run the Database tools screen's own actions.

bash
curl -s -H "$H" $A/accounts/sarahbakes/db-tools/dumps
curl -s -X POST -H "$H" -H "Content-Type: application/json" -d '{"database":"sarahbakes_shop"}' $A/accounts/sarahbakes/db-tools/dumps
curl -s -X POST -H "$H" -H "Content-Type: application/json" -d '{}' \
  $A/accounts/sarahbakes/db-tools/dumps/sarahbakes_shop-20261026-031500.my.sql.gz/restore
curl -s -H "$H" "$A/accounts/sarahbakes/db-tools/slow-queries?database=sarahbakes_shop"
Endpoint What it does
GET …/db-tools/dumps dumps (name, engine, database, size in bytes, created), schedules and schedule_limit (0 = unlimited)
POST …/db-tools/dumps makes a compressed, consistent dump of database now (201, the dump); engine only when a MySQL and a PostgreSQL database share the name
POST …/db-tools/dumps/{name}/restore loads the dump into its own database, or into database (another database of the same kind)
GET …/db-tools/slow-queries the slowest queries (normalised, with calls, avg_ms, max_ms, total_ms, rows_examined, last_seen); ?database= for one database