One contract for your casas
The OpenAPI contract, plus the few rules every client follows: idempotency keys, ETags, jobs and problem details.
The machine-readable contract
GET /api/v1/openapi.json returns an OpenAPI 3.1 document of exactly what this deployment implements: every path, schema, required scope and response, plus the webhook events. It is generated from the running operation catalogue, the same one that produces the MCP tools, so REST and MCP never drift apart.
curl -s "https://<your host>/api/v1/openapi.json"The surface covers casas and drafts, revisions and publications, posts, the template catalogue, imports, portfolios and bulk runs, domains and DNS plans, email forwarding, signup and contact settings, social sources, analytics, promotions, billing, team members and webhooks. GET /workspaces/{id}/capabilities tells you which of these are live, simulated or waiting on credentials in your workspace.
Retries are deliberate
- Every mutation needs an
Idempotency-Keyheader of 16 to 128 characters. Repeating a request with the same key and body returns the original result withIdempotent-Replayed: true. The same key with a different body is409 idempotency_key_reused. - Edits to a casa need
If-Matchwith theETagfrom your last read. A stale value is412 revision_conflictand nothing changes. - Publishing takes the exact
revision_idandexpected_digestyou read, so you publish what you checked.
Long work is a job
Publishing, bulk runs and other slow operations answer 202 with a job. Poll GET /workspaces/{id}/jobs/{job_id} no faster than next_poll_after_seconds, or subscribe to job.updated webhooks. Accepted is not finished: read the job’s state, counts and error before you report success.
Errors are problem details
Errors use application/problem+json with a stable code, a localized title, the request_id and retryable. Branch on code, never on the title text.
{
"type": "https://<your host>/problems/insufficient_scope",
"title": "This token does not include the permission this action needs.",
"status": 403,
"code": "insufficient_scope",
"request_id": "01M5...",
"retryable": false,
"context": { "required_scope": "account:read" }
}Lists and limits
- List endpoints take
limit(up to 100) and acursorfrom the previous page. - Each workspace token may make 120 reads and 30 writes per minute. Over the limit you get
429with aRetry-Afterheader. - Keep unknown response fields: new fields can appear without a version change.