# API dependency map from OpenAPI specs
> Generate and maintain a diagram showing which services expose, consume, and depend on which APIs. Built from OpenAPI specs and SDK imports - kept current as services ship.
## Metadata
- **Diagram family**: `architecture`
- **Source**: OpenAPI specs / SDK imports
- **Workflow types**: scan, generate, update, validate, render, ci-cd
- **Audience**: developer, platform, agent
- **MCP tools**: `dsp_create_scene`, `dsp_apply_ops`, `dsp_validate_scene`, `dsp_render_scene`
- **HTTP endpoints**:
  - `POST /v1/scenes`
  - `POST /v1/scenes/:id/applyOps`
  - `POST /v1/scenes/:id/render`
---
---

## What this example shows

A directed graph of HTTP / SDK dependencies between services, with edge labels showing the actual endpoint or SDK call rather than abstract "depends on" arrows. The "Web App" and "Mobile App" hit the gateway, the gateway fans out to auth / users / orders / catalog APIs, internal services call each other (orders → billing, orders → users, catalog → search), and external SDK integrations (Stripe, SendGrid) sit at the edge of the graph.

## When to use it

When your platform has more than ~10 services and "who calls whom" is no longer something a single engineer holds in their head. The diagram is invaluable for: scoping deprecation work (who'd be affected if we sunset Catalog?), auditing third-party data exposure (which services hand data to which vendors?), incident scoping (when Billing is down, what else fails?), and onboarding (here's the call graph; here's the entry points).

## What the agent does

The agent scans the OpenAPI specs in your repo (and / or grep for SDK imports - `import Stripe from "stripe"`), builds the directed call graph, then applies typed operations to keep the persisted scene current. New endpoints become new edge labels; new services become nodes; deprecated endpoints disappear from the graph. The diagram is rebuilt on every push that touches an OpenAPI spec or an SDK import.

Edge labels show the actual endpoint where space allows ("POST /v1/login", "GET /users/:id") rather than abstract direction. For high-cardinality calls (e.g. dozens of REST endpoints between gateway and a single service), the agent collapses them to a representative ("REST") to keep the diagram readable.

## What the output includes

- A directed call graph with stable node positioning across runs (same service has the same on-screen location every time).
- Edge labels showing endpoint paths or SDK names - readers learn the integration shape from the diagram alone.
- External systems (Stripe, SendGrid, etc.) visually distinct via the `externalSystem` node type.
- Auto-layout via `layoutStrategy: { algorithm: "hierarchical", direction: "LR" }` - the agent never hand-positions; the engine figures it out.
- A revision history showing how the API surface evolved (which endpoints existed when).
## Agent workflow
Maintain a current diagram of which services expose, consume, and depend on which APIs by parsing OpenAPI specs and SDK imports across the repository, then patching the persisted Zindex scene each time a service ships.
**Inputs**

- Glob of OpenAPI spec files in the monorepo (e.g. services/*/openapi.yaml)
- Glob of source files that import generated SDKs (used to derive consumer→provider edges)
- Existing Zindex scene id (stored as a repo secret)
- Zindex API key with scene-write scope
**Outputs**

- Updated persisted scene with one node per service and one edge per cross-service call
- Rendered SVG showing the current API topology
- Revision diff highlighting newly added consumers / providers since the last run
- Optional: PR comment when the topology changes meaningfully (new service added, edge removed)
**Steps**

1. **Create or fetch the persisted scene** - On first run, create a scene with hierarchical LR layoutStrategy. On subsequent runs, fetch the existing scene by id to read the current revision and elements.
   _MCP: `dsp_create_scene` · HTTP: `POST /v1/scenes`_

2. **Parse OpenAPI specs** - Walk every services/*/openapi.yaml in the monorepo. Each spec becomes a service node; emit operationIds + paths so they can later become edge labels (e.g. 'POST /v1/login'). Do not parse free-text README links - the spec is the source of truth.

3. **Derive consumer→provider edges** - Scan source files for imports of generated SDKs (e.g. `import { usersClient } from '@acme/sdk-users'`). Each import is evidence that the importing service consumes the imported API. Map the SDK package name back to the spec → an edge from consumer to provider, labeled with the most-frequently-called operationId.

4. **Diff parsed topology against the persisted scene** - Compare the parsed (services, edges) tuple to what's currently in the scene. New services become createNode ops; removed services become deleteElement ops; changed labels become updateEdge ops. Always reuse stable element ids (the service name) so a renamed label stays on the same edge.
   _MCP: `dsp_get_scene` · HTTP: `GET /v1/scenes/${SCENE_ID}`_

5. **Apply the operation batch** - Send the diff as one applyOps batch with errorPolicy=allOrNothing. Reuse stable element ids - `users_api`, `orders_api`, `e_orders_users` - so renames update the existing element rather than create a duplicate.
   _MCP: `dsp_apply_ops` · HTTP: `POST /v1/scenes/${SCENE_ID}/ops`_

6. **Validate the new revision** - Confirm the topology is still valid: every edge endpoint resolves to a node, no duplicate edges between the same pair without distinct labels.
   _MCP: `dsp_validate_scene` · HTTP: `POST /v1/scenes/validate`_

7. **Render the updated diagram** - Render to SVG. The hierarchical LR layout naturally separates clients (left), gateway (centre), and provider APIs (right); cloud-icon services render icon-only and read cleanly inside the layout.
   _MCP: `dsp_render_scene` · HTTP: `POST /v1/scenes/${SCENE_ID}/render`_

8. **Publish the rendered SVG to the docs site** - Upload the rendered SVG to the docs site (or commit to the repo's docs/ directory). Optionally, when the topology diff contains added or removed services, post a Slack message to the platform channel so the team is aware of the new dependency.
## Agent prompt

Drop this into a system prompt for an MCP-connected agent.

```
You are an automated platform-documentation agent. Your job is to keep an API dependency-map diagram of an organisation's microservices in sync with the actual code, by parsing OpenAPI specs and SDK imports across the monorepo on a schedule (and on every PR that touches a service spec).

The persisted Zindex scene id is `${SCENE_ID}`; it already exists. Treat it as the canonical, mutable, immutable-revisioned source of truth for the API topology. Each run computes the smallest valid set of typed operations that move the scene from its current revision to one that matches the current code.

Workflow on every run:

1. Walk every `services/*/openapi.yaml` in the monorepo. Each spec corresponds to one service node - use the spec's `info.title` (or the directory name) as the stable element id. Capture the operationIds and paths so they can become edge labels.

2. Walk every source file in the monorepo and look for imports of generated SDK packages (`@acme/sdk-users`, `@acme/sdk-orders`, …). Each import is evidence that the importing service consumes the imported API. Build a `(consumer_service_id, provider_service_id, operationId)` tuple for the most-frequently-called operation between each pair.

3. Call `dsp_get_scene({ sceneId: "${SCENE_ID}" })` to read the current revision and elements. Diff what you parsed against what is persisted: new services → `createNode`, removed services → `deleteElement`, new edges → `createEdge`, removed edges → `deleteElement`, changed edge labels → `updateEdge`.

4. Call `dsp_apply_ops` with one batch. Set `errorPolicy: "allOrNothing"`. Reuse stable element ids - `users_api`, `orders_api`, `e_orders_billing` - so a renamed service or relabelled edge stays on the same element rather than producing a delete+create. Pass a meaningful `revisionMessage` like "add billing-api spec; new e_orders_billing edge from POST /charge".

5. Call `dsp_validate_scene` and resolve any `EDGE_LABEL_SUPPRESSED_REDUNDANT` and `LABEL_DUPLICATION_DETECTED` warnings. (`CANVAS_AUTO_EXTENDED` is informational - let the layout engine size the canvas as the topology grows.) `EDGE_COLUMN_NOT_FOUND` should not appear here; if it does, an edge is incorrectly using ER-family `column` anchors and needs `from/to.elementId` only.

6. Call `dsp_render_scene({ format: "svg", theme: "clean" })` and publish the rendered SVG to the docs site (or commit it to `docs/architecture/api-topology.svg`). The watermark stamps scene-id + revision + date, so the published artifact is traceable back to the persisted scene.

7. Call `dsp_diff_scene({ from: PREV_REVISION, to: NEW_REVISION })`. If the diff contains added or removed services (new providers or consumers), post a short Slack message to the platform channel summarising the change so the team is aware of the new cross-service dependency.

Hard rules: never hand-edit the rendered SVG; always edit the scene with `dsp_apply_ops` and re-render. Never regenerate the scene from scratch; always patch with stable ids - the topology is a long-lived, evolving graph, and stable ids are what make revision history meaningful. Treat the OpenAPI specs as the source of truth; if a spec contradicts a free-text comment elsewhere, follow the spec.
```
## Validation

Captured `POST /v1/scenes/validate` response: **valid** (0 diagnostics)

_Scene validates with no diagnostics._
## Resources
- **Canonical scene**: [/examples/api-dependency-map.scene.json](/examples/api-dependency-map.scene.json)
- **Operations envelope**: [/examples/api-dependency-map.ops.json](/examples/api-dependency-map.ops.json)
- **Workflow recipe**: [/examples/api-dependency-map.workflow.json](/examples/api-dependency-map.workflow.json)
- **Revision diff**: [/examples/api-dependency-map.diff.json](/examples/api-dependency-map.diff.json)
- **GitHub Actions workflow**: [/examples/api-dependency-map.github-actions.yml](/examples/api-dependency-map.github-actions.yml)
- **Rendered SVG**: [/examples/api-dependency-map.svg](/examples/api-dependency-map.svg)
- **Human page**: [/examples/api-dependency-map](/examples/api-dependency-map)
- **Manifest**: [/examples/index.json](/examples/index.json)
## Related examples

- [/examples/living-architecture-docs](/examples/living-architecture-docs)
- [/examples/pr-architecture-diff](/examples/pr-architecture-diff)
- [/examples/compliance-pii-flow](/examples/compliance-pii-flow)
- [/examples/request-flow-from-handler](/examples/request-flow-from-handler)