In one paragraph: everything the console does runs on a public REST API at https://api.rarecloud.io/v1, so anything you can click you can script. You authenticate with a bearer token you create in the console and scope to the job. Every endpoint is in the API reference and the OpenAPI spec. This page covers what they all have in common. If you prefer not to write HTTP calls, the CLI, the Terraform provider and the MCP server use the same API.
Read the public catalog
Products, plans, regions and images need no token:
curl -s https://api.rarecloud.io/v1/catalog/regions | jq .data
curl -s https://api.rarecloud.io/v1/catalog/images | jq .data
curl -s https://api.rarecloud.io/v1/catalog/listings/cloud-vm | jq .data
Create a token
In the console open Account, then API tokens, then New token. Give it a name of up to 80 characters, pick its scopes, and optionally set an expiry date and a rate limit from 1 to 600 requests a minute (the default is 60). The token starts with rc_pat_ and is shown once, so copy it before you close the dialog.
export RARECLOUD_TOKEN=rc_pat_...
curl -s https://api.rarecloud.io/v1/services \
-H "Authorization: Bearer $RARECLOUD_TOKEN" | jq .data
Revoke a token in the same place and it stops working. Creating, listing and revoking tokens needs a signed-in console session, so a token can never mint itself a stronger one.
Scopes
| Scope | What it opens |
|---|---|
account:read / account:write | Profile, SSH keys, contacts, activity / changes to them |
services:read / services:write | Servers, clusters, volumes, networks, firewalls, load balancers, Object Storage, the registry, sandboxes, proxies, limits / creating and changing them |
billing:read / billing:write | Invoices, balance, ledgers / top-ups, paying invoices, payment methods, spend alerts, vouchers |
domains:read / domains:write | Domains, DNS, TLD prices / registering, transferring, renewing, managing |
tickets:read / tickets:write | Tickets / opening, replying, closing |
* | All of the above |
Scopes match exactly: services:write does not include services:read. A call without the scope it needs answers 403 PERMISSION_DENIED.
Responses
A success is { "ok": true, "data": ... }. A failure is:
{ "ok": false, "error": { "code": "INVALID_PARAM", "message": "...", "details": [{ "field": "...", "message": "..." }] } }
code is stable, so branch on it. details appears only when there is something to add. GET /v1/services can answer with an X-Partial-Results header naming a category that could not be read just now; the rest of the list is still valid.
An id that belongs to another account answers 404, the same as one that does not exist.
Error codes
| HTTP | code | What to do |
|---|---|---|
| 400 | INVALID_PARAM | Fix the request. details names the field. |
| 401 | AUTH_REQUIRED, AUTH_TOKEN_EXPIRED | Send a valid token. |
| 403 | PERMISSION_DENIED | The token lacks the scope. Create one that has it. |
| 403 | RESOURCE_PROTECTED | API access is switched off for this resource in the console. Do not retry; ask its owner. |
| 403 | ACCOUNT_ORDERING_BLOCKED | New orders are paused on this account. Contact support. |
| 403 | ACCOUNT_CLOSED | The account is closed. Contact support. |
| 404 | NOT_FOUND | Wrong id, or not yours. |
| 409 | CONFLICT | The resource's state does not allow this now. details may say why. |
| 409 | NOT_READY | The resource is still getting ready. Wait and retry. |
| 409 | REACTIVATION_WINDOW_CLOSED | A lapsed proxy can no longer be renewed. Order a new one. |
| 409 | BACKEND_POLICY_BLOCKED | A service behind the API refused the request on a policy of its own. Nothing changed, and the same request can succeed later. |
| 409 | QUOTA_EXCEEDED | A limit is in the way. See limits and quota requests. |
| 409 | IDEMPOTENCY_IN_PROGRESS | The first request with this key is still running. Wait Retry-After, then retry with the same key. |
| 413 | PAYLOAD_TOO_LARGE | The body or file is over the limit. |
| 422 | IDEMPOTENCY_KEY_REUSED | This key was used for a different request. Use a new key. |
| 429 | RATE_LIMITED | Wait Retry-After. |
| 501 | NOT_IMPLEMENTED | The operation is not available for this resource. |
| 502 | BACKEND_BAD_RESPONSE | A service behind the API refused or failed. |
| 503 | BACKEND_UNAVAILABLE | Briefly busy. Wait Retry-After; retry a create only with the same Idempotency-Key. |
| 503 | ENV_UNAVAILABLE | A sandbox could not take its environment variables. No sandbox was created. |
| 503 | SANDBOX_LAUNCH_GATE_CLOSED | AI Sandboxes are not open on this account yet. |
| 500 | INTERNAL | A real fault. Open a ticket. |
Rate limits
Each token has its own limit per minute, counted separately per API area (/v1/services, /v1/billing and so on). Answers to token calls carry X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset. Past the limit you get 429 with Retry-After.
Safe retries
If a create times out, you cannot tell whether it happened. Send an Idempotency-Key header with a fresh value per operation (a UUID works; 1 to 255 printable ASCII characters) and the same value when you retry:
curl -s https://api.rarecloud.io/v1/volumes \
-H "Authorization: Bearer $RARECLOUD_TOKEN" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 5f0c6c1e-8a43-4b8e-9f2a-0d4a2f6e9b17" \
-d '{"name":"web-01-data","sizeGb":50}'
The API runs it at most once. A retry gets the first answer back, marked Idempotent-Replayed: true. Keys are kept for 24 hours. A one-time secret from the first answer, such as a console password, is not repeated: the replay lists the omitted fields in secretsOmittedOnReplay. The routes that take the header are marked in the API reference.
Check before you order
POST /v1/services/preflight takes the same body as POST /v1/services and runs the same balance check, with nothing created, held or charged. When the answer is no it says why, and where it applies gives the add-funds or pay-invoice link. It needs services:write.
Work that finishes in the background
Some creates answer before the work is done. A load balancer answers with status pending: poll GET /v1/load-balancers/{id} until it is active. A server resize answers 202: poll GET /v1/services/{id}. Poll instead of creating again.
Resources you made read-only
In the console you can switch API access off for a single resource. Tokens can still read it, but changes and reads of its credentials answer 403 RESOURCE_PROTECTED. Objects carry apiAccess (full or read_only), and GET /v1/api-access lists the read-only ones. No token can flip the switch.
Links
- API reference: console.rarecloud.io/docs/api
- OpenAPI spec: console.rarecloud.io/openapi.json
- For agents: console.rarecloud.io/llms.txt
- Next steps: Cloud VM docs, limits and quota requests, using the API from AI agents