Docs
Open the console →
API reference

API reference: Cloud accounts

Cloud Control cloud-connections API: list and create accounts, verify (validate) health, disconnect, run an on-demand sync, and read keyset-paginated synced inventory.

Connect and read cloud accounts. Reads are open to any member; mutations require manage_cloud_accounts (SRE · Cloud Admin, Org Admin, or platform admin). Cross-org ids return 404.

GET/api/cloud/accountsSession or Bearer

List your org's cloud accounts with status, health detail and per-type sync runs. Never includes the encrypted connection payload.

Example response
json
{ "accounts": [ { "id": 1, "provider": "AWS", "name": "prod",
  "externalKey": "123456789012", "status": "healthy",
  "healthDetail": { "checks": [ { "name": "sts:AssumeRole", "status": "ok", "checkedAt": "…" } ] },
  "lastValidatedAt": "…", "lastSyncedAt": "…", "runs": [ { "resourceType": "ec2-instance", "stats": {} } ] } ] }
Errors
StatusWhen
401Not signed in.
POST/api/cloud/accountsmanage_cloud_accounts

Create a connection for a provider. Returns 201 with the new account and onboarding references.

Parameters
NameInRequiredDescription
providerbodyyesAWS, GCP, AZR or ALI.
namebodynoOptional label.
awsbodyno{ accountId } for AWS.
gcpbodyno{ projectId, projectNumber } for GCP.
Example request
json
{ "provider": "AWS", "name": "prod", "aws": { "accountId": "123456789012" } }
Example response
json
{ "id": 1, "…": "onboarding references (ExternalId, role/script details)" }
Errors
StatusWhen
400Unknown provider or invalid input.
403Caller lacks manage_cloud_accounts (audited cloud.rbac_denied).
409Already connected — includes existingId.
503Could not create the account.
POST/api/cloud/accounts/{id}/validatemanage_cloud_accounts

Verify / re-check health. First-ever healthy fires the cutover and kicks the first sync.

Parameters
NameInRequiredDescription
idpathyesAccount id in your org.
Example response
json
{ "status": "healthy", "identity": { "…": "…" }, "checks": [ { "name": "…", "status": "ok" } ] }
Errors
StatusWhen
403Caller lacks manage_cloud_accounts.
404No such account in your org.
409Account disconnected, or a check failed — carries missing for a permission error.
503Transient provider error — retry.
POST/api/cloud/accounts/{id}/syncmanage_cloud_accounts

Bounded on-demand sync of one healthy account. Returns 202 with the pass summary.

Parameters
NameInRequiredDescription
idpathyesAccount id in your org.
Example response
json
{ "queued": 4, "completed": 3, "deferred": 1 }
Errors
StatusWhen
403Caller lacks manage_cloud_accounts.
404No such account in your org.
409Connection is not healthy — fix health first.
DELETE/api/cloud/accounts/{id}manage_cloud_accounts

Disconnect (never purge). Syncing stops; discovered rows are marked account_disconnected.

Parameters
NameInRequiredDescription
idpathyesAccount id in your org.
Example response
json
{ "ok": true, "reminder": "delete the IAM role / federation config to fully de-provision." }
Errors
StatusWhen
403Caller lacks manage_cloud_accounts.
404No such account in your org.
409Already disconnected.
GET/api/cloud/resourcesSession or Bearer

Keyset-paginated synced inventory. Filter and page through your resources.

Parameters
NameInRequiredDescription
providerquerynoAWS / GCP / AZR / ALI.
typequerynoResource type filter.
regionquerynoRegion filter.
qquerynoFree-text search.
limitqueryno1–200 (default 100).
cursorquerynoKeyset cursor from a prior nextCursor.
includeDeletedqueryno1 to include soft-deleted rows with reason.
Example response
json
{ "resources": [ { "id": 42, "provider": "AWS", "resourceType": "network",
  "nativeId": "vpc-0abc…", "name": "prod-use1", "region": "us-east-1", "status": "ok",
  "attributes": {}, "providerDetail": {}, "tags": {}, "firstSeenAt": "…", "lastSeenAt": "…",
  "deletedAt": null, "deletedReason": null,
  "managed": false, "managedByWorkspaceId": null } ], "nextCursor": 42 }
