ArchTruth

ArchTruth / docs / api

ArchTruth API & MCP

Both surfaces expose the same operations and share one implementation. Authenticate with an org-scoped API key created by a workspace owner under Settings · API keys. Keys are hashed at rest and shown once.

Authorization: Bearer as_live_…
ScopeAllows
readlist, get, search, render, validate
write+ create, patch (typed ops), replace (whole DSL)

Every write creates a version and an audit row attributed to the key (versions.api_key_id, audit_log.api_key_id).

Concurrency

GET /diagrams/{id} returns ETag: "<revision>". Send it back as If-Match on PATCH/PUT; a stale value returns 412 and nothing is written. Omit If-Match for unconditional writes (not recommended for agents).

Rate limits

Per key, per minute: 120 read requests, 30 write requests. Every authenticated /api/v1 response carries X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset (Unix seconds); a 429 adds Retry-After. Counters live in api_requests, one row per key and minute, pruned hourly by pg_cron after 24 h.

REST — /api/v1

OpenAPI 3.1: GET /api/v1/openapi (public).

BASE=https://archtruth.app/api/v1
H='Authorization: Bearer as_live_…'

curl -s $BASE/diagrams -H "$H"
curl -s $BASE/diagrams/<id> -H "$H"                       # → dsl, layout, diagnostics, layers, ETag
curl -s $BASE/diagrams/<id>/render?layer=future -H "$H"   # → image/svg+xml
curl -s "$BASE/search?q=checkout" -H "$H"
curl -s $BASE/validate -H "$H" -H 'content-type: application/json' -d '{"dsl":"service a"}'

curl -s $BASE/diagrams -H "$H" -H 'content-type: application/json' \
  -d '{"name":"Orders","dsl":"service a \"A\"\nservice b \"B\"\na -> b"}'

curl -s -X PATCH $BASE/diagrams/<id> -H "$H" -H 'If-Match: 3' -H 'content-type: application/json' \
  -d '{"ops":[{"op":"addNode","id":"c","kind":"queue","label":"Events"},{"op":"addEdge","from":"b","to":"c"}],"message":"add event bus"}'

Ops

addNode {id, kind, label?, parent?, props?, layer?} · removeNode {path, layer?} · setNode {path, label?, kind?, props?, unset?} · moveNode {path, parent} · addEdge {from, to, dir?, label?, props?, layer?} · removeEdge {id, layer?} · setEdge {id, label?, props?, unset?} · setTitle {title} · setDiagramProps {props?, unset?} · addLayer {id, label?} · removeLayer {id} · setLayer {id, label?, props?}

Ops are applied through the CST-preserving printer: untouched lines (comments, spacing, order) stay byte-identical. layer on add/remove ops records the change in that layer (base removals become ! lines).

MCP — /api/mcp (Streamable HTTP)

Tools: list_diagrams, get_diagram, search_diagrams, render_diagram, validate_dsl, create_diagram, patch_diagram, replace_diagram. Same key, same scopes, same 412 semantics (expectedRevision).

Claude Code:

claude mcp add --transport http archtruth https://archtruth.app/api/mcp \
  --header "Authorization: Bearer as_live_…"

Cowork / other clients (mcp.json):

{ "mcpServers": { "archtruth": { "url": "https://archtruth.app/api/mcp", "headers": { "Authorization": "Bearer as_live_…" } } } }

Suggested agent loop: get_diagram → reason over dsl → patch_diagram with expectedRevision → on 412, re-read and retry.

Editors create view-only links from the editor's Share panel (optional expiry, revocable). Anonymous viewers get the rendered diagram with SVG/PNG export — never the DSL, versions or linked CMDB records.

Machine-readable spec: OpenAPI 3.1 JSON · New to the product? Start with the user guide.

API & MCP · ArchTruth