revision-external-api
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.app
For 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/components
Create 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/components
Create 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/components
Update 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-id
Standard 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/template
Accepts 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}/dependencies
Returns 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/components
curl -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, desc
Rules:
- 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.