Errors
StatusWhen
400limit out of 1–200, or a negative cursor.
401Not signed in / invalid token.
POST/api/cloud/reachabilitySession

Network reachability / path analysis (NET). Given a source and destination IP, returns whether traffic is reachable and the ordered per-layer hop list (security-group egress → NACL egress → route → gateway → NACL ingress → security-group ingress + the stateless return path), naming the blocking layer.

Parameters
NameInRequiredDescription
sourceIpbodyyesSource IPv4 address.
destIpbodyyesDestination IPv4 address.
protocolbodynotcp | udp | icmp | all (default tcp).
portbodyno0–65535 (default 443).
sourceComponentIdbodynoA resource nativeId to disambiguate the source.
destComponentIdbodynoA resource nativeId to disambiguate the destination.
Example response
json
{ "reachable": false, "protocol": "tcp", "port": 443,
  "source": { "kind": "instance", "id": "i-0a…", "name": "prod-node-01", "ip": "10.0.1.41" },
  "destination": { "kind": "instance", "id": "i-0a…", "name": "prod-node-02", "ip": "10.0.2.41" },
  "hops": [ { "layer": "Destination security group (ingress)", "direction": "ingress",
    "component": { "id": "sg-0a…app1", "name": "app", "kind": "securitygroup" },
    "verdict": "deny", "explanation": "No ingress rule allows tcp/443 from 10.0.1.41." } ],
  "blockedAt": 5, "summary": "Not reachable: blocked at destination security group (ingress) …" }
Errors
StatusWhen
400sourceIp/destIp is not a valid IPv4, bad protocol, or port out of range.
401Not signed in.
200A never-connected org (no topology) returns { empty: true }.
POST/api/terraform/workspacesmutate_infra

Create a Terraform workspace from a blueprint against a healthy cloud account. The criticality sets the approval policy: 'production' (default) requires a second approver; 'standard' lets the plan author self-approve.

Parameters
NameInRequiredDescription
blueprintIdbodyyesA blueprint id from GET /api/terraform/blueprints.
cloudAccountIdbodyyesA healthy cloud account in your org, matching the blueprint's provider.
namebodyyesLowercase letters, digits, hyphens (2–41 chars).
regionbodynoDeploy region (defaults from the blueprint).
criticalitybodyno'production' (default — critical, approver ≠ author) or 'standard' (non-production — the plan author may self-approve). Any other value → 400.
Example request
json
{ "blueprintId": "aws/s3-bucket", "cloudAccountId": 3,
  "name": "web-assets", "region": "us-east-1", "criticality": "standard" }
Example response
json
{ "workspace": { "id": 7, "provider": "AWS", "region": "us-east-1",
  "blueprintId": "aws/s3-bucket", "name": "web-assets", "status": "active",
  "criticality": "standard", "currentStateVersion": 0 } }
Errors
StatusWhen
400Unknown blueprint, bad name, provider mismatch, unhealthy account, or invalid criticality.
401Not signed in.
403Role lacks mutate_infra (Viewer).
POST/api/terraform/workspaces/{id}/approvemutate_infra

Approve a planned run. The policy must pass. On a 'production' workspace the approver must differ from the plan's author (separation of duties, 403 on self-approve); on a 'standard' workspace the plan author may approve their own run.

Parameters
NameInRequiredDescription
idpathyesWorkspace id in your org.
runIdbodyyesThe planned run to approve.
Example request
json
{ "runId": 12 }
Example response
json
{ "runId": 12, "state": "approving", "approverId": 5 }
Errors
StatusWhen
401Not signed in.
403Role lacks mutate_infra; policy failed; or (production workspace) the approver is the plan's author.
404No such workspace/run in your org (cross-org / unknown).
POST/api/terraform/importmutate_infra

Import (adopt) any discovered resource into Terraform — including IAM (roles, policies, users, groups) and, via a generic fallback, any other service: generates real HCL + a Terraform import block (with the correct AWS import id per type — IAM roles/users/groups by name, a managed policy by ARN), records the adopt, marks the resource managed, and best-effort commits the HCL to your connected repo. See the Import existing resources guide for limitations (the apply is the mock runner this round).

