Manages architecture components, diagrams, attributes, tags, and templates via the Revision External API. Triggers when Revision API, architecture components, C4 diagrams, or syncing architecture data with Revision are mentioned.
Resources
1Install
npx skillscat add revision-org/revision-skills/revision-external-api Install via the SkillsCat registry.
Revision External API
REST API for managing architecture documentation in Revision workspaces.
Prerequisites
Before making any API calls, the user must provide two things:
- Organization URL: Each organization has its own subdomain, e.g.
https://acme-company.revision.app/. This is the base URL for all API requests. Always ask the user for their organization URL — there is no default. - API key: A Bearer token from the workspace settings.
Authentication
All requests require a Bearer token (API key from workspace settings):
Authorization: Bearer <api-key>Base URL
The base URL is the organization's own Revision URL. Every organization has a unique subdomain:
https://{organization}.revision.appFor example: https://acme-company.revision.app
Important: Do not use a generic URL. Always use the organization-specific subdomain provided by the user.
Resources
| Resource | Endpoints | Description |
|---|---|---|
| Components | CRUD + batch upsert + filter | Architecture components (services, databases, etc.) |
| Diagrams | CRUD + batch upsert + filter | Architecture diagrams with component instances, relations, textareas |
| Attributes | CRUD + batch upsert | Custom attribute definitions on components |
| Tags | CRUD + batch upsert | Tags for categorizing diagrams |
| Types | Read-only | Component type definitions |
| Template | POST | Bulk sync of components + diagrams in a single transaction |
Quick Start
List components
curl -H "Authorization: Bearer $API_KEY" \
https://acme-company.revision.app/api/external/componentsCreate a component
curl -X POST -H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{"name": "User Service", "state": "ACTIVE"}' \
https://acme-company.revision.app/api/external/componentsCreate a component with a predictable ID
curl -X POST -H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{"id": "user-service", "name": "User Service", "state": "ACTIVE"}' \
https://acme-company.revision.app/api/external/componentsUpdate a component
curl -X PATCH -H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{"name": "User Service", "state": "ACTIVE", "desc": "Handles user auth"}' \
https://acme-company.revision.app/api/external/components/component-idStandard CRUD Pattern
Every resource (components, diagrams, attributes, tags) follows the same pattern:
| Method | Path | Action |
|---|---|---|
| GET | /api/external/{resource} |
List all (with optional query filters on components, diagrams, types) |
| POST | /api/external/{resource} |
Create (single item) |
| GET | /api/external/{resource}/{id} |
Get by ID |
| PATCH | /api/external/{resource}/{id} |
Update by ID |
| PATCH | /api/external/{resource}/upsert-batch |
Batch upsert (items with id are updated, without are created) |
Note: DELETE endpoints exist but are not yet implemented (return 501).
ID behavior: If you provide an id when creating, that exact ID is used (predictable). If you omit id, one is auto-generated. Providing a predictable id is useful when you need to reference the resource elsewhere (e.g. a component's id in a component instance's componentId).
Create requests accept a single object (not an array). Returns 201 on success.
Batch upsert is the most powerful pattern: send items with id to update, without id to create, all in one request.
Component Schema
{
"id": "string",
"name": "string",
"state": "DRAFT | ACTIVE | ARCHIVED",
"desc": "string | null",
"inlineDesc": false,
"typeId": "string | null",
"apiContext": "string",
"attributes": [{ "id": "string", "value": "boolean | number | string | null" }],
"linksTo": ["diagram-id-1", "diagram-id-2"]
}id: Optional on create — provide it for a predictable ID, omit for auto-generatedapiContext: Optional label to group related imports (defaults to current UTC timestamp if omitted)linksTo: Array of diagram IDs this component links toattributes: Component attribute values (reference attribute definitions byid)
Diagram Schema
{
"id": "string",
"name": "string",
"state": "DRAFT | ACTIVE | ARCHIVED",
"url": "string",
"desc": "string | null",
"level": "C0 | C1 | C2 | C3 | C4 | D1 | P0 | null",
"tags": ["tag-id-1"],
"apiContext": "string",
"componentInstances": [],
"relations": [],
"textareas": []
}Diagram Levels
| Level | Meaning |
|---|---|
| C0 | Landscape |
| C1 | System Context |
| C2 | Container |
| C3 | Component |
| C4 | Code |
| D1 | Deployment |
| P0 | Process |
Component Instances
A component is part of the architecture model — a reusable entity that can be referenced across many diagrams. A component instance is a visual placeholder on a diagram. It can optionally link to a component via componentId, but it doesn't have to — unlinked instances are just standalone placeholders with a name and type.
Two types:
Important: position, width, and height are all optional. When omitted, Revision will automatically lay out and size the instances. Prefer omitting them unless the user explicitly asks for specific positioning or sizing — auto-layout produces better results.
Non-container (default):
{
"ref": "unique-ref",
"componentId": "component-id | null",
"parent": "container-ref",
"isContainer": false,
"placeholder": { "text": "Name", "typeId": "type-id" }
}Container (groups other instances):
{
"ref": "unique-ref",
"componentId": "component-id | null",
"isContainer": true,
"placeholder": { "text": "Name", "typeId": "type-id" }
}refis required and must be unique within the diagramcomponentIdlinks the instance to a component definition (null for placeholders)- Non-containers can reference a
parentcontainer via the container'sref - Containers cannot have a parent
position,width,heightare optional — omit them to let Revision auto-layout and auto-size
Relations
Directed edges between component instances:
{
"fromRef": "instance-ref-1",
"toRef": "instance-ref-2",
"label": "string | null",
"desc": "string | null",
"linksTo": ["diagram-id"]
}Textareas
Free text on diagrams:
{
"position": { "x": 100, "y": 100 },
"width": 300,
"text": "string | null"
}Attribute Schema
Custom fields on components:
{
"id": "string",
"name": "string",
"desc": "string | null",
"type": "STRING | NUMBER | BOOLEAN | LINK | USERLIST | LIST",
"list": ["option1", "option2"],
"forTypes": ["type-id-1"],
"required": false,
"apiContext": "string"
}listis only valid whentypeisLIST(and required for LIST)forTypes: Restrict attribute to specific component types
Tag Schema
{
"id": "string",
"name": "string",
"desc": "string | null",
"color": "gray | red | orange | yellow | green | blue | purple",
"apiContext": "string"
}Type Schema (Read-Only)
{
"id": "string",
"name": "string"
}Types are managed in the Revision UI. List via GET /api/external/types. Supports optional name query parameter for filtering.
Template Sync
Bulk sync components and diagrams in a single transaction:
curl -X POST -H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{"components": [...], "diagrams": [...]}' \
https://acme-company.revision.app/api/external/templateAccepts both JSON and YAML. Components and diagrams follow their standard schemas.
Filtering & Dependencies
Filtering Components
GET /api/external/components?name=...&typeId=...&tagId=...&attributeId=...&attributeValue=...&state=...All filters optional. attributeValue requires attributeId.
Filtering Diagrams
GET /api/external/diagrams?componentId=...&tagId=...&name=...&level=...&state=...All filters optional.
Filtering Types
GET /api/external/types?name=...Component Dependencies
GET /api/external/components/{id}/dependenciesReturns DependencySearchResult[] — upstream and downstream direct dependencies for a component.
Workflow: Create a Diagram with Components
A typical end-to-end flow: search for duplicates, create components, then create a diagram that references them.
Search for existing duplicates — MUST do this before creating anything:
- For each component you plan to create, search by name:
GET /api/external/components?name=<name> - For the diagram, search by name:
GET /api/external/diagrams?name=<name> - If matches are found → ask the user whether to reuse the existing resource or create a new one
- If the user chooses to reuse → use the existing resource's
idinstead of creating a new one - If no matches → proceed to create
- Skip ONLY when the user explicitly says "create a new..." or "update the existing..."
- For each component you plan to create, search by name:
List types to find the right
typeIdvalues:
curl -H "Authorization: Bearer $API_KEY" \
https://acme-company.revision.app/api/external/types- Create components (skip any that the user chose to reuse from step 1):
curl -X POST -H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{"id": "user-service", "name": "User Service", "state": "ACTIVE"}' \
https://acme-company.revision.app/api/external/componentscurl -X POST -H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{"id": "user-db", "name": "User Database", "state": "ACTIVE"}' \
https://acme-company.revision.app/api/external/components- Create a diagram with component instances and a relation:
curl -X POST -H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "User Service Context",
"level": "C2",
"state": "ACTIVE",
"componentInstances": [
{ "ref": "us", "componentId": "user-service" },
{ "ref": "udb", "componentId": "user-db" }
],
"relations": [
{ "fromRef": "us", "toRef": "udb", "label": "Reads/writes" }
]
}' \
https://acme-company.revision.app/api/external/diagrams- Verify by fetching the diagram back:
curl -H "Authorization: Bearer $API_KEY" \
https://acme-company.revision.app/api/external/diagrams/<returned-id>For bulk operations, use the template endpoint to sync everything in a single transaction instead.
Output Summary
After every mutation (create, update, batch upsert, or template sync), print a summary that clearly separates what was created from what was updated.
Format:
Created:
- Component "User Service" (id: user-service)
- Diagram "System Context" (id: system-context)
Updated:
- Component "Auth Service" (id: auth-service) — updated name, descRules:
- Use Created for POST (201) responses and batch upsert items that had no
idprovided - Use Updated for PATCH (200) responses and batch upsert items that had an
idprovided - Always include the resource type, name, and ID
- For updates, briefly note which fields changed
- Omit a section if it's empty (e.g. don't print "Updated:" if nothing was updated)
Error Responses
All errors return:
{ "error": "description" }| Status | Meaning |
|---|---|
| 400 | Validation error |
| 401 | Missing or invalid API key |
| 404 | Resource not found |
| 405 | Method not allowed |
| 501 | Not implemented (e.g. DELETE endpoints) |
Error Recovery
When an API call fails:
- 401: Confirm the API key is correct and the Authorization header uses
Bearerprefix. - 400: Read the
errorfield — it describes the validation issue. Fix the request body and retry. - 404: Verify the resource ID. Use the list endpoint (
GET /api/external/{resource}) to confirm the resource exists. - 501: DELETE is not implemented. Use PATCH to set
state: "ARCHIVED"instead.
Always verify mutations by fetching the resource back after create/update to confirm the change took effect.
Full OpenAPI Spec
For the complete OpenAPI 3.0.3 specification with all request/response schemas, see OPENAPI.md.