Skip to main content

Scanning API

The Scanning API allows you to programmatically trigger security scans, check scan status, and retrieve scan results for your Infrastructure as Code repositories.

Base URL

https://api.cloudgeni.ai/api/v1

Authentication

All endpoints require authentication via the X-CLOUDGENI-API-KEY header. See API Authentication for details.

Endpoints

List Repositories

Get all repositories in your organization.

GET /organizations/{orgId}/repositories
Path Parameters:
ParameterTypeDescription
orgIdstringOrganization ID
Query Parameters:
ParameterTypeDescriptionDefault
limitintegerResults per page (1-100)20
offsetintegerPagination offset0
providerstringFilter by git provider (github, gitlab, azure-devops)-
Example Request:
curl -X GET \
  -H "X-CLOUDGENI-API-KEY: $CLOUDGENI_API_KEY" \
  "https://api.cloudgeni.ai/api/v1/organizations/org_123/repositories?limit=10"
Example Response:
{
  "data": [
    {
      "id": "repo_abc123",
      "name": "infrastructure",
      "fullName": "myorg/infrastructure",
      "provider": "github",
      "defaultBranch": "main",
      "lastScanAt": "2024-01-15T10:30:00Z",
      "status": "active"
    }
  ],
  "pagination": {
    "total": 25,
    "limit": 10,
    "offset": 0
  }
}

Trigger Scan

Start a new scan on a repository.

POST /organizations/{orgId}/repositories/{repoId}/scans
Path Parameters:
ParameterTypeDescription
orgIdstringOrganization ID
repoIdstringRepository ID
Request Body:
FieldTypeDescriptionRequired
branchstringBranch to scanNo (defaults to default branch)
commitstringSpecific commit SHANo
typestringScan type: static, fullNo (default: static)
Example Request:
curl -X POST \
  -H "X-CLOUDGENI-API-KEY: $CLOUDGENI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"branch": "main", "type": "static"}' \
  "https://api.cloudgeni.ai/api/v1/organizations/org_123/repositories/repo_abc/scans"
Example Response:
{
  "id": "scan_xyz789",
  "repositoryId": "repo_abc123",
  "branch": "main",
  "commit": "a1b2c3d4e5f6",
  "type": "static",
  "status": "queued",
  "createdAt": "2024-01-15T10:35:00Z"
}

Get Scan Status

Check the status of a scan.

GET /organizations/{orgId}/repositories/{repoId}/scans/{scanId}
Path Parameters:
ParameterTypeDescription
orgIdstringOrganization ID
repoIdstringRepository ID
scanIdstringScan ID
Example Request:
curl -X GET \
  -H "X-CLOUDGENI-API-KEY: $CLOUDGENI_API_KEY" \
  "https://api.cloudgeni.ai/api/v1/organizations/org_123/repositories/repo_abc/scans/scan_xyz"
Example Response:
{
  "id": "scan_xyz789",
  "repositoryId": "repo_abc123",
  "branch": "main",
  "commit": "a1b2c3d4e5f6",
  "type": "static",
  "status": "completed",
  "createdAt": "2024-01-15T10:35:00Z",
  "completedAt": "2024-01-15T10:36:30Z",
  "summary": {
    "total": 15,
    "critical": 0,
    "high": 2,
    "medium": 5,
    "low": 8,
    "info": 0
  }
}
Scan Status Values:
StatusDescription
queuedScan is waiting to start
runningScan is in progress
completedScan finished successfully
failedScan encountered an error
cancelledScan was cancelled

List Scans

Get scan history for a repository.

GET /organizations/{orgId}/repositories/{repoId}/scans
Path Parameters:
ParameterTypeDescription
orgIdstringOrganization ID
repoIdstringRepository ID
Query Parameters:
ParameterTypeDescriptionDefault
limitintegerResults per page (1-100)20
offsetintegerPagination offset0
statusstringFilter by status-
branchstringFilter by branch-
Example Request:
curl -X GET \
  -H "X-CLOUDGENI-API-KEY: $CLOUDGENI_API_KEY" \
  "https://api.cloudgeni.ai/api/v1/organizations/org_123/repositories/repo_abc/scans?limit=5&status=completed"

Get Scan Findings

Retrieve findings from a completed scan.

GET /organizations/{orgId}/repositories/{repoId}/scans/{scanId}/findings
Path Parameters:
ParameterTypeDescription
orgIdstringOrganization ID
repoIdstringRepository ID
scanIdstringScan ID
Query Parameters:
ParameterTypeDescriptionDefault
limitintegerResults per page (1-100)20
offsetintegerPagination offset0
severitystringFilter: critical, high, medium, low, info-
statusstringFilter: open, resolved, suppressed-
Example Request:
curl -X GET \
  -H "X-CLOUDGENI-API-KEY: $CLOUDGENI_API_KEY" \
  "https://api.cloudgeni.ai/api/v1/organizations/org_123/repositories/repo_abc/scans/scan_xyz/findings?severity=high"
