Documents
Endpoints
| Method | Path | Scope | Description |
|---|---|---|---|
| GET | /documents | documents:read | List documents |
| POST | /documents | documents:write | Create a document |
| GET | /documents/:id | documents:read | Get a document with content |
| PATCH | /documents/:id | documents:write | Update a document |
| DELETE | /documents/:id | documents:write | Soft-delete a document |
List Documents
curl "https://my.clarife.app/api/v1/documents?limit=10&offset=0" \
-H "Authorization: Bearer clrf_your_key"Query parameters:
| Param | Type | Default | Description |
|---|---|---|---|
| limit | integer | 50 | Results per page (1-100) |
| offset | integer | 0 | Number of results to skip |
| sort | string | updated_at | Sort field: updated_at, created_at, title |
| order | string | desc | Sort order: asc or desc |
| project_id | uuid | -- | Filter by project |
Response:
{
"data": [
{
"id": "d1a2b3c4-5678-90ab-cdef-1234567890ab",
"title": "Getting Started Guide",
"description": "Onboarding tutorial for new users",
"updated_at": "2026-03-20T14:00:00Z",
"created_at": "2026-03-15T10:30:00Z",
"block_count": 12,
"screenshot_count": 5,
"word_count": 450,
"visibility": "private"
}
],
"total": 1,
"limit": 10,
"offset": 0
}Create a Document
curl -X POST https://my.clarife.app/api/v1/documents \
-H "Authorization: Bearer clrf_your_key" \
-H "Content-Type: application/json" \
-d '{
"title": "API Setup Guide",
"description": "How to connect via the clarife API",
"project_id": "p1a2b3c4-5678-90ab-cdef-1234567890ab"
}'Body parameters:
| Field | Type | Required | Description |
|---|---|---|---|
| title | string | No | Document title (max 500 chars, defaults to "Untitled") |
| description | string | No | Short description (max 2000 chars) |
| content | object | No | Document content (see Content Format below) |
| project_id | uuid | No | Assign to a project |
| template | string | No | Template identifier |
| visibility | string | No | private or workspace (requires X-Workspace-Id header) |
Response (201 Created):
{
"data": {
"id": "d2b3c4d5-6789-01ab-cdef-2345678901ab",
"title": "API Setup Guide",
"created_at": "2026-03-28T12:00:00Z"
}
}Get a Document
curl https://my.clarife.app/api/v1/documents/d1a2b3c4-5678-90ab-cdef-1234567890ab \
-H "Authorization: Bearer clrf_your_key"Returns the full document including content with all blocks.
Response:
{
"data": {
"id": "d1a2b3c4-...",
"title": "Getting Started Guide",
"description": "Onboarding tutorial",
"content": {
"meta": { "version": 1, "locale": "en" },
"blocks": [
{ "type": "heading", "id": "h1-title", "sort_order": 0, "level": 1, "content": "Getting Started" },
{ "type": "text", "id": "t1-intro", "sort_order": 1, "content": "Welcome to the guide." },
{ "type": "screenshot", "id": "ss1-dashboard", "sort_order": 2, "media_id": "m1234567-...", "caption": "Dashboard view", "alignment": "center" }
]
},
"version": 4,
"block_count": 3,
"screenshot_count": 1,
"word_count": 12,
"visibility": "private",
"template": null,
"branding_id": null,
"updated_at": "2026-03-20T14:00:00Z",
"created_at": "2026-03-15T10:30:00Z"
}
}The top-level version field is the document's version number, incremented on every content change - pass it as expected_version when updating (see below).
Update a Document
curl -X PATCH https://my.clarife.app/api/v1/documents/d1a2b3c4-5678-90ab-cdef-1234567890ab \
-H "Authorization: Bearer clrf_your_key" \
-H "Content-Type: application/json" \
-d '{ "title": "Updated Title" }'All body fields are optional. Only provided fields are updated.
| Field | Type | Description |
|---|---|---|
| title | string | New title (max 500 chars) |
| description | string | New description (max 2000 chars) |
| content | object | Replace document content |
| expected_version | integer | Optional concurrency guard - the version value from GET /documents/:id (mismatch = 409 CONFLICT) |
⚠️ Warning: When updating content, you must send the full content - the blocks array replaces the existing one, and block_annotations / block_enhance_settings (if the document has them) must be sent back too, otherwise they are permanently removed. First read the current content with GET /documents/:id, modify it, and send it all back.
Optimistic concurrency (optional): pass the version value from the GET /documents/:id response as expected_version. The update then applies only if the document has not changed in the meantime - otherwise the API returns 409 with code CONFLICT and the current version number in the message. On a conflict, re-read the document, re-apply your changes to the fresh content, and retry. We recommend sending expected_version with every content update - it protects against overwriting changes saved concurrently in the editor, by another integration, or by an MCP agent.
Response (200 OK):
{
"data": {
"id": "d1a2b3c4-...",
"title": "Updated Title",
"version": 5,
"updated_at": "2026-03-28T13:00:00Z"
}
}Delete a Document
curl -X DELETE https://my.clarife.app/api/v1/documents/d1a2b3c4-5678-90ab-cdef-1234567890ab \
-H "Authorization: Bearer clrf_your_key"Documents are soft-deleted (moved to trash). They are permanently removed after 30 days.
Response (204 No Content): Empty body.
Content Format
Document content follows a flat block-based structure. Each block must include these common fields:
| Field | Type | Required | Description |
|---|---|---|---|
| type | string | Yes | Block type (see types below) |
| id | string | Yes | Unique ID within the document (e.g. "h1-title", "ss3-result") |
| sort_order | integer | Yes | Display order starting from 0 |
heading
{
"type": "heading",
"id": "h1-title",
"sort_order": 0,
"level": 1,
"content": "My Tutorial Title"
}level: 1, 2, or 3 (H1, H2, H3)content: plain text
text
{
"type": "text",
"id": "t1-intro",
"sort_order": 1,
"content": "Paragraph text here.\nUse line breaks for lists:\n• Item one\n• Item two"
}content: plain text or basic HTML (<b>,<i>,<a>,<br>)
screenshot / image
{
"type": "screenshot",
"id": "ss1-dashboard",
"sort_order": 2,
"media_id": "77b4185f-bb13-47ea-97a4-6b0d88289df1",
"caption": "Dashboard overview",
"alignment": "center"
}media_id(UUID, required): references an uploaded media file - see the Media API for the upload workflowcaption(string, optional): displayed below the imagealignment:"left","center", or"right"width(integer, optional): display width in pixels (omit for original size)
Use "image" type for non-screenshot visuals (diagrams, illustrations). Same schema as screenshot.
divider
{ "type": "divider", "id": "d1", "sort_order": 5 }No additional fields.
code
{
"type": "code",
"id": "c1-example",
"sort_order": 6,
"code": "npm install clarife",
"language": "bash"
}code(required): the code stringlanguage: syntax highlighting (e.g."python","javascript","bash","sql")
table
{
"type": "table",
"id": "tbl1",
"sort_order": 7,
"has_header": true,
"columns": [
{ "label": "Name" },
{ "label": "Role" }
],
"rows": [
["Alice", "Developer"],
["Bob", "Designer"]
]
}has_header(boolean, required): whether the column labels render as a header rowcolumns(required): one entry per column;labelis the header text, optionalwidth(px) andalign("left"|"center"|"right")rows: 2D array of cell strings - data only, headers live incolumns
Annotations and screenshot enhance settings
Besides meta and blocks, content can carry two optional objects created in the clarife editor:
block_annotations: annotation layers (arrows, boxes, blur, etc.) keyed by screenshot blockidblock_enhance_settings: screenshot frame and background styling, also keyed by blockid
You normally do not author these by hand - read them from the GET /documents/:id response and send them back unchanged when updating. Both fields are validated; a malformed structure returns 400 VALIDATION_ERROR.
⚠️ Warning: updating content replaces the whole content. If you omit block_annotations or block_enhance_settings, the annotations and screenshot styling are permanently removed.
Complete Example
Creating a document with text and a screenshot:
curl -X POST https://my.clarife.app/api/v1/documents \
-H "Authorization: Bearer clrf_your_key" \
-H "Content-Type: application/json" \
-d '{
"title": "Setup Guide",
"content": {
"meta": { "version": 1, "locale": "en" },
"blocks": [
{ "type": "heading", "id": "h1", "sort_order": 0, "level": 1, "content": "Setup Guide" },
{ "type": "text", "id": "t1", "sort_order": 1, "content": "Follow these steps to get started." },
{ "type": "screenshot", "id": "ss1", "sort_order": 2, "media_id": "77b4185f-...", "caption": "Settings screen", "alignment": "center" },
{ "type": "divider", "id": "d1", "sort_order": 3 },
{ "type": "text", "id": "t2", "sort_order": 4, "content": "You are all set!" }
]
}
}'ℹ️ Info: To add images, you must first upload them via the Media API. The 4-step workflow is: create presigned URL → upload file → confirm → add screenshot block with media_id to the document.