Skip to content

API overview ​

The MicroApps API is a plain REST API that speaks JSON. It is the same API the console uses, so anything you can do by clicking, you can do with an HTTP request. What the console uses is what you get.

Base URL ​

https://cloud-api.microapps.io

Authentication ​

Every request under /api carries a bearer token in the Authorization header:

http
Authorization: Bearer <token>

The token can be one of two things, and the API works out which by looking at it:

  • A login token (JWT) from POST /auth/login. Good for interactive sessions. It expires after about an hour and there is no refresh endpoint, so long-lived automation should use the other option.
  • An API key (starts with mck_) that you create once and reuse. Best for scripts, servers, and anything that runs without a human present. See API keys.

Everything under /auth/* and /open/* is unauthenticated. /mcp is API key only.

Content type ​

Requests and responses are JSON unless a specific endpoint says otherwise (invoice PDFs and the pod console are the exceptions).

http
Content-Type: application/json
Accept: application/json

Every response carries an X-Request-Id header. Quote it if you open a support ticket about a failed call and we can find the exact request.

Pagination ​

List endpoints that can grow without bound take three query parameters:

ParameterDefaultNotes
page11-based
limit20max 100; larger values are clamped, not rejected
search-case-insensitive substring match; longer than 100 characters and the tail is trimmed
GET /api/pods?page=1&limit=20&search=web

They return an envelope:

json
{
  "data": [
    { "id": "6a4d5b83b7006ccae6391810", "name": "my-app", "status": "Running" },
    { "id": "6a4d5b83b7006ccae6391811", "name": "web-staging", "status": "Stopped" }
  ],
  "total": 42,
  "page": 1,
  "limit": 20,
  "totalPages": 3
}

Smaller collections (a pod's snapshots, a firewall's rules) come back as a plain array. Each endpoint's page says which shape it uses.

Errors ​

Errors are JSON with a single message field. The HTTP status carries the category.

http
HTTP/1.1 400 Bad Request
Content-Type: application/json
json
{ "message": "Subject must be between 3 and 200 characters" }

There is no error code, no nested errors array, and no field-level breakdown - just the status and a sentence you can show a user.

StatusMeaning
400Bad request - your input did not validate
401Unauthorized - missing, invalid, or expired token
402Insufficient credit - top up and try again
403Forbidden - no permission, unverified email, or you hit an account limit
404Not found - or not yours
409Conflict - a duplicate, or the resource is busy with another operation
428A domain you are adding needs ownership validation first
429Too many requests, or too many failed logins
500Something broke on our side

Credit and limits ​

Creating anything billable (pods, snapshots, backups, networks, firewalls, domains, email accounts) needs at least $3 of account credit, or you get a 402:

json
{ "message": "Insufficient credit. You need at least $3 on your account to proceed." }

Each resource type also has a per-account limit; hit it and you get a 403. (The per-pod snapshot and backup caps are the one exception - those return 400. The backup cap goes away once paid backups start.) Both are covered in Billing and Account limits.

Rate limits ​

Every caller gets a token bucket: 5 requests per second sustained, with a burst of 15. The burst absorbs the handful of parallel calls a dashboard fires on load; the 5/s is the ceiling you cannot average above.

PrefixBucket keyed on
/api, /mcpyour account
/auth, /openthe calling IP address

Going over returns 429:

json
{ "message": "Rate limit exceeded; slow down and try again" }

If you have a legitimate reason to go faster, tell us - we would rather raise the limit than watch you write exponential backoff.

Asynchronous operations ​

A lot of actions (creating a pod, resizing, restoring a snapshot, cloning) kick off work in the background. The API responds right away with the new resource in a transient status like Initializing or Restoring, and you poll until it settles. Firing a second operation at a resource that is still busy returns 409.

Sections ​

Built for the long tail.