HTTP API

How to authenticate to Loomplane's API, where its OpenAPI document lives, and what each route group does.

Everything the dashboard and loomctl do goes through one HTTP API. The OpenAPI document is served at /openapi.json, and /swagger in development. pkg/client is a typed Go client for it.

Authentication

Every route under /api/v1 except /api/v1/public-config sits behind a guard. It accepts an authsome session or a Loomplane API key as a bearer token:

curl -H "Authorization: Bearer $LOOMPLANE_API_KEY" \
  https://loomplane.example.com/api/v1/projects

Session cookies also work (authsome sets an HttpOnly, SameSite=Lax cookie), and that's what the dashboard uses. The organization comes from the session or key. The dashboard sends X-Loomplane-Org with the organization it believes it's in, and a mismatch returns 409. Make an API key under Settings, API keys. API keys can only be created and revoked from a signed-in session, and not with another key.

GET /api/v1/session returns who you are, your organization and your permissions.

Route groups

All paths are under /api/v1.

GroupWhat it covers
/projectsProjects and their sources, environments, analyses, manifest (get, put, draft, edits, revisions), plans, deployments, bindings, graph, variables, backup policies and recovery
/projects/{id}/clouds, /cloud-changes, /cloud-syncsProject views of Clouds, targets, placement previews and syncs
/projects/{id}/domain-routes, /route-operationsDomain routes and their operations
/analysesOne analysis and its graph
/plansGet a plan, approve it, reject it, read its deployment
/deploymentsGet a deployment, read its logs, retry it
/variablesOrganization-wide variables
/connectionsCloud connections: create, check, replace a credential, delete, read storage
/connection-clouds, /providersThe cloud types you can connect, and the provider catalog
/cloudsOrganization Clouds: targets, grants, servers, pools, changes and syncs
/dns-zonesOrganization DNS zones
/catalogCatalog endpoints and kinds
/githubGitHub installations and the repositories they can read, plus the webhook
/api-keysList, create and revoke API keys
/members, /invitationsPeople
/notificationsNotifications, preferences, retry and signed webhooks
/service-backups, /service-restores, /service-backup-retirementsDatabase recovery
/native-recovery-sources, /native-recovery-copiesNative cloud snapshots and copies
/infrastructureCtrl Plane's status, and the server enrollment callback
/activityThe audit trail
/realtimeLive events
/session, /public-configWho you are, and what the sign-in page needs

The document at /openapi.json has every operation, its parameters and its schemas. It's the source for the dashboard's generated clients (make gen-client).

Key flows

Analyze, plan and approve with curl:

# Analyze
curl -X POST -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
  -d '{}' "$URL/api/v1/projects/$PROJECT/analyses"

# Plan an environment
curl -X POST -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
  -d '{"environment":"production"}' "$URL/api/v1/projects/$PROJECT/plans"

# Approve the revision you read
curl -X POST -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
  -d '{"revision":"..."}' "$URL/api/v1/plans/$PLAN/approve"

Planning runs in the background. The create call returns the plan at once, so read GET /api/v1/plans/{id} until it's done planning. An approval carries the plan's revision (and an optional note). If the plan's world changed, it comes back stale and nothing happens. The OpenAPI document has the full shapes.

Live events

/api/v1/realtime/ws upgrades to a WebSocket, /api/v1/realtime/events serves server-sent events, and /api/v1/realtime/snapshot returns the current state for REST recovery. All three use the same authenticated contract and an organization-scoped cursor. The dashboard falls back from WebSocket to SSE, then to REST recovery when the stream goes stale.

Proxy the WebSocket route with upgrades and keep the SSE route unbuffered. See Monitoring.

Status codes

Stale, busy and referenced-resource conflicts return 409, and invalid or blocked changes return 422. Placement reviews and syncs accept work with 202 and a persisted ID, and they take an idempotency key, so a lost response can be recovered by repeating the same request. Another organization's resources return 404.

Go client

pkg/client wraps the API with the same transport loomctl uses:

c := client.New("https://loomplane.example.com", apiKey)
who, err := c.Session(ctx)

On this page