REST API

Infrastructure as data. API-first.

Query, diff, and transact on Terraform state over HTTP. Build internal tooling without scraping state files.

MQL queries · Transactions · Terraform HTTP backend
OpenAPI 3.0 Type-Safe Clients Bearer Auth JSON Responses

Integrate in 10 minutes

Three composable calls that cover the full Stategraph API surface.

01
Step 1
Create a service account
shell
$ curl -X POST https://stategraph.example.com/api/v1/api-users \
    -H "Authorization: Bearer $ADMIN_TOKEN" \
    -H "Content-Type: application/json" \
    -d '{"name": "ci-pipeline"}'

# Response
{
  "id": "sa_01j8k9x2p3q4r5s6t7u8v9w0",
  "name": "ci-pipeline",
  "token": "sg_live_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6"
}

$ export SG_TOKEN="sg_live_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6"
02
Step 2
Query your infrastructure state
shell
$ curl "https://stategraph.example.com/api/v1/mql" \
    -H "Authorization: Bearer $SG_TOKEN" \
    --data-urlencode "q=SELECT type, COUNT(*) as count
    FROM instances
    GROUP BY type
    ORDER BY count DESC"

# Your state, as structured data
{
  "rows": [
    { "type": "aws_instance",        "count": 47 },
    { "type": "aws_security_group",  "count": 31 },
    { "type": "aws_s3_bucket",       "count": 18 },
    { "type": "aws_iam_role",        "count": 14 }
  ],
  "total": 4,
  "elapsed_ms": 12
}
03
Step 3
Fetch blast radius before a change
shell
$ curl \
    "$SG_URL/api/v1/states/$STATE_ID/instances/aws_vpc.main/blast-radius" \
    -H "Authorization: Bearer $SG_TOKEN"

# Dependency tree with distance metrics
{
  "address": "aws_vpc.main",
  "dependents": [
    { "address": "aws_subnet.public_a",  "distance": 1, "type": "aws_subnet" },
    { "address": "aws_subnet.public_b",  "distance": 1, "type": "aws_subnet" },
    { "address": "aws_instance.web",     "distance": 2, "type": "aws_instance" },
    { "address": "aws_lb.app",           "distance": 2, "type": "aws_lb" },
    { "address": "aws_ecs_service.api",  "distance": 3, "type": "aws_ecs_service" }
  ],
  "total_dependents": 23
}
Dependency Tree Visualization
aws_vpc.main
CHANGED
aws_subnet.public_a
distance: 1
aws_subnet.public_b
distance: 1
aws_instance.web
distance: 2
aws_lb.app
distance: 2
aws_ecs_service.api
distance: 3
23 total dependents across 3 levels of the dependency graph

API Endpoints

Concrete paths. Structured JSON responses. Full OpenAPI spec for every endpoint.

Query

MQL Query API

GET /api/v1/mql

Execute SQL-like queries against infrastructure state. Returns structured JSON. Use in dashboards, reports, and compliance tools.

View docs →

Manage

States

GET POST /api/v1/tenants/{id}/states

List, create, and import states. Each state maps to a Terraform workspace and becomes queryable via MQL.

View docs →

Audit

Transactions

GET /api/v1/tenants/{tenant_id}/tx
GET /api/v1/tx/{tx_id}/logs

List transactions, fetch logs, and view audit trail. Full history of every terraform apply with tags and timestamps.

View docs →

Analyze

Blast Radius

GET /api/v1/states/{id}/instances/{address}/blast-radius

Returns dependency tree with distance metrics for any resource. Use in pre-apply workflows to quantify change impact.

View docs →

Detect

Gap Analysis

POST /api/v1/tenants/{tenant_id}/gaps/import
GET /api/v1/tenants/{tenant_id}/gaps

Detect drift between Terraform state and live cloud resources. AWS, GCP, and Azure. Results are cached for performance.

View docs →

Backend

Terraform HTTP Backend

GET POST /api/v1/states/backend/{group_id}

Implements the Terraform HTTP backend protocol. State locking, workspace support, drop-in replacement for S3 or GCS.

View docs →

Integration Examples

Real workflows. Real JSON responses. Copy, paste, ship.

CI/CD Pipeline

Block deploys by blast radius

Run a blast radius check before terraform apply. Fail the pipeline if too many resources would be affected.

pre-apply.sh
# Check blast radius for the resource being changed
BLAST=$(curl -s \
  "${SG_URL}/api/v1/states/${STATE_ID}/instances/${ADDR}/blast-radius" \
  -H "Authorization: Bearer $SG_TOKEN")

TOTAL=$(echo $BLAST | jq '.total_dependents')

if [ "$TOTAL" -gt 10 ]; then
  echo "Blast radius too high ($TOTAL dependents)."
  exit 1
fi
Compliance

Find unencrypted resources

Query your entire infrastructure state for encryption violations. Route results to PagerDuty, Slack, or SIEM.

compliance-check.sh
$ curl "$SG_URL/api/v1/mql" \
  -H "Authorization: Bearer $SG_TOKEN" \
  --data-urlencode "q=SELECT type, address
    FROM instances
    WHERE type IN ('aws_s3_bucket', 'aws_ebs_volume')
      AND attributes->>'encrypted' = 'false'"

{
  "rows": [
    { "type": "aws_ebs_volume", "address": "aws_ebs_volume.data_disk" },
    { "type": "aws_s3_bucket",  "address": "aws_s3_bucket.logs" }
  ],
  "total": 2
}
TYPE-SAFE

OpenAPI 3.0 Schema

Full OpenAPI specification for type-safe client generation in TypeScript, Python, Go, Rust, and any language with OpenAPI tooling.

Generate TypeScript Client
$ npx openapi-typescript \
    https://stategraph.example.com/api/v1/openapi \
    --output stategraph.d.ts

// Full type safety
import { paths } from './stategraph';

type States = paths['/api/v1/tenants/{id}/states']['get'];
TypeScript
openapi-typescript
Python
openapi-python-client
Go
oapi-codegen
Rust
openapi-generator

Auth & Access

Machine access uses service accounts. Each integration gets its own identity and token.

POST
Create
Service Account
TOKEN
Authenticate
Bearer Header
API
Query & Transact
All Endpoints
DELETE
Revoke
When Done
Create

Create a service account

Each integration gets its own identity and bearer token. No shared credentials.

create service account
$ curl -X POST $SG_URL/api/v1/api-users \
    -H "Authorization: Bearer $ADMIN_TOKEN" \
    -d '{"name": "terraform-ci"}'

{
  "id": "sa_01j8k9x2p3q4...",
  "name": "terraform-ci",
  "token": "sg_live_a1b2c3d4..."
}
Revoke

Revoke when done

Delete the service account when the integration is decommissioned. Token is immediately invalid.

revoke access
$ curl -X DELETE \
    $SG_URL/api/v1/api-users/sa_01j8k9x2p3q4 \
    -H "Authorization: Bearer $ADMIN_TOKEN"

204 No Content
# Token is immediately invalid

Build on Infrastructure as Data

Query, diff, and transact on your Terraform state over HTTP. OpenAPI schema for type-safe clients in any language.

API Reference Get Started