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.