ProxioDocs
API Reference

Authentication

Authenticate to the Proxio API with a single Bearer key. Learn the pxo_ key format, the read / write / purchase scopes, per-key IP allowlists, expiry, and how to rotate keys safely.

The Proxio API uses one authentication scheme: a Bearer API key sent in the Authorization header. There is no second token, no cookie, and no separate auth domain.

Authorization: Bearer pxo_9fJ2kQ7xR4mN8pL1dW6vB3cH5tZ0aYqS7dK2mN9x

Every endpoint requires a valid key except the two public discovery routes: a GET on the base URL itself and GET /openapi.json.

Key format

A key looks like pxo_ followed by 40 base62 characters. It is generated from 30 cryptographically random bytes, so it carries roughly 240 bits of entropy.

  • The full key is shown once, at creation. It is stored only as a SHA-256 hash, so Proxio can never show it to you again.
  • Only a short prefix (the first 12 characters, e.g. pxo_9fJ2kQ7x) is retained for display, so you can tell keys apart in the dashboard.
  • Lost keys cannot be recovered. Revoke and recreate instead.

Store keys as secrets

Keep keys out of source control, browsers, and logs. Inject them from a secret manager or environment variable at runtime. If a key leaks, revoke it in Settings → API Keys immediately.

Managing keys

Keys are created and managed in the dashboard under Settings → API keys, or programmatically through the API Keys endpoints themselves, so a pipeline can mint and revoke its own credentials without a human opening the dashboard. Each key carries a name, its scopes, an optional expiry, an optional list of allowed IPs, and an optional per-key rate-limit override. The override is self-service in one direction only: you can set a key below the default of 120 req/min, but raising a key above the default is done by Proxio support. The dashboard table also shows each key's prefix, when it expires, its allowed IPs, and a Last used timestamp so you can spot idle or stale keys.

A key can only mint a weaker-or-equal key

Minting through the API carries one more rule the dashboard doesn't need to enforce on itself: a key can only create a key whose scopes, expiry, IP allowlist, and rate limit are no broader than its own. See API Keys for the exact inheritance and narrowing rules.

Scopes

Every key carries one or more scopes. Each endpoint declares exactly one scope it requires, and the key must literally contain it, there is no implicit elevation from write to read.

ScopeGrants
readEvery GET: account, products, services, usage, credentials, sessions, whitelist, locations, wallet (including top-ups and transactions), orders, webhooks (including deliveries and the event log), and API keys. Also POST /orders/quote, it prices without spending, so it's scoped like a read.
writeMutations that don't spend money: credential create / update / delete / rotate, whitelist add / remove (including batch add), session rotate / delete, webhook management (including redeliver), toggling a service's auto-renewal, and API key create / revoke.
purchaseWallet spend, and opening a wallet top-up: POST /orders, POST /services/{id}/renew, and POST /wallet/topups.

The dashboard offers three presets when you create a key:

  • Read-only = read
  • Automation = read, write
  • Full = read, write, purchase

If a key is missing the scope an endpoint needs, the request fails with INSUFFICIENT_SCOPE (403) and a details array naming the required scope:

{
  "error": {
    "code": "INSUFFICIENT_SCOPE",
    "message": "This key is missing the required scope.",
    "doc_url": "https://docs.proxio.net/docs/api/errors#insufficient_scope",
    "request_id": "req_8Ke2jP4mQ",
    "details": [{ "required": "purchase" }]
  }
}

IP allowlists

Each key can pin the source IPs that are allowed to use it. Store a list of CIDR ranges on the key; a call from an IP outside every range fails with IP_NOT_ALLOWED (403). Leave the list empty to allow any IP.

The IP that is checked is the public source address Proxio sees for the request. Allowlists pair well with server-to-server integrations that run from a stable set of egress IPs.

Expiry

A key can carry an expires_at timestamp. After it passes, the key stops working and calls fail with EXPIRED_API_KEY (401). Short-lived keys are a good fit for time-boxed jobs and contractors. Leave expires_at unset for a key that never expires on its own.

How a request is authenticated

On every call the API runs these checks in order and returns the first failure:

CheckFailure codeHTTP
Authorization header presentUNAUTHENTICATED401
Header is a well-formed Bearer pxo_… and the key hash matchesINVALID_API_KEY401
Key is not revoked or deactivatedREVOKED_API_KEY401
Key is not past its expires_atEXPIRED_API_KEY401
Owning account is not suspendedACCOUNT_SUSPENDED403
Caller IP is within the key's allowlistIP_NOT_ALLOWED403
Key carries the endpoint's required scopeINSUFFICIENT_SCOPE403

A malformed key and an unknown key both return INVALID_API_KEY with the same HTTP status and error code (the message text itself differs slightly, "the provided API key is malformed" versus "...is invalid"), so the API never reveals whether a given prefix exists.

Rotating keys

Because a key is scoped and independent, rotation is a clean, zero-downtime swap:

Create the replacement

Mint a new key with the same scopes (and IP allowlist, if any) in Settings → API Keys. Copy the full pxo_… value once.

Deploy it

Roll the new key out to your services or secret manager. Because each key has its own rate-limit budget, the old and new keys run side by side without interfering.

Revoke the old key

Once traffic has fully moved, revoke the old key. Revocation is a soft delete: the key stays listed as revoked for audit, and any further call with it returns REVOKED_API_KEY.

On this page