REST API
Manage your servers and orders from your own tooling. Create a key on the billing page — it is shown once and stored only as a hash.
Authentication
Send your key as Authorization: Bearer YOUR_API_KEY (or as an
X-API-Key header). All responses are JSON.
curl -H "Authorization: Bearer bhk_your_key_here" \ /api/v1/servers
Keys are scoped to your account only. Rate limit: 60 requests per minute per key. A key never carries panel or payment-provider credentials.
Endpoints
| Method | Path | Description |
|---|---|---|
| GET | /api/v1/ping | Verify a key and return your account summary. |
| GET | /api/v1/plans | List plans with memory, disk, CPU and price. /packages is the same endpoint. |
| GET | /api/v1/orders | List your orders and their provisioning status. |
| POST | /api/v1/orders | Create an order in pending. Body: {"plan":"1gb","server_name":"My WhatsApp Bot","runtime":"nodejs"}. The price always comes from the plan. |
| GET | /api/v1/orders/{ref} | One order, e.g. BH1A2B3C4D. Returns 404 if it is not yours. |
| POST | /api/v1/orders/{ref}/pay | Start the M-Pesa STK push. Body: {"phone":"2547XXXXXXXX"}. Returns the checkout id. |
| GET | /api/v1/servers | List your servers with IP, port and limits. |
| GET | /api/v1/servers/{id} | One server. Returns 404 if it is not yours. |
Order lifecycle
An order moves through pending → paid → provisioning
→ active (failed if provisioning gives up). A server's own status is
mirrored from the panel: installing, starting, running,
offline or suspended. Read either through
/api/v1/orders/{ref}.
Example response
{
"data": [
{
"id": 12,
"name": "my-discord-bot",
"identifier": "a1b2c3d4",
"order_ref": "BH1A2B3C4D",
"package": "1 GB",
"memory_mb": 1024,
"disk_mb": 2048,
"cpu_percent": 100,
"ip": "62.171.140.132",
"port": 26061,
"status": "running",
"created_at": "2026-01-14 09:12:44"
}
],
"panel_url": "http://62.171.140.132"
}
Errors
| Status | Meaning |
|---|---|
401 | Missing, invalid or revoked API key. |
404 | The resource does not exist or is not yours. We never reveal another account's resources. |
409 | Conflict, e.g. paying an order that is already paid. |
422 | Validation failed. The response names the offending field. |
429 | Rate limit exceeded. Back off and retry. |
502 | The payment provider could not start the checkout. |
Payments
Checkout is a server-side M-Pesa STK push. Our backend polls the payment provider for the
status of the checkout and only releases a server once the status is completed.
There is no browser-visible payment callback, so a redirect is never proof of payment.