byp

API reference

Same engine as the dashboard. Order machines, read credentials, run power actions and watch your credit from any script that speaks HTTP.

Base URL

/api/index.php

With mod_rewrite enabled you can also call /api/v1/products.

Authentication

Authorization: Bearer byp_live_...

Create a key and give it the scopes the script needs.

Versions

Live: v1

The version sits in the path. Inside a version fields are added, never removed.

Response shape

Every answer uses the same envelope, so a client can be written once.

{
  "ok": true,
  "data": { },
  "meta": { "count": 6 }
}

{
  "ok": false,
  "error": {
    "code": "missing_scope",
    "message": "The key is missing the scope orders:write.",
    "details": { "required": "orders:write" }
  }
}

Scopes

account:readRead profile and balance
products:readRead the product catalogue
orders:readRead orders
orders:writePlace and cancel orders
servers:readRead servers and credentials
servers:writeRun power and rebuild actions
billing:readRead transactions and top ups
billing:writeCreate top up requests

Endpoints

V1

Account

GET /v1/account account:read Profile of the current account
GET /v1/account/balance account:read Prepaid credit of the current account
GET /v1/account/keys account:read API keys of the current account

Admin

GET /v1/admin/queue orders:read Orders waiting for delivery
GET /v1/admin/stats account:read Operational counters
POST /v1/admin/tick orders:write Run the delivery queue by hand

Billing

GET /v1/billing/transactions billing:read Credit movements of the current account
GET /v1/billing/topups billing:read Top up requests of the current account
POST /v1/billing/topups billing:write Request new prepaid credit
POST /v1/billing/topups/{reference}/settle billing:write Staff endpoint that books an incoming payment

Products

GET /v1/products public Catalogue of virtual and root servers
GET /v1/products/{slug} public Single product with specs and stock

Orders

GET /v1/orders orders:read Orders of the current account
POST /v1/orders orders:write Buy a server with prepaid credit
GET /v1/orders/{key} orders:read Single order including the delivered server
POST /v1/orders/{key}/cancel orders:write Cancel an order that is still in setup
POST /v1/orders/{key}/deliver orders:write Staff shortcut that delivers an order right away

Servers

GET /v1/servers servers:read Servers of the current account
GET /v1/servers/{id} servers:read Single server with product details
GET /v1/servers/{id}/credentials servers:read Root login for a delivered server
POST /v1/servers/{id}/actions servers:write Start, stop, reboot or rebuild a server
GET /v1/servers/{id}/events servers:read Recent activity of a server

Status

GET /v1/status public Service heartbeat

Meta

GET /v1/meta/routes public List every endpoint of this version
GET /v1/meta/scopes public Available API key scopes
GET /v1/meta/os-templates public Installable operating systems
GET /v1/meta/drivers account:read Registered provisioning drivers

Try a call

Runs against this installation. GET requests work with your browser session, other clients need a key.

Nothing sent yet.

Order a machine

curl -X POST /api/index.php/v1/orders \
  -H "Authorization: Bearer $KEY" \
  -H "Content-Type: application/json" \
  -d '{"product":"vps-pro","months":3,"os_template":"ubuntu-24-04"}'

Reboot a server

curl -X POST /api/index.php/v1/servers/12/actions \
  -H "Authorization: Bearer $KEY" \
  -d '{"action":"reboot"}'

Adding your own endpoints

The API loads every folder under api/modules as a version and every file inside it as a module. A module is one file that returns a function. Drop it in, reload, done. Nothing else has to be touched.

<?php

return function (ApiRouter $router, array $meta) {
    $router->get('/backups', function (ApiRequest $req, array $params, ApiContext $ctx) {
        return ApiResponse::collection(backups_for($ctx->userId()));
    }, ['scope' => 'servers:read', 'summary' => 'List backups']);
};

A new major version is a new folder, for example api/modules/v2. Both versions then answer at the same time, so clients can move over when they are ready. Provisioning backends work the same way: a file in app/drivers registers itself and becomes selectable per product.