API

Authentication and scopes

API keys, scopes, address allowlists: what a key may do, and what it may not.

A key acts as you: same quota, same credit, same suspensions. It is not a back door, it is you. Which is also why it reaches neither your invoices, nor your payment methods, nor your tickets.

The token

It travels as a bearer token, on every call:

bash
Authorization: Bearer ffxf_live_a1b2c3d4…

We store only its SHA-256 fingerprint. The console then shows only its head, enough to recognise the key in a list without it being usable. A lost key is not recovered; it is revoked.

Ten keys per account. Enough to separate concerns (monitoring, provisioning, CI) and few enough that the inventory stays readable.

Scopes

One scope per consequence, not per resource: reading costs nothing, acting interrupts a service, creating spends credit, destroying erases a disk.

ScopeWhat it opens
catalog.readregions, plans and images (already public)
vms.readlist machines and read their state
vms.createorder, spends credit
vms.actionstart, stop, reboot, reinstall, rename
vms.destroydestroy a machine and its disk
vms.consoleopen a console session
network.writeIPv6 addresses, reverse DNS, private networks, firewalls and load balancers
backups.writerestore and delete backups
billing.readbalance, usage, quota
billing.writeset the monthly budget
sshkeys.writemanage the account SSH keys

A call outside a key's scopes answers 403 insufficient_scope, and says which one was missing.

Restricting to addresses

A key can accept calls only from listed addresses. That is the setting that makes a stolen token useless elsewhere, and it costs one line when creating the key. With no list, the key works from anywhere.

Expiry and revocation

An optional expiry date is set at creation: after that day the key stops working, and nothing else changes. Revocation deletes the key rather than disabling it: a key you no longer want should not stay one click from working again.

Anything using it stops immediately. Plan the rotation: create the new key, deploy it, then revoke the old one.

No stored key: OIDC

In GitHub Actions, GitLab CI or any other OIDC issuer, a token issued to the job for a few minutes replaces the key. You declare the issuer and a binding (conditions on the repository, branch or workflow, and scopes); the job sends its token like a key. See OIDC: CI without an API key.

Authentication refusals

CodeWhat happened
missing_tokenno Authorization header
invalid_api_keyunknown token
key_disabledkey switched off
key_expiredpast its expiry date
ip_not_allowedcall from an address outside the list
insufficient_scopethe key lacks the required scope
account_suspendedaccount closed: contact support
invalid_oidc_tokenOIDC token malformed, badly signed, expired or for an unknown audience
oidc_claim_mismatchvalid OIDC token that no enabled binding accepts
binding_expiredthe matching OIDC binding has expired
oidc_provider_unavailableOIDC issuer unreachable, try again later

Support & discussions

Technical questions, incident reports, or infrastructure discussions, the team is reachable on Discord, Telegram, X, Instagram, Reddit, and IRC.