Skip to content

API Reference

Sovereign GRC exposes a REST API at /api/v1/. All endpoints require authentication via Cloudflare Access JWT token.

Authentication

All API requests must include a valid Cloudflare Access JWT in the CF_Authorization cookie or Authorization: Bearer <token> header.

Base URL

https://your-domain.com/api/v1

Common Response Codes

Code Description
200 Success
201 Created
400 Bad Request - Invalid input
401 Unauthorized - Missing/invalid token
403 Forbidden - Insufficient permissions
404 Not Found
422 Validation Error
500 Internal Server Error

Frameworks

List Frameworks

GET /frameworks

Response:

{
  "items": [
    {
      "id": "uuid",
      "name": "SOC 2 Type II",
      "version": "2017",
      "description": "Trust Services Criteria",
      "control_count": 64
    }
  ]
}

Get Framework

GET /frameworks/{framework_id}

List Framework Controls

GET /frameworks/{framework_id}/controls

Organizations

List Organizations

GET /orgs

Create Organization

POST /orgs
Content-Type: application/json

{
  "name": "Acme Corp",
  "domain": "acme.com"
}

Get Organization

GET /orgs/{org_id}

Update Organization

PUT /orgs/{org_id}
Content-Type: application/json

{
  "name": "Acme Corporation"
}

Delete Organization

DELETE /orgs/{org_id}

Users

Get Current User

GET /users/me

List Organization Users

GET /orgs/{org_id}/users

Create User

POST /orgs/{org_id}/users
Content-Type: application/json

{
  "email": "user@example.com",
  "name": "John Doe",
  "role": "analyst"
}

Roles: admin, auditor, analyst, viewer

Get User

GET /orgs/{org_id}/users/{user_id}

Update User

PUT /orgs/{org_id}/users/{user_id}
Content-Type: application/json

{
  "role": "auditor"
}

Delete User

DELETE /orgs/{org_id}/users/{user_id}

Assessments

List Assessments

GET /orgs/{org_id}/assessments

Query Parameters: - framework_id - Filter by framework - status - Filter by status (pending, in_progress, completed, failed)

Create Assessment

POST /orgs/{org_id}/assessments
Content-Type: application/json

{
  "framework_id": "uuid",
  "name": "Q1 2026 SOC 2 Assessment",
  "scope": "Production environment"
}

Get Assessment

GET /orgs/{org_id}/assessments/{assessment_id}

Delete Assessment

DELETE /orgs/{org_id}/assessments/{assessment_id}

Execute Assessment

Start AI-powered assessment execution.

POST /orgs/{org_id}/assessments/{assessment_id}/execute

Resume Assessment

Resume a paused assessment.

POST /orgs/{org_id}/assessments/{assessment_id}/resume

Cancel Assessment

POST /orgs/{org_id}/assessments/{assessment_id}/cancel

Get Assessment Status

GET /orgs/{org_id}/assessments/{assessment_id}/status

Response:

{
  "status": "in_progress",
  "progress": 45,
  "controls_evaluated": 29,
  "controls_total": 64,
  "current_control": "CC6.1"
}


Findings

List Findings

GET /orgs/{org_id}/findings

Query Parameters: - assessment_id - Filter by assessment - status - Filter by status (pass, fail, partial, not_applicable) - severity - Filter by severity (critical, high, medium, low, info)

Get Finding

GET /orgs/{org_id}/findings/{finding_id}

Update Finding

PATCH /orgs/{org_id}/findings/{finding_id}
Content-Type: application/json

{
  "status": "pass",
  "remediation_notes": "Implemented MFA for all users"
}

Risk Management

List Risk Register Entries

GET /orgs/{org_id}/risks

Query Parameters: - status - Filter by status (open, mitigated, accepted, transferred) - owner_id - Filter by risk owner

Create Risk Entry

POST /orgs/{org_id}/risks
Content-Type: application/json

{
  "title": "Third-party data breach",
  "description": "Risk of vendor experiencing data breach affecting our data",
  "category": "third_party",
  "likelihood": 3,
  "impact": 4,
  "owner_id": "uuid",
  "treatment": "mitigate"
}

Likelihood/Impact Scale: 1-5 (1=Very Low, 5=Very High)

Categories: operational, financial, compliance, strategic, third_party, cyber, reputational

Treatment: accept, mitigate, transfer, avoid

