One token, made in the panel
Sent as a bearer token. Scope it to read-only or to a single service if you want; tokens are independent of your password and revoking one never logs you out.
JSON over HTTPS. No SDK required, no separate developer account, and no endpoint that exists in the panel but not here.
Create a server
curl -X POST https://api.vpsoffshore.com/v1/servers \
-H "Authorization: Bearer $TOKEN" \
-d '{"plan":"reef","image":"debian-13"}'Returns a build id immediately. The machine answers on SSH about sixty seconds later, and the address is routed before the credentials are sent.
20 endpoints
Base URL https://api.vpsoffshore.com/v1. Versioned in the path; v1 will keep working when v2 exists, and the date it stops will be announced a year ahead.
Servers
Storage
Networking
Catalogue
Billing
Anything the panel can do is here, and nothing here is missing from the panel. When the two disagree that is a bug — tell us from the panel and it is fixed rather than documented as intended behaviour.
How it behaves
An API is judged on its bad paths, not its good ones. Three of the four below are about what happens when something goes wrong.
One token, made in the panel
Sent as a bearer token. Scope it to read-only or to a single service if you want; tokens are independent of your password and revoking one never logs you out.
JSON in, JSON out, no SDK needed
Plain HTTPS with no custom envelope, no XML fallback and no signing ritual. If curl can do it, you have a client. Official libraries exist for Go, Python and TypeScript and none of them is required.
Rate limits you will not hit by accident
600 requests a minute per token, 60 for creation calls. Every response carries the remaining budget in a header, and exceeding it returns 429 with the number of seconds to wait — never a silent drop.
Errors that say what to do
A 4xx carries a machine-readable code, a human sentence, and the field at fault. We would rather return a long error than a short one you have to guess at.
The two things you write once
Both are worth reading before you write the first call rather than after the first failure.
Authenticate
curl https://api.vpsoffshore.com/v1/servers \
-H "Authorization: Bearer $TOKEN"
Tokens are made in the panel and can be scoped to read-only or to one service. They are independent of your password, and revoking one does not log you out anywhere.
Read the rate limit
X-RateLimit-Remaining: 574
X-RateLimit-Reset: 41
On every response, not only on the one that fails. Exceeding the limit returns 429 with the seconds to wait, never a silent drop and never a shortened response.
An error tells you the field
{"error":"plan_unknown",
"message":"No plan named 'reff'. Did you mean 'reef'?",
"field":"plan"}
A machine-readable code, a human sentence and the field at fault. Long errors are cheaper than short ones you have to guess at.
Poll a build
curl https://api.vpsoffshore.com/v1/servers/$ID \
-H "Authorization: Bearer $TOKEN" | jq .state
Goes building → running. There is no webhook you must register before you can create anything, and polling once a second is inside the limit.
Nothing to apply for
No developer account, no approval, no sandbox that behaves differently from production.