Cloud Accounts API Pro+
Manage cloud accounts for multi-account, multi-provider cloud discovery. Each cloud account represents a set of credentials for scanning resources in an AWS, Azure, or GCP environment.
Endpoints Summary
| Method | Endpoint | Description |
|---|---|---|
GET | /api/cloud-accounts | List cloud accounts |
POST | /api/cloud-accounts | Add a cloud account |
GET | /api/cloud-accounts/:id | Get account details |
PUT | /api/cloud-accounts/:id | Update a cloud account |
DELETE | /api/cloud-accounts/:id | Remove a cloud account |
POST | /api/cloud-accounts/:id/validate | Validate credentials |
Authentication
All endpoints require a Bearer token in the Authorization header.
Authorization: Bearer <your-api-token>List Cloud Accounts
GET /api/cloud-accountsReturns all cloud accounts for the current organization.
Example:
curl -X GET "https://api.controlinfra.com/api/cloud-accounts" \
-H "Authorization: Bearer YOUR_TOKEN"Response:
{
"accounts": [
{
"_id": "665b1c2d3e4f5a6b7c8d9e0f",
"name": "Production",
"awsAccountId": "123456789012",
"credentialType": "assumeRole",
"roleArn": "arn:aws:iam::123456789012:role/ControlinfraReadOnly",
"status": "active",
"lastValidated": "2025-01-15T10:00:00Z",
"regions": ["us-east-1", "us-west-2"],
"createdAt": "2025-01-01T00:00:00Z"
},
{
"_id": "665b1c2d3e4f5a6b7c8d9e10",
"name": "Staging",
"awsAccountId": "987654321098",
"credentialType": "accessKey",
"status": "active",
"lastValidated": "2025-01-14T08:00:00Z",
"regions": ["us-east-1"],
"createdAt": "2025-01-05T00:00:00Z"
}
]
}Add a Cloud Account
POST /api/cloud-accountsCommon Fields:
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Friendly account name |
provider | string | Yes | Cloud provider: aws, azure, or gcp |
AWS Fields (nested under aws):
| Field | Type | Required | Description |
|---|---|---|---|
aws.authMethod | string | Yes | credentials, assume_role, or oidc |
aws.accessKeyId | string | Conditional | AWS access key ID (if authMethod is credentials) |
aws.secretAccessKey | string | Conditional | AWS secret key (if authMethod is credentials) |
aws.roleArn | string | Conditional | IAM role ARN (if authMethod is assume_role or oidc) |
aws.externalId | string | No | External ID for AssumeRole (recommended) |
aws.region | string | No | Default region (defaults to us-east-1) |
Azure Fields (nested under azure):
| Field | Type | Required | Description |
|---|---|---|---|
azure.authMethod | string | Yes | service_principal or oidc |
azure.subscriptionId | string | Yes | Azure Subscription ID |
azure.tenantId | string | Yes | Azure AD Tenant ID |
azure.clientId | string | Yes | App Registration Client ID |
azure.clientSecret | string | Conditional | Client secret (if authMethod is service_principal) |
GCP Fields (nested under gcp):
| Field | Type | Required | Description |
|---|---|---|---|
gcp.authMethod | string | Yes | service_account |
gcp.projectId | string | Yes | GCP project ID |
gcp.clientEmail | string | Yes | Service account email |
gcp.privateKey | string | Yes | Service account private key (PEM) |
Example (AWS — AssumeRole):
curl -X POST "https://api.controlinfra.com/api/cloud-accounts" \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Production",
"provider": "aws",
"aws": {
"authMethod": "assume_role",
"roleArn": "arn:aws:iam::123456789012:role/ControlinfraReadOnly",
"externalId": "controlinfra-abc123",
"region": "us-east-1"
}
}'Example (Azure — Service Principal):
curl -X POST "https://api.controlinfra.com/api/cloud-accounts" \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Azure Production",
"provider": "azure",
"azure": {
"authMethod": "service_principal",
"subscriptionId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"tenantId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"clientId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"clientSecret": "your-client-secret"
}
}'Example (GCP — Service Account):
curl -X POST "https://api.controlinfra.com/api/cloud-accounts" \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "GCP Production",
"provider": "gcp",
"gcp": {
"authMethod": "service_account",
"projectId": "my-project-123",
"clientEmail": "controlinfra@my-project-123.iam.gserviceaccount.com",
"privateKey": "-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----\n"
}
}'Response: 201 Created
{
"_id": "665b1c2d3e4f5a6b7c8d9e0f",
"name": "Production",
"provider": "aws",
"status": "active",
"createdAt": "2025-01-15T10:00:00Z"
}WARNING
Credentials are encrypted at rest and never returned in API responses after creation.
Get Account Details
GET /api/cloud-accounts/:idExample:
curl -X GET "https://api.controlinfra.com/api/cloud-accounts/665b1c2d3e4f5a6b7c8d9e0f" \
-H "Authorization: Bearer YOUR_TOKEN"Update a Cloud Account
PUT /api/cloud-accounts/:idUpdate account properties. Only provided fields are updated. Provider credentials are passed under the provider-specific key (aws, azure, or gcp).
Request Body:
| Field | Type | Description |
|---|---|---|
name | string | Friendly account name |
status | string | active or disabled |
aws | object | Updated AWS credentials (for AWS accounts) |
azure | object | Updated Azure credentials (for Azure accounts) |
gcp | object | Updated GCP credentials (for GCP accounts) |
Example:
curl -X PUT "https://api.controlinfra.com/api/cloud-accounts/665b1c2d3e4f5a6b7c8d9e0f" \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Production (Primary)"
}'Delete a Cloud Account
DELETE /api/cloud-accounts/:idRemoves the cloud account and its stored credentials. Discovered resources from this account are retained but marked as disconnected.
Example:
curl -X DELETE "https://api.controlinfra.com/api/cloud-accounts/665b1c2d3e4f5a6b7c8d9e0f" \
-H "Authorization: Bearer YOUR_TOKEN"Response: 204 No Content
Validate Credentials
POST /api/cloud-accounts/:id/validateTest the stored credentials by calling the provider's identity API (AWS STS, Azure Resource Manager, or GCP Cloud Resource Manager).
Example:
curl -X POST "https://api.controlinfra.com/api/cloud-accounts/665b1c2d3e4f5a6b7c8d9e0f/validate" \
-H "Authorization: Bearer YOUR_TOKEN"Response:
{
"valid": true,
"awsAccountId": "123456789012",
"arn": "arn:aws:sts::123456789012:assumed-role/ControlinfraReadOnly/session",
"validatedAt": "2025-01-15T12:00:00Z"
}Error Response (invalid credentials):
{
"valid": false,
"error": "The security token included in the request is expired",
"validatedAt": "2025-01-15T12:00:00Z"
}Plan Limits
| Plan | Max Cloud Accounts | Max Regions |
|---|---|---|
| Free | 0 | 0 |
| Pro | 1 | 1 |
| Team | Unlimited | Unlimited |
| Enterprise | Unlimited | Unlimited |
Exceeding plan limits returns 403 Forbidden with a plan upgrade message.