Skip to content

API guide

Practical recipes for the DXDT public API. The reference is the contract; this page shows how to use it.

Every request sends a token as a bearer header:

export DXDT_HOST=https://<your-dxdt-host>
export DXDT_TOKEN=dxdt_...

curl -s "$DXDT_HOST/api/v1/me" -H "Authorization: Bearer $DXDT_TOKEN"

Recipes

List open findings

curl -s "$DXDT_HOST/api/v1/pulse/findings?status=open" \
  -H "Authorization: Bearer $DXDT_TOKEN" | jq '.findings[] | {id, title, severity}'

Filters: status, severity, domain. Sorting: sort_by, sort_dir. One finding with its evidence trail: GET /api/v1/pulse/findings/{id}.

Update a finding's status

curl -s -X PATCH "$DXDT_HOST/api/v1/pulse/findings/$FINDING_ID/status" \
  -H "Authorization: Bearer $DXDT_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"status": "resolved"}'

Returns {"success": true} and records the change in the audit trail. Statuses follow the finding lifecycle: open, acknowledged, in_progress, resolved, dismissed. Any non-GET call requires a read_write token.

List and create incidents

# Open incidents
curl -s "$DXDT_HOST/api/v1/incidents?status=open" \
  -H "Authorization: Bearer $DXDT_TOKEN" | jq '.incidents[] | {id, title, severity}'

# Create one (201)
curl -s -X POST "$DXDT_HOST/api/v1/incidents" \
  -H "Authorization: Bearer $DXDT_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"title": "Checkout latency spike", "severity": "SEV2"}'

Filters: status, severity (create defaults to SEV3). Timeline: GET /api/v1/incidents/{id}/timeline, incremental with ?after_id=<n>.

Ask the agent

curl -s -X POST "$DXDT_HOST/api/v1/ask" \
  -H "Authorization: Bearer $DXDT_TOKEN" \
  -H "Content-Type: application/json" \
  --max-time 660 \
  -d '{"prompt": "why did egress spike yesterday?", "session_id": "ci-probe-1"}'

Returns {"reply": "...", "session_id": "..."}. Requires read_write scope; counts against the token's daily agent budget. Turns can take minutes — set a generous timeout, or stream via /api/v1/stream and /api/v1/stream/attach (runs are durable server-side; see the reference).

Review a Terraform plan

curl -fsS "$DXDT_HOST/api/v1/plan-review" \
  -H "Authorization: Bearer $DXDT_TOKEN" \
  -H "Content-Type: application/json" \
  -d "{\"plan\": $(jq -Rs . < plan.json)}"

Annotates the change against your live environment and returns overall_risk, cited annotations, and "read_only": true. A missing or empty plan is a 400. See Plan review for the response shape and CI wiring.

Conventions

Convention Behavior
List responses Wrapped in a named key: {"findings": [...]}, {"incidents": [...]}, {"sessions": [...]}
Pagination GET /api/v1/incidents takes limit (default 50) and offset (default 0); findings use filters + sort_by/sort_dir
Timestamps UTC, ISO-8601
Tenancy Every response is scoped to the token's tenant; no parameter changes that

Errors

Standard errors are {"detail": "..."}:

Status Meaning
400 Invalid body (e.g. missing prompt, title, or plan)
401 Missing, invalid, expired, or revoked token — never a silent fall-through
403 Valid token, insufficient rights: read token on a non-GET, agent invocation without read_write, or a plan without API access
404 No such resource in your tenant
429 Daily agent budget exhausted for this token (agent endpoints only; everything else keeps working)

Feature endpoints gated by your plan return 402 with a different shape:

{"error": "tier_restricted", "message": "...", "upgrade_required": true}

The only rate limit is the agent budget: agent invocations are capped per token per UTC day — see Authentication.

Stability

/api/v1 is the stable public contract: documented endpoints won't change incompatibly without a new version prefix. Pin scripts and CI to /api/v1/... paths; probe with the unauthenticated GET /api/v1/version.