API Reference

The API provides endpoints for managing dependency graphs, updating node states, querying graphs and events, and configuring notifications. It operates under the /v1 prefix and uses JSON for most requests and responses, with YAML support for graph imports/exports. All namespace-scoped operations require authentication tied to a specific namespace.

The API enforces project invariants, such as valid states ("green", "yellow", "red"), no cycles in dependencies, and node IDs without slashes. State updates trigger graph computation for effective states, which propagate worst-case states transitively through dependencies. Changes may incur credits via Legendum billing in hosted mode (see self-hosted-mode.md and hosted-mode.md).

Rate limiting applies (120 requests/minute per IP). Events are audited (events-auditing.md) and purged periodically (data-purging.md).

Authentication

Most endpoints require a Bearer token in the Authorization header. Tokens are obtained via [signup](#signup) or CLI configuration (configuration.md, cli-commands.md).

Example header:

Authorization: Bearer dep_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Unauthenticated endpoints: POST /v1/signup.

Namespace-scoped endpoints verify token ownership of the namespace. See authentication.md for details.

Additionally, /ns/* paths support Basic Auth (token:dep_local for self-hosted) and return plain-text formats for CLI use.

Common Headers and Parameters

Signup

POST /v1/signup

Creates an account, links to Legendum, and emails a token. Unauthenticated.

Request body:

{
  "email": "user@example.com",
  "account_key": "lak_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}

Response (201):

{
  "message": "Account created. Your token will be emailed to you.",
  "email": "user@example.com"
}

Errors: Invalid email (400), existing account (409), Legendum link failure (502).

Namespaces

POST /v1/namespaces

Creates a namespace (lowercase alphanumeric + hyphens, ≤64 chars). Token auth (no namespace required).

Request body:

{
  "id": "my-project"
}

Response (201):

{
  "id": "my-project"
}

DELETE /v1/namespaces/:namespace

Deletes namespace and all data (nodes, edges, events, notifications). Namespace auth.

Response: 204 No Content.

Nodes

Nodes represent services or resources. Each has a state, optional label, reason, solution, default_state, meta (JSON), ttl (e.g., "30s"), and depends_on array.

GET /v1/nodes/:namespace

Lists all nodes. Namespace auth.

Response:

[
  {
    "id": "db",
    "namespace": "my-project",
    "state": "green",
    "effective_state": "green",
    "label": "PostgreSQL",
    "reason": null,
    "solution": null,
    "depends_on": [],
    "depended_on_by": ["api"],
    "default_state": null,
    "ttl": null,
    "meta": null,
    "state_changed_at": "2024-01-01T12:00:00Z",
    "updated_at": "2024-01-01T12:00:00Z"
  }
]

GET /v1/nodes/:namespace/:nodeId

Single node details. Returns 404 if missing.

PUT /v1/nodes/:namespace/:nodeId

Creates or updates node. Charges 1 credit for new nodes. Validates states, TTL, no cycles.

Request body:

{
  "label": "API Server",
  "state": "yellow",
  "default_state": "green",
  "reason": "High latency",
  "solution": "Scale up",
  "depends_on": ["db"],
  "ttl": "1h",
  "meta": {"version": "1.2.3"}
}

DELETE /v1/nodes/:namespace/:nodeId

Deletes node and edges. 204 or 404.

State Updates

PUT /v1/state/:namespace/:nodeId/:state

Shorthand for state-only updates ("green", "yellow", "red"). Headers: X-Reason, X-Solution.

Charges 1 credit per write (create or change). Updates last_state_write.

Example:

PUT /v1/state/my-project/api/red
Authorization: Bearer dep_xxx
X-Reason: Outage
X-Solution: Restart

Response: 204.

Dispatches notifications on effective state changes (self + downstream).

Graphs

GET /v1/graph/:namespace

Full graph JSON. ?format=yaml for YAML export. ?state=red filters nodes/edges.

Response:

{
  "namespace": "my-project",
  "nodes": [...],
  "edges": [{"from": "api", "to": "db"}]
}

PUT /v1/graph/:namespace

Imports YAML graph. Content-Type: application/yaml. ?prune=true removes unlisted nodes.

Errors: Namespace mismatch (400), cycles (409), insufficient funds (402).

GET /v1/graph/:namespace/:nodeId

Subgraph: node + upstream + downstream.

GET /v1/graph/:namespace/:nodeId/upstream

Transitive dependencies.

GET /v1/graph/:namespace/:nodeId/downstream

Transitive dependents.

See graph-computation.md and graph-visualization.md.

Events

GET /v1/events/:namespace, GET /v1/events/:namespace/:nodeId

State change history. Params: ?since=...&limit=100&order=desc.

Response:

{
  "events": [
    {
      "id": 1,
      "ns_id": 1,
      "node_id": "api",
      "previous_state": "green",
      "new_state": "red",
      "previous_effective_state": "green",
      "new_effective_state": "red",
      "reason": "Outage",
      "solution": "Restart",
      "created_at": "2024-01-01T12:00:00Z"
    }
  ]
}

Notifications

Manage rules for webhooks/emails on effective state changes.

GET /v1/notifications/:namespace

PUT /v1/notifications/:namespace

Request body:

{
  "id": "alert-1",
  "watch": "api",
  "on": "red",
  "url": "https://hooks.example.com/webhook",
  "email": true,
  "secret": "shh",
  "ack": true
}

DELETE /v1/notifications/:namespace/:ruleId

POST /v1/notifications/:namespace/:ruleId/ack

Unsuppresses rule.

See notifications.md.

Usage

GET /v1/usage/:namespace

Monthly stats.

Response:

{
  "email": "user@example.com",
  "namespace": "my-project",
  "period": "2024-01",
  "nodes": 5,
  "active_nodes": 3,
  "total_events": 10,
  "webhook_deliveries": 2,
  "emails_sent": 1
}

Legacy /ns Paths (CLI-Friendly)

GET /ns/:namespace (Basic Auth): Text list of nodes.

GET /ns/:namespace/:nodeId: Text node details.

Supports .json, .yaml, .svg suffixes. Auto-creates namespace in self-hosted. See deployment.md, cli-commands.md.

Recent changes