Reading order for agents
This page is written for a non-human reader: an LLM agent, a provisioning script, a Terraform-like tool. It is deliberately short and imperative.
Read in this order
Section titled “Read in this order”- Core concepts — vocabulary. Without it you will misuse “network”, “subnet” and “region”.
- Intent, truth and reconciliation — explains why
a
200 OKdoes not mean the infrastructure changed. - Asynchronous operations — how to wait correctly. Read this before writing any polling loop.
- REST API and the OpenAPI document it links to — the authoritative contract.
- The product page for whatever you are about to create. Each one lists its preconditions in a table; most failures are a missing precondition, not a bug.
Invariants you must not violate
Section titled “Invariants you must not violate”Never treat 202 Accepted as done. Mutating endpoints return 202 with a job
identifier. The resource is not in its final state. Poll the job, not the resource, and
stop on a terminal job state.
Never poll faster than five seconds. Jobs talk to hypervisors; a tight loop achieves nothing except rate limiting.
Never retry a 409 unchanged. 409 Conflict means a precondition failed — a port is
taken, a subnet has no egress, a resource is being deleted. Retrying the identical
request produces the identical conflict. Read the message; it names the precondition and
usually the fix.
Do not invent identifiers. Every resource identifier is prefixed (srv_, lb_,
cert_, s3s_) and issued by the API. Never construct one.
Do not assume address availability. Addresses are allocated by the control plane. Ask for one; never guess an address and configure it inside a guest.
Prefer the smallest scope. Tokens carry a role. Use a read-only token for inspection; only use a write token in the step that actually changes something.
Failure semantics
Section titled “Failure semantics”| Status | Meaning for you |
|---|---|
422 | Your request body is wrong. The response lists offending fields. Fix and resend. |
409 | The request is well-formed but the world is not ready. Read the message; act on it. Do not retry blindly. |
503 | An upstream (hypervisor, DNS provider) is temporarily unavailable. Retry with backoff. |
404 | The resource does not exist for your organisation. This is also the answer when it exists but belongs to someone else — that is deliberate. |
Ordering constraints that are easy to get wrong
Section titled “Ordering constraints that are easy to get wrong”These are real dependencies, not style preferences. Each is enforced and will produce a
409 if you get it backwards.
- A subnet needs a gateway before anything in it can reach the internet. Appliances that must call home — object storage nodes, load balancers — cannot be created in a subnet without egress.
- A
datatier subnet can never have egress. Do not put appliances there. - A TLS listener needs a domain whose DNS zone9 hosts. Certificate issuance uses a DNS challenge, so the domain must be in your account with DNS delegated to the platform.
- A load balancer port is single-protocol. All listeners on the same port must be
either all
tcpor allhttps. - Deleting is two-phase. After a delete call the resource is still visible in a terminating state for a buffer period. That is not a stale read.
Talking to the platform in natural language
Section titled “Talking to the platform in natural language”If your runtime supports the Model Context Protocol, the platform ships an MCP server
that exposes the same intents as tools — servers_list, servers_create and so on.
Read-only tools are marked as such so a client can run them without asking the user for
confirmation.
The MCP server calls the public HTTP API and nothing else. It has no database access and
no privileged path. Anything it can do, you can do with a token and curl; the reverse
is also true, which is why there is no capability gap to discover. See
MCP server.