Public REST API
Caplo provides a workspace-scoped REST API for integrating scripts, ETL jobs, and other HTTP clients with your architecture repository.
Use this API when you want standard HTTP CRUD for entities, relations, and Process-owned BPMN. For AI coding agents, prefer MCP connections.
Base URL
https://app.caplo.ai/api/v1
Interactive docs (Swagger UI): /api/v1/docs
OpenAPI document: /api/v1/openapi.json
Authentication
- Sign in to Caplo as a workspace admin.
- Open Settings → API keys.
- Create a key (optionally set an expiration) and copy the secret immediately (
caplo_sk_...). Caplo only shows it once. - Send it on every request:
Authorization: Bearer caplo_sk_<prefix>_<secret>
The key is bound to one workspace. Do not send a workspace_id in the request body or query string.
Reads may send optional Caplo-Draft-Id: <draft-uuid> to resolve a draft. Mutations must send exactly one write target: Caplo-Write-Target: main or Caplo-Draft-Id: <draft-uuid>. Missing or conflicting headers return 422. A draft-targeted mutation needs the normal resource write scope plus drafts:write. Use GET /drafts/{id} for the draft name and other metadata. Publish and delete stay in the Caplo UI.
Resources
Entities
| Method | Path | Description |
|---|---|---|
GET | /entities | List/search (type, q, approved, limit, offset) |
POST | /entities | Create |
GET | /entities/{id} | Get by id (includes unapproved and soft-deleted) |
PATCH | /entities/{id} | Update name, properties, and/or approved |
DELETE | /entities/{id} | Soft-delete (cascades connected relations) |
GET | /entities/{id}/bpmn | Canonical BPMN for that Process (404 if missing, not a process, or no BPMN row) |
PUT | /entities/{id}/bpmn | Create or replace Process BPMN (last-write-wins; 404 if missing or not a process) |
PUT body:
{
"code": "<bpmn:definitions>...</bpmn:definitions>",
"entity_bindings": [
{ "bpmn_element_id": "Activity_2", "type": "application", "name": "DocuSign" }
]
}
entity_bindings is optional. code must be complete BPMN 2.0 XML, including the DI section. Put repository links only in entity_bindings for tasks, lanes, and participants. The Process must already exist. Writes are last-write-wins. GET includes existing bindings even when the linked entity is unapproved or soft-deleted. PUT unions Caplo entityRef leftovers in code, the optional entity_bindings list, and stored links for elements that still exist. An empty list does not clear links. Removing an element from code drops that element's link.
Example create:
curl -sS -X POST "https://app.caplo.ai/api/v1/entities" \
-H "Authorization: Bearer $CAPLO_API_KEY" \
-H "Caplo-Write-Target: main" \
-H "Content-Type: application/json" \
-d '{"type":"application","name":"CRM","properties":{"description":"Customer system"}}'
Drafts
| Method | Path | Description |
|---|---|---|
GET | /drafts | List drafts visible to the key |
POST | /drafts | Create (name, optional description, is_private). is_private defaults to Shared (false) |
GET | /drafts/{id} | Get one draft |
PATCH | /drafts/{id} | Update name, description, is_private, or reviewer_id. Reviewer is Shared-only; going Personal clears it. Creator is fixed. |
Requires drafts:read / drafts:write. Draft responses include creator_id, updater_id, and reviewer_id.
Relations
| Method | Path | Description |
|---|---|---|
GET | /relations | List/search (from, to, type, q, approved, limit, offset) |
POST | /relations | Create |
GET | /relations/{id} | Get by id (includes unapproved and soft-deleted) |
PATCH | /relations/{id} | Update name, properties, and/or approved |
DELETE | /relations/{id} | Soft-delete |
Example create:
curl -sS -X POST "https://app.caplo.ai/api/v1/relations" \
-H "Authorization: Bearer $CAPLO_API_KEY" \
-H "Caplo-Write-Target: main" \
-H "Content-Type: application/json" \
-d '{"from":"<entity-uuid>","to":"<entity-uuid>","type":"flows","name":"orders"}'
Metamodel discovery
| Method | Path | Description |
|---|---|---|
GET | /entity-types | Enabled entity types + writable property schemas |
GET | /entity-types/{type}/properties | Property schema for one entity type |
GET | /relation-types | Relation types + property schemas |
GET | /relation-types/{type}/properties | Property schema for one relation type |
Each property definition includes valueSchema, example, and writeHelp for the JSON write
shape. Phase in / Phase out are dateOrRange values: { "earliest": "YYYY-MM-DD", "latest": "YYYY-MM-DD" }.
Errors
Errors use a consistent JSON shape:
{
"error": {
"code": "validation_error",
"message": "Provide at least one of name, properties, or approved."
}
}
Common status codes:
401— missing/invalid/revoked/expired API key403— missing scope or workspace role permission404— resource not found (for PATCH/DELETE, also when already soft-deleted)409— uniqueness conflict (for example an already-approved entity with the same name+type). Creating an entity whose name+type matches a live unapproved row approves that existing row instead.422— invalid input or write-target headers (missing both targets, or sending both)
Draft errors use stable codes such as draft_closed, draft_forbidden, personal_in_shared, stale_head, and dangling_endpoint.
Limits and notes
- Pagination uses
limit(max 100) andoffset. - Deletes are soft deletes; they do not permanently erase rows.
- Process-owned BPMN can be read and written with
GET/PUT /entities/{id}/bpmn. That updates the canonical repository BPMN for the Process. It does not create or change a canvas shape.PUTunions XML leftovers,entity_bindings, and stored links for elements that still exist incode. Linked BPMN cards pick up the new XML the next time they load. - TLDraw diagrams, reports, and live canvas sync are not part of this API.