Example Response:
{
  "data": [
    {
      "id": "finding_123",
      "checkId": "CKV_AWS_19",
      "title": "S3 Bucket Encryption",
      "description": "S3 bucket does not have encryption enabled",
      "severity": "high",
      "status": "open",
      "resource": {
        "type": "aws_s3_bucket",
        "name": "data_bucket",
        "file": "storage/main.tf",
        "line": 15
      },
      "remediation": {
        "description": "Enable server-side encryption",
        "code": "server_side_encryption_configuration { ... }"
      }
    }
  ],
  "pagination": {
    "total": 2,
    "limit": 20,
    "offset": 0
  }
}

Webhooks

Scan Completed Webhook

Configure webhooks to receive notifications when scans complete. Webhook Payload:
{
  "event": "scan.completed",
  "timestamp": "2024-01-15T10:36:30Z",
  "data": {
    "scanId": "scan_xyz789",
    "repositoryId": "repo_abc123",
    "repositoryName": "myorg/infrastructure",
    "branch": "main",
    "status": "completed",
    "summary": {
      "total": 15,
      "critical": 0,
      "high": 2,
      "medium": 5,
      "low": 8
    },
    "dashboardUrl": "https://app.cloudgeni.ai/scans/scan_xyz789"
  }
}

Code Examples

Trigger Scan and Wait for Results

const axios = require('axios');

const client = axios.create({
  baseURL: 'https://api.cloudgeni.ai/api/v1',
  headers: {
    'X-CLOUDGENI-API-KEY': process.env.CLOUDGENI_API_KEY
  }
});

async function scanAndWait(orgId, repoId) {
  // Trigger scan
  const { data: scan } = await client.post(
    `/organizations/${orgId}/repositories/${repoId}/scans`,
    { type: 'static' }
  );

  console.log(`Scan started: ${scan.id}`);

  // Poll for completion
  while (true) {
    const { data: status } = await client.get(
      `/organizations/${orgId}/repositories/${repoId}/scans/${scan.id}`
    );

    if (status.status === 'completed') {
      console.log('Scan completed:', status.summary);
      return status;
    }

    if (status.status === 'failed') {
      throw new Error('Scan failed');
    }

    await new Promise(r => setTimeout(r, 5000)); // Wait 5s
  }
}

Check for Critical Findings

#!/bin/bash

SCAN_ID=$(curl -s -X POST \
  -H "X-CLOUDGENI-API-KEY: $CLOUDGENI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"type": "static"}' \
  "https://api.cloudgeni.ai/api/v1/organizations/$ORG_ID/repositories/$REPO_ID/scans" \
  | jq -r '.id')

echo "Scan started: $SCAN_ID"

# Wait for completion
while true; do
  STATUS=$(curl -s \
    -H "X-CLOUDGENI-API-KEY: $CLOUDGENI_API_KEY" \
    "https://api.cloudgeni.ai/api/v1/organizations/$ORG_ID/repositories/$REPO_ID/scans/$SCAN_ID" \
    | jq -r '.status')

  if [ "$STATUS" = "completed" ]; then
    break
  fi
  sleep 5
done

# Check for critical findings
CRITICAL=$(curl -s \
  -H "X-CLOUDGENI-API-KEY: $CLOUDGENI_API_KEY" \
  "https://api.cloudgeni.ai/api/v1/organizations/$ORG_ID/repositories/$REPO_ID/scans/$SCAN_ID" \
  | jq '.summary.critical')

if [ "$CRITICAL" -gt 0 ]; then
  echo "Critical findings detected!"
  exit 1
fi

echo "No critical findings"
exit 0

Error Responses

Common Errors

400 Bad Request - Invalid request parameters:
{
  "error": "bad_request",
  "message": "Invalid branch name",
  "details": {
    "field": "branch",
    "issue": "Branch 'invalid/name' does not exist"
  }
}
404 Not Found - Resource doesn’t exist:
{
  "error": "not_found",
  "message": "Scan not found",
  "details": {
    "scanId": "scan_xyz789"
  }
}
409 Conflict - Scan already in progress:
{
  "error": "conflict",
  "message": "A scan is already running for this repository",
  "details": {
    "existingScanId": "scan_abc123"
  }
}

Rate Limits

Scanning API has specific rate limits:
OperationLimit
Trigger scan10 per minute
Get status60 per minute
List findings30 per minute
See API Authentication for details.