Vantix API
Lease dedicated Mac minis from your own code. The API lets you check stock, order machines billed to your card on file, manage the SSH keys installed on new machines, and share unbranded browser desktops.
Base URL: https://panel.vantixservers.com/api/v1
Contents
- Quickstart
- Authentication
- Conventions
- Stock
- Orders
- Instances
- SSH keys
- Console links
- Account
- Billing and cancelling
- Errors
- Limits
Quickstart
-
Sign in at panel.vantixservers.com. Under Billing, add a card. Adding a card doesn't charge it.
-
Under API keys, create a key and store it somewhere safe. It's shown once.
-
Check what's in stock:
export VANTIX_KEY=vx_... curl -s https://panel.vantixservers.com/api/v1/stock -H "Authorization: Bearer $VANTIX_KEY" -
Order a machine, with your SSH key so you can log straight in:
curl -s https://panel.vantixservers.com/api/v1/orders \ -H "Authorization: Bearer $VANTIX_KEY" \ -H "Idempotency-Key: $(uuidgen)" \ -H "Content-Type: application/json" \ -d "{\"configuration\":\"16\",\"ssh_keys\":[\"$(cat ~/.ssh/id_ed25519.pub)\"]}"The response lists your new machine under
instances, for examplemac-03. -
Wait for
ssh.keys_statusto becomeinstalled, usually a minute or two, then connect:curl -s https://panel.vantixservers.com/api/v1/instances/mac-03 -H "Authorization: Bearer $VANTIX_KEY" ssh vantix@203.0.113.3 -
To give someone the desktop in their browser, create a console link.
Authentication
Send your API key as a bearer token on every request:
Authorization: Bearer vx_0123456789abcdef...
Keys start with vx_. Create and revoke them in the panel under
API keys. Only accounts with a card on file can create keys, and each
account can have up to 10.
A key acts as your account. Anyone holding it can order machines billed to your card, read your machines' passwords and open their desktops. So:
- Keep keys on your servers. Don't put them in browser code, mobile apps or public repositories. The API doesn't accept requests from other websites' browser JavaScript.
- Use one key per system, so you can revoke one without breaking the others.
- Revoke a key in the panel the moment it may have leaked. Requests using it fail straight away.
A missing, malformed or revoked key gets 401 unauthorized.
Conventions
- JSON. Requests with a body send
Content-Type: application/json. Unknown fields are rejected with400, so typos don't pass silently. - Money. Amounts are integers in cents, in US dollars.
46500is $465.00. - Times. Timestamps are RFC 3339, such as
2026-09-26T10:15:02Z. - IDs. Machines have short IDs such as
mac-03. Orders, SSH keys and console links have UUIDs. - Errors. Every error has the same shape. See Errors.
- Idempotency.
POST /ordersaccepts anIdempotency-Keyheader. See Retrying safely.
Stock
GET /stock
Lists the configurations you can order right now, with live availability and prices. Prices are per Mac, per billing period.
{
"ordering_enabled": true,
"configurations": [
{
"id": "16",
"name": "Mac mini M4",
"chip": "Apple M4 · 16GB · 512GB",
"available": 3,
"max_per_order": 5,
"pricing": {
"quarterly": { "amount": 46500, "currency": "usd", "interval_months": 3 },
"monthly": { "amount": 17800, "currency": "usd", "interval_months": 1 }
}
}
]
}
| Field | Description |
|---|---|
id |
Pass this as configuration when ordering. |
available |
Machines ready to hand over now. 0 means sold out. |
max_per_order |
The most you can order in one request. |
pricing.quarterly |
Billed every 3 months. Always present. |
pricing.monthly |
Billed monthly with no commitment. Only present when offered. |
ordering_enabled is false, with an empty list, while ordering is paused.
Orders
POST /orders
Leases machines and charges your card on file for the first billing period. The machines are yours as soon as the request succeeds.
| Field | Required or default | Description |
|---|---|---|
configuration |
required | An id from GET /stock. |
quantity |
default 1 |
From 1 to the configuration's max_per_order. |
term |
default "quarterly" |
"quarterly" or "monthly". |
ssh_keys |
optional | Up to 10 public keys, added to your account before the machines are reserved, so they're installed at handover. See SSH keys. |
instance_ssh_keys |
optional | One array of public keys per ordered Mac, up to 10 keys per Mac. These keys are exclusive to that Mac's lease; account keys are excluded. Cannot be combined with ssh_keys. |
Keys in ssh_keys are added to your account first, all or none. If they
don't fit under the 10-key limit, the order stops with 409 limit_reached
before anything is reserved or charged. Once added they stay on your account
even if the order then fails, for example for lack of stock.
{ "configuration": "16", "quantity": 2, "term": "monthly", "ssh_keys": ["ssh-ed25519 AAAA... ci@build"] }
For resellers, give each Mac a separate key set:
{
"configuration": "16",
"quantity": 2,
"term": "monthly",
"instance_ssh_keys": [
["ssh-ed25519 AAAA... customer-a@laptop"],
["ssh-ed25519 AAAA... customer-b@laptop"]
]
}
Each inner array belongs to one Mac, in the returned instances order for a
fully fulfilled order. To wait and set keys after ordering, use an empty
array for that Mac, for example "instance_ssh_keys": [[], []]. This still
excludes account keys. Add its keys later with PUT /instances/{id}/ssh-keys.
Keys supplied this way are saved with the pending order and attached only
when payment succeeds, including when payment is resolved later. They never
enter your account key list. If an order reports a provisioning shortfall,
read each assigned Mac's key selection to identify its customer.
Response:
{
"id": "5a0c7c1e-3f55-4a53-9d0e-2b0f4d8f6e21",
"status": "active",
"configuration": "16",
"quantity": 2,
"term": "monthly",
"instances": ["mac-03", "mac-04"],
"created_at": "2026-09-26T10:15:02Z"
}
| Status | Meaning |
|---|---|
201 Created |
Paid. instances lists your new machines. |
200 OK |
A repeat of an earlier request with the same Idempotency-Key. The body is that order, in its current state. |
202 Accepted |
We couldn't confirm the payment outcome yet. The order is pending; poll GET /orders/{id}. It becomes active or failed within about 15 minutes. |
400 |
Invalid request: invalid_request, unknown_configuration, term_unavailable or invalid_quantity. |
402 |
payment_method_required: add a card first. payment_failed: the card was declined, and the message says why. Nothing was charged. |
409 |
insufficient_stock: fewer machines are available than you asked for. error.available says how many are. Nothing was charged. |
422 |
invalid_ssh_key (the message names the bad key) or idempotency_key_reused. |
Stock is held for you while your card is charged, so a 201 never comes back
without machines. In the rare case that some can't be handed over, the order
is still active and its error says how many are still being provisioned.
We follow up by email.
Your card must allow charges without you present. If your bank requires a
verification step for every payment, the order fails with payment_failed.
Use another card or contact your bank.
Retrying safely
Networks fail, and a timed-out order request may or may not have gone through.
Send an Idempotency-Key header with a unique value, such as a UUID, on every
order. If you retry with the same key, you get the original order back rather
than a second one. Reusing a key with different fields, including different
ssh_keys or instance_ssh_keys, returns 422 idempotency_key_reused. Keys can be 1 to 255 printable ASCII characters.
GET /orders/{id}
The order's current state, in the same shape as above.
| Status | Meaning |
|---|---|
pending |
Payment is being confirmed. instances is empty. |
active |
Paid. instances lists the machines. |
failed |
Not charged, or the charge was declined. error says why. |
Instances
An instance is a Mac mini on your account.
GET /instances
{
"instances": [
{
"id": "mac-03",
"name": "Vantix-MacMini-03",
"status": "active",
"configuration": "16",
"ip_address": "203.0.113.3",
"ssh": {
"host": "203.0.113.3",
"port": 22,
"user": "vantix",
"command": "ssh vantix@203.0.113.3",
"key_mode": "account",
"keys_status": "installed",
"keys_installed_at": "2026-09-26T10:16:40Z"
},
"mac_user": "vantix",
"console_url": "https://panel.vantixservers.com/machines/mac-03/guac",
"assigned_at": "2026-09-26T10:15:02Z"
}
]
}
| Field | Description |
|---|---|
ssh.key_mode |
Present when SSH handover is enabled. account: uses your account keys at handover. instance: uses only this Mac's keys. |
ssh.keys_status |
installed: your keys are on the machine. pending: installing, usually a minute or two. no_keys: the selected key set is empty; add account keys or this Mac's keys according to key_mode. unmanaged: contact support to have keys added. |
mac_user |
The macOS account, for SSH and the desktop. |
console_url |
The desktop in a browser where you're signed in to the panel. To give the desktop to someone else, use a console link. |
GET /instances/{id}
One machine, in the same shape, plus mac_password: the macOS account
password, used for sudo and to unlock the screen.
Don't change the macOS account password. The browser console and console links sign in with it, so changing it locks you out of the desktop. If you need it changed, contact support.
Another account's machine returns 404.
SSH keys
SSH on your machines accepts keys only, no passwords. By default, your account
keys are installed on each new machine once, at handover, a minute or two after
it becomes yours. A Mac in instance mode receives only its own key set. In the same step Vantix's own access is removed, so from then
on only you can change the machine's keys.
That means:
- An account key you add reaches machines in
accountmode whosekeys_statusisno_keysorpending. It never reaches a Mac ininstancemode. - It doesn't reach a machine that's already
installed. To add a key there, SSH in with an existing key and append it to/etc/ssh/mosyle_authorized_keys/<mac_user>usingsudo. - Removing a key from your account doesn't remove it from machines that have it.
To have account keys on new machines from the start, pass ssh_keys when
ordering, or add them first. Use instance_ssh_keys for separate customers or
machines. In the panel, choose Set keys separately for each Mac at checkout,
then set each Mac's keys on the dashboard. The browser desktop remains usable
while SSH waits for keys.
Ed25519, ECDSA, security-key types (sk-ssh-ed25519, sk-ecdsa-sha2-nistp256)
and RSA of 3072 bits or more are accepted. Paste the single line from your
.pub file. Options before the key type are rejected, and the comment is kept
for display but never written to a machine.
GET /ssh-keys
{
"ssh_keys": [
{
"id": "8c1d2e3f-0000-4000-8000-000000000001",
"type": "ssh-ed25519",
"fingerprint": "SHA256:Xb2n1s9…",
"comment": "ci@build",
"created_at": "2026-09-26T10:14:00Z"
}
]
}
POST /ssh-keys
curl -s https://panel.vantixservers.com/api/v1/ssh-keys \
-H "Authorization: Bearer $VANTIX_KEY" \
-H "Content-Type: application/json" \
-d "{\"public_key\":\"$(cat ~/.ssh/id_ed25519.pub)\"}"
Returns 201 with the key. Errors: invalid_ssh_key (422), and
duplicate_ssh_key or limit_reached (409).
DELETE /ssh-keys/{id}
Removes the key from your account. Returns 204.
GET /instances/{id}/ssh-keys
Returns the key selection for a Mac you own:
{
"mode": "instance",
"editable": true,
"ssh_keys": [
{
"id": "8c1d2e3f-0000-4000-8000-000000000001",
"type": "ssh-ed25519",
"fingerprint": "SHA256:Xb2n1s9…",
"comment": "customer-a@laptop",
"created_at": "2026-09-26T10:14:00Z"
}
]
}
In account mode this lists the current account keys. In instance mode it
lists this lease's keys. This is the panel's configuration, not a live read
of the Mac's key file. editable becomes false when handover first starts.
PUT /instances/{id}/ssh-keys
Replaces the entire selection before handover starts. The default mode is
instance. Keys are validated together; a bad key leaves the selection unchanged.
{"mode": "instance", "ssh_keys": ["ssh-ed25519 AAAA... customer-a@laptop"]}
- Up to 10 keys per Mac, independently of the account's 10-key limit.
- Account keys are excluded in
instancemode. {"mode":"instance","ssh_keys":[]}clears the selection and waits for keys.{"mode":"account"}switches back to the account keys before handover.- Returns
204on success,422 invalid_ssh_keyfor invalid keys, or409 ssh_keys_lockedif handover has started. A different account's Mac returns404. - Once handover starts, use an existing SSH key or the browser console to
edit
/etc/ssh/mosyle_authorized_keys/<mac_user>withsudo. Contact support if setup has failed. The API cannot change keys on a handed-over Mac. - Separate keys are cleared when the lease changes; they never carry over to the next customer, even if the same account leases the Mac again.
An account-key handover may start immediately after assignment. Choose
instance_ssh_keys when ordering if you need guaranteed time to select keys.
Console links
A console link opens a machine's desktop in any browser, with no sign-in and no Vantix branding. Use them to give your own users or customers a desktop, or to embed one in your own site.
A link gives full control of the machine's desktop, so treat it like a password. It stops working when:
- it expires,
- you revoke it, or
- the machine's lease ends.
Revoking a link, or the lease ending, also disconnects desktops already open through it within a few seconds. Expiry only stops new visits: a desktop opened just before expiry stays connected until it's closed. Prefer short-lived links created when they're needed.
POST /instances/{id}/console-links
| Field | Required or default | Description |
|---|---|---|
title |
optional | Shown in the browser tab and the toolbar, up to 80 characters. Default "Remote desktop". |
expires_in |
default 86400 |
Seconds until the link stops working, from 300 (5 minutes) to 2592000 (30 days). |
The body is optional.
curl -s https://panel.vantixservers.com/api/v1/instances/mac-03/console-links \
-H "Authorization: Bearer $VANTIX_KEY" \
-H "Content-Type: application/json" \
-d '{"title":"Acme build machine","expires_in":3600}'
{
"id": "2f7c9a10-0000-4000-8000-000000000002",
"instance": "mac-03",
"url": "https://panel.vantixservers.com/console/vxc_0123…",
"title": "Acme build machine",
"expires_at": "2026-09-26T11:15:02Z",
"created_at": "2026-09-26T10:15:02Z",
"last_used_at": null
}
The url is only returned here. We store a hash of it, so it can't be shown
again. Create a new link if you lose it.
To hide the toolbar, add ?toolbar=0. That suits embedding in your own page:
<iframe src="https://panel.vantixservers.com/console/vxc_0123…?toolbar=0"
style="width:100%;height:720px;border:0"
allow="clipboard-read; clipboard-write"></iframe>
The toolbar holds the Paste button, which types text into the session, and a Reconnect button. Without the toolbar, people can still type and use the mouse normally.
A link that is invalid, expired or revoked shows a plain "invalid or expired" page. It doesn't say which.
GET /instances/{id}/console-links
The machine's live links, in the same shape but without url.
DELETE /console-links/{id}
Revokes one link. Returns 204.
DELETE /instances/{id}/console-links
Revokes every link to the machine. Returns how many were revoked:
{ "revoked": 3 }
Account
GET /account
{
"id": "aaaaaaaa-0000-4000-8000-00000000000a",
"email": "you@example.com",
"card": { "brand": "Visa", "last4": "4242", "exp_month": 4, "exp_year": 2030 },
"can_order": true,
"api_key_id": "f30e043c-0000-4000-8000-000000000003",
"instances": 2
}
card is null when there's no card on file. can_order is false until you
add one. api_key_id identifies the key that made the request.
Billing and cancelling
- Each order is its own subscription. It renews automatically every quarter
or month, depending on its
term, and charges your card on file. - Change cards with Replace card in the panel. The new card is used for new orders and for every renewal of orders placed through the API. Leases bought through checkout in the panel keep the card used at checkout; change those in Manage billing.
- Manage or cancel subscriptions with Manage billing in the panel. You can't cancel through the API.
- When a subscription ends, its machines are taken back and wiped for the next customer. Copy off anything you need first.
Errors
Errors have one shape:
{
"error": {
"code": "insufficient_stock",
"message": "Not enough machines of this configuration are available right now.",
"available": 1
}
}
Branch on code, which is stable. message is written for people and may change.
| Status | Code | Meaning |
|---|---|---|
400 |
invalid_request |
Malformed JSON, an unknown field or a bad value. |
400 |
unknown_configuration |
Not an id from /stock, or not orderable now. |
400 |
term_unavailable |
Monthly billing isn't offered for this configuration. |
400 |
invalid_quantity |
Below 1 or above max_per_order. |
401 |
unauthorized |
Missing, malformed or revoked API key. |
402 |
payment_method_required |
Add a card in the panel. |
402 |
payment_failed |
The card was declined. Nothing was charged. |
404 |
not_found |
No such endpoint, or it isn't on your account. |
405 |
method_not_allowed |
Wrong HTTP method for the endpoint. |
409 |
insufficient_stock |
Not enough machines. See available. |
409 |
conflict |
A concurrent request is using the same Idempotency-Key. Retry. |
409 |
ssh_keys_locked |
Handover has started; change keys on the Mac itself. |
409 |
duplicate_ssh_key |
That key is already on your account. |
409 |
limit_reached |
Too many SSH keys or console links. See Limits. |
422 |
idempotency_key_reused |
Same Idempotency-Key, different order. |
422 |
invalid_ssh_key |
Not a usable public key. The message says why. |
429 |
rate_limited |
Wait the number of seconds in Retry-After. |
500 |
internal_error |
Retry after a short wait. |
502 |
payment_provider_unavailable |
Couldn't reach the card processor. Retry. |
503 |
unavailable, ordering_disabled, ssh_keys_unavailable, console_unavailable |
Temporarily unavailable. |
Retry 429 and 5xx with backoff. For POST /orders, always retry with the
same Idempotency-Key.
Limits
| Limit | Value |
|---|---|
| Requests | 120 a minute per API key |
| Orders | 10 order requests a minute per account |
| API keys | 10 per account |
| SSH keys | 10 per account, plus 10 per Mac in instance mode |
| Console links | 100 live links per account |
| Opening a console link | 30 times a minute per link |
Need more? Contact team@usevantix.com.