Get Risk Entry

GET /orgs/{org_id}/risks/{risk_id}

Update Risk Entry

PUT /orgs/{org_id}/risks/{risk_id}
Content-Type: application/json

{
  "status": "mitigated",
  "residual_likelihood": 2,
  "residual_impact": 3
}

Get Risk Heatmap

GET /orgs/{org_id}/risks/heatmap

Response:

{
  "inherent": [
    {"likelihood": 3, "impact": 4, "count": 5},
    {"likelihood": 2, "impact": 3, "count": 8}
  ],
  "residual": [
    {"likelihood": 2, "impact": 3, "count": 7},
    {"likelihood": 1, "impact": 2, "count": 6}
  ]
}

List Key Risk Indicators

GET /orgs/{org_id}/kris

Create KRI

POST /orgs/{org_id}/kris
Content-Type: application/json

{
  "name": "Failed Login Attempts",
  "description": "Count of failed login attempts in 24h",
  "unit": "count",
  "green_threshold": 100,
  "amber_threshold": 500,
  "collection_method": "steampipe",
  "steampipe_query": "SELECT count(*) FROM aws_cloudtrail_event WHERE event_name = 'ConsoleLoginFailure'"
}

Update KRI Value

PUT /orgs/{org_id}/kris/{kri_id}/value
Content-Type: application/json

{
  "value": 245
}

Vendors

List Vendors

GET /orgs/{org_id}/vendors

Query Parameters: - status - Filter by status (active, inactive, pending, offboarded) - risk_tier - Filter by risk tier (critical, high, medium, low)

Create Vendor

POST /orgs/{org_id}/vendors
Content-Type: application/json

{
  "name": "Cloud Provider Inc",
  "category": "infrastructure",
  "risk_tier": "critical",
  "contact_email": "security@cloudprovider.com",
  "a2a_endpoint": "https://api.cloudprovider.com/.well-known/sovereign-a2a"
}

Get Vendor

GET /orgs/{org_id}/vendors/{vendor_id}

Update Vendor

PUT /orgs/{org_id}/vendors/{vendor_id}
Content-Type: application/json

{
  "status": "active",
  "risk_rating": 85
}

Request A2A Attestation

POST /orgs/{org_id}/vendors/{vendor_id}/attestation
Content-Type: application/json

{
  "frameworks": ["SOC2_TYPE2", "ISO27001"],
  "requested_evidence": ["audit_report", "certificate", "controls_mapping"]
}

Response:

{
  "assessment_id": "uuid",
  "status": "pending",
  "request_sent_at": "2026-01-27T10:00:00Z"
}


Incidents

List Incidents

GET /orgs/{org_id}/incidents

Query Parameters: - status - Filter by status (open, investigating, contained, resolved, closed) - severity - Filter by severity (critical, high, medium, low, info) - phase - Filter by NIST phase (detection, analysis, containment, eradication, recovery, post_incident)

Create Incident

POST /orgs/{org_id}/incidents
Content-Type: application/json

{
  "title": "Suspicious Login Activity",
  "description": "Multiple failed login attempts from unusual IP range",
  "category": "unauthorized_access",
  "severity": "high",
  "affected_systems": ["auth-server-01", "vpn-gateway"],
  "source": "siem_alert"
}

Categories: malicious_code, unauthorized_access, data_breach, denial_of_service, phishing, insider_threat, physical, other

Severity: critical, high, medium, low, informational

Get Incident

GET /orgs/{org_id}/incidents/{incident_id}

Response includes: - Incident details - Current phase - SLA status - Assigned tasks - Response timeline

Update Incident

PATCH /orgs/{org_id}/incidents/{incident_id}
Content-Type: application/json

{
  "severity": "critical",
  "commander_id": "uuid",
  "affected_records": 5000
}

Transition Incident Phase

POST /orgs/{org_id}/incidents/{incident_id}/transition
Content-Type: application/json

{
  "new_phase": "containment",
  "notes": "Initial analysis complete, moving to containment"
}

Get Incident Timeline

GET /orgs/{org_id}/incidents/{incident_id}/timeline

Response:

{
  "items": [
    {
      "timestamp": "2026-01-27T10:05:00Z",
      "event_type": "phase_transition",
      "description": "Phase changed from detection to analysis",
      "actor": "John Doe"
    }
  ]
}

Execute Playbook

