Guide

API and agents

API overview

The Mesh API is a versioned REST/JSON API for CI pipelines, scripts, and AI agents. Everything the console does with projects, services, deployments, domains, volumes, logs, usage, and billing, the API does too.

Base URL

The API lives at the same origin as the console: add /v1 paths to the address you sign in to. The console shows it on the API tokens page. This guide uses https://mesh.example.com.

Terminal
export MESH_API=https://mesh.example.com
export MESH_TOKEN=wgm_...

curl $MESH_API/v1/token -H "Authorization: Bearer $MESH_TOKEN"

Every path starts with /v1. The API reference lists every endpoint, and GET /v1/openapi.json returns the OpenAPI 3.1 document with every request and response schema.

Authentication

Send an API token as a bearer token. The token acts as the person who created it: workspace roles apply on every call, exactly as in the console, and its scope narrows what it may touch.

Requests and responses

Bodies are JSON with snake_case field names. 64-bit integers, such as size_bytes, are strings. Enum values are their full names, such as DEPLOYMENT_STATE_ACTIVE.

Terminal
curl -X POST $MESH_API/v1/projects \
  -H "Authorization: Bearer $MESH_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name": "storefront"}'

Staged changes

Creating or updating a service, or creating a volume, changes the service's draft. Nothing runs until you release the environment:

Terminal
curl -X POST $MESH_API/v1/environments/$ENVIRONMENT_ID/releases \
  -H "Authorization: Bearer $MESH_TOKEN"

Service.pending_changes and unapplied_changes report what waits. See Deployments and releases.

Updating a service replaces its whole draft and needs the current expected_spec_revision, so two clients cannot overwrite each other's changes. Read the service, change the spec, and send it back.

Deletes

Deletes are restorable during the grace period with POST …/restore. Workspaces, projects, production environments, and volumes need confirmation_name set to the resource's name. GET …/deletion-preview shows what a delete would take with it. See Deleting and restoring.

Errors

Every error has the same shape, and every response carries an X-Request-Id header. Quote it when you ask for help.

JSON
{
  "error": {
    "code": "not_found",
    "message": "service not found",
    "request_id": "6f1c2b0e-…"
  }
}
CodeHTTP statusMeaning
invalid_argument400The request is malformed or a value is out of range.
unauthenticated401The token is missing, expired, or revoked.
permission_denied403The token's scope, access, or your role does not allow this.
not_found404The resource does not exist, or you cannot see it.
conflict, failed_precondition409The resource changed, or its state does not allow this now.
rate_limited429Slow down; see Retry-After.
unavailable503Try again shortly.
deadline_exceeded504The operation took too long.
internal500Something failed on our side.

A resource in another workspace looks the same as a missing one.

Retries

Reads are always safe to retry. Retry a write only when no response arrived. Deployment actions accept an idempotency_key, so repeating the same request never runs the action twice.

Rate limits

Each token may make 10,000 requests per hour, with bursts of up to 50 per second. Responses carry X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset; a 429 adds Retry-After. Your operator can change the limits.

Versioning

/v1 is a stable contract. New endpoints and new optional fields arrive in v1; a breaking change would get a new version prefix.