Parameters
NameInRequiredDescription
nativeIdbodyyesThe discovered resource's native id (from GET /api/cloud/resources, managed:false).
Example request
json
{ "nativeId": "vpc-0aa1b2c3d4e5f0001" }
Example response
json
{ "managed": true, "nativeId": "vpc-0aa1b2c3d4e5f0001", "resourceType": "network",
  "tfType": "aws_vpc", "address": "aws_vpc.prod-use1", "mapped": true,
  "workspaceId": 7, "workspaceName": "imported-aws-us-east-1", "runId": 12,
  "stateVersion": 1, "repoPath": "terraform/imported/aws_vpc-prod-use1.tf.json",
  "repoWritten": true, "commitRef": "63c0111…" }
Errors
StatusWhen
400Missing nativeId / body isn't JSON.
401Not signed in.
403Role lacks mutate_infra (Viewer).
404No such resource in your org (cross-org / unknown id).
409The resource is already under Terraform management.
POST/api/terraform/workspaces/{id}/resourcesmutate_infra

Assign / MOVE a synced resource INTO this workspace (folder). A workspace is a folder of resources; this reassigns membership and recompiles the target AND the resource's previous folder from all their members, returning both recompiled diffs + any address conflicts.

Parameters
NameInRequiredDescription
idpathyesTarget workspace (folder) id in your org.
nativeIdbodyyesThe resource's native id (from GET /api/cloud/resources).
Example request
json
{ "nativeId": "i-0abc123def4567890" }
Example response
json
{ "nativeId": "i-0abc123def4567890", "previousWorkspaceId": null, "targetWorkspaceId": 7,
  "to": { "workspaceId": 7, "workspaceName": "web-tier", "memberCount": 1,
    "diff": { "add": 1, "change": 0, "destroy": 0 }, "conflicts": [], "committed": true,
    "stateVersion": 1, "repoWritten": true }, "from": null }
Errors
StatusWhen
400Missing nativeId / body isn't JSON / the workspace targets a different provider.
401Not signed in.
403Role lacks mutate_infra (Viewer).
404No such workspace or resource in your org (cross-org / unknown).
409The target workspace has been destroyed.
DELETE/api/terraform/workspaces/{id}/resources/{nativeId}mutate_infra

Remove a resource from this folder (unmanage it) and recompile the folder — the removed member shows as a delete in the diff. Native ids containing slashes (GCP/S3) can be passed via a ?nativeId= query, which wins over the path segment.

Parameters
NameInRequiredDescription
idpathyesThe folder (workspace) id the resource currently belongs to.
nativeIdpathyesThe member resource's native id (or pass ?nativeId= for slash-y ids).
Example response
json
{ "nativeId": "i-0abc…", "previousWorkspaceId": 7, "targetWorkspaceId": null,
  "from": { "workspaceId": 7, "diff": { "add": 0, "change": 0, "destroy": 1 }, "memberCount": 0 }, "to": null }
Errors
StatusWhen
401Not signed in.
403Role lacks mutate_infra (Viewer).
404The resource is not a member of this folder in your org (cross-org / unknown).
POST/api/terraform/workspaces/{id}/compilemutate_infra

Recompile the folder module from its member resources and return the diff + any conflicts, WITHOUT changing membership — the drift/recompile check. { commit: true } regenerates + commits (new state version + best-effort repo write) when there are no conflicts.

Parameters
NameInRequiredDescription
idpathyesWorkspace (folder) id in your org.
commitbodynotrue to commit the recompile (default false = preview only).
Example request
json
{ "commit": true }
Example response
json
{ "workspaceId": 7, "workspaceName": "web-tier", "memberCount": 2,
  "diff": { "add": 0, "change": 0, "destroy": 0 }, "conflicts": [], "committed": false, "stateVersion": 3 }
Errors
StatusWhen
401Not signed in.
403Role lacks mutate_infra (Viewer).
404No such workspace in your org (cross-org / unknown).