Developer reference
REST API reference
20 endpoints under /api/v1 — clients, orders, invoices, services, products, nodes, platform status and an OpenAI-compatible AI Router. Every sample below is generated from the endpoint specification, so the method, parameters and body always match what the API accepts.
New to the API? Start with the OpenAI-compatible quickstart. Tokens are issued by our staff — send us the scopes you need with a support request.
Base URL
All endpoints are served from https://hostingswift.com/api/v1. Paths in this reference are relative to that base. JSON in, JSON out, UTF-8.
Authentication
- API token — Authorization: Bearer hs_… — a token created in the client panel, sent on every request.
- AI key — Authorization: Bearer hs-sk-… — an AI Router key with the `chat` scope, OpenAI-compatible auth.
- None (public) — No credentials required. Read-only, cached, and never includes customer data.
Tokens carry scopes such as services:read or invoices:write. A request that needs a scope the token does not hold gets 403 insufficient_scope. Accounts with an admin role bypass scope checks. Tokens are stored as hashes — we can never show one again, so keep it in a secret manager.
curl https://hostingswift.com/api/v1/status \
-H "Authorization: Bearer $HOSTINGSWIFT_TOKEN"Errors
Failures use one JSON shape, and validation failures add an issues array naming each field.
{
"error": {
"message": "Token missing required scope(s): invoices:write",
"code": "insufficient_scope"
}
}400Malformed request — usually an invalid JSON body (`invalid_json`).401Missing, invalid, revoked or expired token.403Token lacks a required scope (`insufficient_scope`), account inactive, or an admin-only change.404The record does not exist (`not_found`).409Conflict — duplicate email or slug, or the service is already terminated.413Body over the size limit (AI Router: 2 MB).422Validation failed (`validation_error`) — `error.issues` lists each field.429Rate limited or AI budget exhausted.503Authentication backend or rate limiter unavailable.
Catalogue
What you can sell or order. The catalogue endpoint is public; products are token-protected.
Public product catalogue with prices, locations and endpoints — safe for AI agents to crawl.
- Authentication
- None (public)
- Required scopes
- None (any valid token, or public)
Request
curl -X GET "https://hostingswift.com/api/v1/ai/catalog"Response · 200
{
"provider": "HostingSwift",
"url": "https://hostingswift.com",
"currency": "USD",
"locations": ["…"],
"services": [
{ "slug": "vps", "name": "VPS hosting", "products": [ { "slug": "…", "prices": [] } ] }
]
}List products, optionally filtered by group or service type.
- Authentication
- API token
- Required scopes
products:read
| Parameter | Type | Required | Description |
|---|---|---|---|
groupId | string | No | Only products in this product group. |
serviceType | string | No | Only products of this service type. |
Request
curl -X GET "https://hostingswift.com/api/v1/products" \
-H "Authorization: Bearer $HOSTINGSWIFT_TOKEN"Response · 200
{ "data": [ { "id": "prod_…", "slug": "vps-2gb", "name": "VPS 2 GB", "groupId": "grp_…", "serviceType": "VPS" } ] }Create a product in an existing product group.
- Authentication
- API token
- Required scopes
products:write
| Parameter | Type | Required | Description |
|---|---|---|---|
slug | string | Yes | Lowercase kebab-case, unique across products. |
name | string | Yes | Display name. |
groupId | string | Yes | Existing product group id. |
serviceType | string | Yes | Service type key, e.g. VPS. |
tagline | string | No | One-line summary. |
description | string | No | Long description (markdown). |
isFree | boolean | No | Free-tier product. |
visible | boolean | No | Listed on the public site. |
featured | boolean | No | Highlighted on the storefront. |
provisioningKey | string | No | Provisioning recipe key. |
cpuCores | integer | No | vCPU count. |
ramMb | integer | No | Memory in MB. |
diskGb | integer | No | Disk in GB. |
bandwidthGb | integer | No | Monthly transfer in GB. |
Errors: 404 — Product group not found. 409 — A product with that slug already exists. 422 — Validation failed — see `error.issues`.
Request
curl -X POST "https://hostingswift.com/api/v1/products" \
-H "Authorization: Bearer $HOSTINGSWIFT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"slug": "vps-2gb",
"name": "VPS 2 GB",
"groupId": "grp_vps",
"serviceType": "VPS",
"ramMb": 2048,
"diskGb": 40
}'Response · 201
{ "data": { "id": "prod_…", "slug": "vps-2gb", "name": "VPS 2 GB" } }Orders and invoices
Place an order for a client and issue the invoice. Pricing is always resolved server-side.
List orders.
- Authentication
- API token
- Required scopes
orders:read
| Parameter | Type | Required | Description |
|---|---|---|---|
status | string | No | Filter by order status. |
userId | string | No | Only orders for this client. |
limit | integer | No | Page size, 1–200. Default 50. |
offset | integer | No | Rows to skip. Default 0. |
Request
curl -X GET "https://hostingswift.com/api/v1/orders" \
-H "Authorization: Bearer $HOSTINGSWIFT_TOKEN"Response · 200
{ "data": [ { "id": "ord_…", "status": "PENDING", "userId": "usr_…", "total": "12.00" } ], "meta": { "total": 128, "limit": 50, "offset": 0 } }Create an order (and, by default, its invoice) for a client.
- Authentication
- API token
- Required scopes
orders:write
| Parameter | Type | Required | Description |
|---|---|---|---|
userId | string | Yes | Client the order belongs to. |
items | array | Yes | At least one item: `{ productId, quantity?, cycle? }`. Cycle is FREE, MONTHLY, QUARTERLY, SEMIANNUAL, ANNUAL or BIENNIAL. |
currency | string | No | ISO-4217 code, 3 letters. |
promoCode | string | No | Promotion code to apply. |
ipAddress | string | No | IP recorded against the order (fraud checks). |
createInvoice | boolean | No | Issue the invoice immediately. |
Errors: 404 — User not found. 422 — Validation failed or the product cannot be priced.
Request
curl -X POST "https://hostingswift.com/api/v1/orders" \
-H "Authorization: Bearer $HOSTINGSWIFT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"userId": "usr_abc123",
"items": [
{
"productId": "prod_vps2gb",
"quantity": 1,
"cycle": "MONTHLY"
}
],
"createInvoice": true
}'Response · 201
{ "data": { "order": { "id": "ord_…" }, "invoice": { "id": "inv_…", "number": "HS-1042" } } }List invoices with their line items and client.
- Authentication
- API token
- Required scopes
invoices:read
| Parameter | Type | Required | Description |
|---|---|---|---|
status | string | No | Filter by invoice status. |
userId | string | No | Only invoices for this client. |
limit | integer | No | Page size, 1–200. Default 50. |
offset | integer | No | Rows to skip. Default 0. |
Request
curl -X GET "https://hostingswift.com/api/v1/invoices" \
-H "Authorization: Bearer $HOSTINGSWIFT_TOKEN"Response · 200
{ "data": [ { "id": "inv_…", "number": "HS-1042", "status": "UNPAID", "total": "12.00", "items": [], "user": { "email": "…" } } ], "meta": { "total": 128, "limit": 50, "offset": 0 } }Create a standalone invoice (manual charges) for a client.
- Authentication
- API token
- Required scopes
invoices:write
| Parameter | Type | Required | Description |
|---|---|---|---|
userId | string | Yes | Client to invoice. |
items | array | Yes | At least one line: `{ unitPrice, description?, productName?, cycle?, quantity? }`. `unitPrice` is required and non-negative. |
dueInDays | integer | No | Positive number of days until due. |
Errors: 404 — User not found. 422 — Validation failed — see `error.issues`.
Request
curl -X POST "https://hostingswift.com/api/v1/invoices" \
-H "Authorization: Bearer $HOSTINGSWIFT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"userId": "usr_abc123",
"items": [
{
"description": "Migration assistance",
"unitPrice": 75,
"quantity": 1
}
],
"dueInDays": 14
}'Response · 201
{ "data": { "id": "inv_…", "number": "HS-1043", "status": "UNPAID" } }Mark an invoice paid (manual payment reconciliation). Records an `invoice.paid` audit event.
- Authentication
- API token
- Required scopes
invoices:write
| Parameter | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Invoice id — a QUERY parameter on this endpoint, not a path segment. |
gateway | string | No | Payment gateway that took the money. Defaults to `manual`. |
transactionId | string | No | Gateway transaction reference, or null. |
amount | number | No | Amount received. Defaults to the invoice total. |
Errors: 400 — Missing query parameter `id`. 404 — Invoice not found.
Request
curl -X PATCH "https://hostingswift.com/api/v1/invoices?id=inv_abc123" \
-H "Authorization: Bearer $HOSTINGSWIFT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"gateway": "manual",
"transactionId": "BANK-9931",
"amount": "12.00"
}'Response · 200
{ "data": { "id": "inv_…", "status": "PAID" } }Clients
Create and maintain client accounts. Only an admin may change a role.
List clients, with free-text search across email, name and company.
- Authentication
- API token
- Required scopes
clients:read
| Parameter | Type | Required | Description |
|---|---|---|---|
q | string | No | Case-insensitive search across email, first/last name and company. |
limit | integer | No | Page size, 1–200. Default 50. |
offset | integer | No | Rows to skip. Default 0. |
Request
curl -X GET "https://hostingswift.com/api/v1/clients" \
-H "Authorization: Bearer $HOSTINGSWIFT_TOKEN"Response · 200
{ "data": [ { "id": "usr_…", "email": "…", "firstName": "…", "role": "CLIENT", "status": "active" } ], "meta": { "total": 128, "limit": 50, "offset": 0 } }Create a client account.
- Authentication
- API token
- Required scopes
clients:write
| Parameter | Type | Required | Description |
|---|---|---|---|
email | string | Yes | Must be a valid email and not already taken. |
firstName | string | No | Given name. |
lastName | string | No | Family name. |
company | string | No | Company name. |
phone | string | No | Phone number. |
country | string | No | Two-letter code. Defaults to US. |
role | string | No | CLIENT, STAFF or ADMIN. Defaults to CLIENT. |
status | string | No | active, suspended or closed. Defaults to active. |
Errors: 409 — A user with that email already exists. 422 — Validation failed — see `error.issues`.
Request
curl -X POST "https://hostingswift.com/api/v1/clients" \
-H "Authorization: Bearer $HOSTINGSWIFT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"email": "[email protected]",
"firstName": "Ada",
"lastName": "Lovelace",
"country": "GB"
}'Response · 201
{ "data": { "id": "usr_…", "email": "…", "role": "CLIENT", "status": "active" } }Fetch one client with counts of their related records.
- Authentication
- API token
- Required scopes
clients:read
| Parameter | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Client id (path parameter). |
Errors: 404 — Client not found.
Request
curl -X GET "https://hostingswift.com/api/v1/clients/usr_abc123" \
-H "Authorization: Bearer $HOSTINGSWIFT_TOKEN"Response · 200
{ "data": { "id": "usr_…", "email": "…", "counts": { "services": 2, "invoices": 7 } } }Update a client. Sending `role` or `staffRole` requires an admin.
- Authentication
- API token
- Required scopes
clients:write
| Parameter | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Client id (path parameter). |
firstName | string | No | Given name, or null to clear. |
lastName | string | No | Family name, or null to clear. |
company | string | No | Company, or null to clear. |
phone | string | No | Phone, or null to clear. |
country | string | No | Two-letter code. |
role | string | No | CLIENT, STAFF or ADMIN — admin only. |
status | string | No | active, suspended or closed. |
staffRole | string | No | Staff role key, or null — admin only. |
Errors: 403 — Only an admin may change roles. 404 — Client not found. 422 — Validation failed.
Request
curl -X PATCH "https://hostingswift.com/api/v1/clients/usr_abc123" \
-H "Authorization: Bearer $HOSTINGSWIFT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"company": "Analytical Engines Ltd",
"country": "GB"
}'Response · 200
{ "data": { "id": "usr_…", "email": "…", "status": "suspended" } }Services
Read the services you run and trigger lifecycle actions. Actions are queued as jobs.
List services with their client and node.
- Authentication
- API token
- Required scopes
services:read
| Parameter | Type | Required | Description |
|---|---|---|---|
status | string | No | Filter by service status, e.g. ACTIVE. |
userId | string | No | Only services for this client. |
nodeId | string | No | Only services on this node. |
limit | integer | No | Page size, 1–200. Default 50. |
offset | integer | No | Rows to skip. Default 0. |
Request
curl -X GET "https://hostingswift.com/api/v1/services" \
-H "Authorization: Bearer $HOSTINGSWIFT_TOKEN"Response · 200
{ "data": [ { "id": "svc_…", "status": "ACTIVE", "node": { "name": "…" }, "user": { "email": "…" } } ], "meta": { "total": 128, "limit": 50, "offset": 0 } }Queue a lifecycle action on a service: suspend, unsuspend, terminate or reboot.
- Authentication
- API token
- Required scopes
services:write
| Parameter | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Service id (path parameter). |
action | string | Yes | suspend, unsuspend, terminate or reboot. |
Errors: 404 — Service not found. 409 — Service is already terminated. 422 — Validation failed.
Request
curl -X POST "https://hostingswift.com/api/v1/services/svc_abc123/actions" \
-H "Authorization: Bearer $HOSTINGSWIFT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"action": "reboot"
}'Response · 202
{ "data": { "serviceId": "svc_…", "action": "reboot", "jobId": "job_…" } }Infrastructure
Nodes and platform health. Node API tokens are never returned.
List nodes with capacity and counts of services and IPs.
- Authentication
- API token
- Required scopes
nodes:read
Request
curl -X GET "https://hostingswift.com/api/v1/nodes" \
-H "Authorization: Bearer $HOSTINGSWIFT_TOKEN"Response · 200
{ "data": [ { "id": "nod_…", "name": "…", "hypervisor": "…", "status": "ONLINE", "serviceCount": 12, "ipCount": 40 } ] }Platform health: database and Redis reachability plus aggregate counts.
- Authentication
- API token
- Required scopes
- None (any valid token, or public)
Request
curl -X GET "https://hostingswift.com/api/v1/status" \
-H "Authorization: Bearer $HOSTINGSWIFT_TOKEN"Response · 200
{
"data": {
"status": "ok",
"time": "2026-01-01T00:00:00.000Z",
"checks": { "db": { "ok": true }, "redis": { "ok": true } },
"counts": { "services": { "ACTIVE": 120 }, "nodes": { "ONLINE": 9 }, "jobs": { "DONE": 40 } }
}
}AI Router
OpenAI-compatible alias on the same base path, so the OpenAI SDKs work by changing `baseURL`.
Create a chat completion. Request and response are OpenAI-compatible; `stream: true` returns SSE.
- Authentication
- AI key
- Required scopes
chat
| Parameter | Type | Required | Description |
|---|---|---|---|
model | string | Yes | A model id from GET /models. |
messages | array | Yes | 1–200 messages with a role of system, user, assistant or tool. |
stream | boolean | No | Stream the reply as server-sent events. |
max_tokens | integer | No | 1–8192. |
temperature | number | No | Sampling temperature. |
Errors: 401 — Invalid or revoked AI key. 413 — Payload over 2 MB. 422 — Invalid request (message includes which field). 429 — Rate limited or budget exhausted.
Request
curl -X POST "https://hostingswift.com/api/v1/chat/completions" \
-H "Authorization: Bearer $HOSTINGSWIFT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"model": "deepseek-chat",
"messages": [
{
"role": "user",
"content": "Explain DNS TTLs in two sentences."
}
]
}'Response · 200
{ "id": "chatcmpl-…", "object": "chat.completion", "model": "…", "choices": [ { "index": 0, "message": { "role": "assistant", "content": "…" }, "finish_reason": "stop" } ], "usage": { "prompt_tokens": 12, "completion_tokens": 40, "total_tokens": 52 } }List chat models enabled for this key, with context length and prices.
- Authentication
- AI key
- Required scopes
chat
Request
curl -X GET "https://hostingswift.com/api/v1/models" \
-H "Authorization: Bearer $HOSTINGSWIFT_TOKEN"Response · 200
{ "object": "list", "data": [ { "id": "deepseek-chat", "object": "model", "owned_by": "hostingswift", "context_length": 64000, "free": false } ] }Cloudflare automation
One endpoint that drives DNS, SSL, WAF, DDoS and cache through our cfk tooling — one shared rate budget (10% of Cloudflare's) and one audit trail. Mutating actions require `confirm: true`.
Discovery: what this key may do — its scopes and the read/write action list.
- Authentication
- AI key
- Required scopes
dns
Errors: 401 — Missing, invalid or revoked key. 403 — Key lacks the `dns` scope, or is not staff and not delegated.
Request
curl -X GET "https://hostingswift.com/api/v1/cloudflare" \
-H "Authorization: Bearer $HOSTINGSWIFT_TOKEN"Response · 200
{
"ok": true,
"service": "HostingSwift Cloudflare automation API",
"version": 1,
"keyId": "key_…",
"scopes": ["chat", "dns"],
"actions": {
"read": ["zone.list", "zone.settings", "dns.list", "ssl.get", "waf.list", "waf.rules", "ddos.status", "ddos.analytics", "raw"],
"write": ["dns.upsert", "dns.delete", "ssl.set-mode", "waf.ip-block", "waf.ip-allow", "cache.purge"]
}
}Run one action. Read: zone.list, zone.settings, dns.list, ssl.get, waf.list, waf.rules, ddos.status, ddos.analytics, raw. Write (need `confirm: true` and the `dns` scope, not `dns:read`): dns.upsert, dns.delete, ssl.set-mode, waf.ip-block, waf.ip-allow, cache.purge.
- Authentication
- AI key
- Required scopes
dns
| Parameter | Type | Required | Description |
|---|---|---|---|
action | string | Yes | One of the actions listed above, max 40 chars. |
zone | string | No | Zone id or name — required by every zone-scoped action. |
account | string | No | Cloudflare account key, when the key spans several. |
name | string | No | Record name (dns.upsert). |
type | string | No | Record type (dns.upsert, dns.list filter). |
content | string | No | Record value (dns.upsert). |
ttl | integer | No | 1–86400 (dns.upsert). |
proxied | boolean | No | Orange-cloud the record (dns.upsert). |
recordId | string | No | Record id (dns.delete). |
mode | string | No | off, flexible, full or strict (ssl.set-mode). |
ip | string | No | Address for waf.ip-block / waf.ip-allow. |
notes | string | No | Notes for the firewall rule. |
path | string | No | GET-only zone-relative API path (raw), must start with /. |
confirm | boolean | No | Must be true for every mutating action (otherwise 428). |
Errors: 403 — Key is read-only (`dns:read`) or not authorised for Cloudflare automation. 422 — Unknown action, invalid request, or a required field is missing. 428 — Mutating action without `confirm: true`. 429 — Rate limited (60 requests/minute per key). 503 — cfk not installed on this host.
Request
curl -X POST "https://hostingswift.com/api/v1/cloudflare" \
-H "Authorization: Bearer $HOSTINGSWIFT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"action": "dns.upsert",
"zone": "example.com",
"name": "www.example.com",
"type": "A",
"content": "203.0.113.10",
"ttl": 300,
"proxied": true,
"confirm": true
}'Response · 200
{ "ok": true, "result": { "…": "action-specific payload from Cloudflare" } }Need something not listed here?
The API is the same one our own panel uses. If you need an endpoint that is missing, tell us what it should do and we will scope it.
Talk to us