POST /orgs/{org_id}/incidents/{incident_id}/playbook
Content-Type: application/json

{
  "playbook_id": "ransomware",
  "execute_automated": true
}

Business Continuity Management

List Business Processes

GET /orgs/{org_id}/bcm/processes

Create Business Process

POST /orgs/{org_id}/bcm/processes
Content-Type: application/json

{
  "name": "Order Fulfillment",
  "description": "End-to-end order processing and delivery",
  "criticality": "business_critical",
  "rto_hours": 4,
  "rpo_hours": 1,
  "mtd_hours": 24,
  "owner_id": "uuid"
}

Criticality: mission_critical, business_critical, business_operational, administrative

Get Dependency Graph

GET /orgs/{org_id}/bcm/dependencies

Response:

{
  "nodes": [
    {"id": "process-1", "type": "process", "name": "Order Fulfillment"},
    {"id": "asset-1", "type": "asset", "name": "PostgreSQL Primary"}
  ],
  "edges": [
    {"source": "process-1", "target": "asset-1", "dependency_type": "requires"}
  ]
}

Get Single Points of Failure

GET /orgs/{org_id}/bcm/spof

Response:

{
  "items": [
    {
      "asset_id": "arn:aws:rds:...",
      "asset_name": "PostgreSQL Primary",
      "dependent_processes": 5,
      "criticality": "mission_critical",
      "recommendation": "Add read replica in different AZ"
    }
  ]
}

Get Recovery Sequence

GET /orgs/{org_id}/bcm/recovery-sequence

Response:

{
  "tiers": [
    {
      "tier": 1,
      "rto_hours": 1,
      "items": [
        {"type": "asset", "id": "...", "name": "Core Database"}
      ]
    },
    {
      "tier": 2,
      "rto_hours": 4,
      "items": [
        {"type": "process", "id": "...", "name": "Order Fulfillment"}
      ]
    }
  ]
}

Discover Dependencies

Trigger automatic discovery of cloud resource dependencies via Steampipe.

POST /orgs/{org_id}/bcm/discover

Evidence

List Evidence

GET /orgs/{org_id}/evidence

Query Parameters: - finding_id - Filter by finding - assessment_id - Filter by assessment

Get Upload URL

Get a pre-signed URL to upload evidence to R2.

POST /orgs/{org_id}/evidence/upload-url
Content-Type: application/json

{
  "filename": "soc2-report-2026.pdf",
  "content_type": "application/pdf",
  "finding_id": "uuid"
}

Response:

{
  "upload_url": "https://...",
  "evidence_id": "uuid",
  "expires_at": "2026-01-27T11:00:00Z"
}

Get Download URL

GET /orgs/{org_id}/evidence/{evidence_id}/download-url

Reports

List Reports

GET /orgs/{org_id}/reports

Generate Report

POST /orgs/{org_id}/reports/generate
Content-Type: application/json

{
  "type": "compliance_summary",
  "assessment_id": "uuid",
  "format": "pdf"
}

Report Types: compliance_summary, gap_analysis, risk_register, incident_summary, bcm_impact_analysis

Formats: pdf, xlsx, json

Download Report

GET /orgs/{org_id}/reports/{report_id}/download

Health & Status

Health Check

GET /health

Response:

{
  "status": "healthy",
  "version": "1.0.0",
  "services": {
    "database": "healthy",
    "redis": "healthy",
    "opa": "healthy",
    "steampipe": "healthy"
  }
}


Error Responses

All errors follow this format:

{
  "detail": "Error message describing what went wrong",
  "code": "ERROR_CODE",
  "field": "field_name"  // Optional, for validation errors
}

Common Error Codes

Code Description
UNAUTHORIZED Missing or invalid authentication
FORBIDDEN User lacks required permission
NOT_FOUND Resource does not exist
VALIDATION_ERROR Input validation failed
CONFLICT Resource already exists
RATE_LIMITED Too many requests

Rate Limits

Endpoint Limit
Default 100 requests/minute
Assessment execution 5 concurrent
Report generation 10/hour
Evidence upload 50/hour

Rate limit headers are included in all responses: - X-RateLimit-Limit - X-RateLimit-Remaining - X-RateLimit-Reset


OpenAPI Specification

The full OpenAPI 3.0 specification is available at:

GET /api/v1/openapi.json

Interactive API documentation (Swagger UI):

GET /api/v1/docs