> Public API.
An HTTP API for reading and writing workspaces, folders, and markdown documents in your MDflow workspace. Authenticate with a Personal Access Token, get clean JSON back. Everything here is also published as a machine-readable OpenAPI 3.1 spec.
- Base URL
- https://mdflow.cz
- Auth
- Bearer token
- Rate limit
- 60 req / min
- Format
- JSON · no-store
Authentication
Every request needs a Personal Access Token. Create one in Settings — it starts with mdf_. Send it in the Authorization header on every call:
Authorization: Bearer mdf_your_token_hereA minimal request:
curl https://mdflow.cz/api/v1/folders \
-H "Authorization: Bearer mdf_your_token_here"The Authorization header accepts either token kind: a Personal Access Token (mdf_…, the simplest path for scripts and direct HTTP calls — every example here uses one), or an OAuth access token that MDflow issues when you connect it as a custom connector in Claude or ChatGPT (see the MCP docs). Either way, the owner needs MDflow Pro.
Endpoints
/api/v1/workspacesList all workspaces owned by the authenticated user, oldest first.
Request
curl https://mdflow.cz/api/v1/workspaces \
-H "Authorization: Bearer mdf_your_token_here"Response200 — array of Workspace
[
{
"id": "5d9f1c2e-8a3b-4c7d-9e10-2f4a6b8c0d12",
"name": "Personal",
"description": "Default workspace.",
"created_at": "2026-01-12T09:24:00.000Z",
"updated_at": "2026-02-03T16:40:12.000Z"
}
]/api/v1/workspacesCreate a workspace. Duplicate names are automatically disambiguated.
Request body
{
"name": "Client work",
"description": "Projects shared with clients."
}Request
curl -X POST https://mdflow.cz/api/v1/workspaces \
-H "Authorization: Bearer mdf_your_token_here" \
-H "Content-Type: application/json" \
-d '{
"name": "Client work",
"description": "Projects shared with clients."
}'Response201 — Workspace
{
"id": "6e0a2d3f-9b4c-5d8e-af21-3a5b7c9d1e23",
"name": "Client work",
"description": "Projects shared with clients.",
"created_at": "2026-02-03T17:08:24.000Z",
"updated_at": "2026-02-03T17:08:24.000Z"
}/api/v1/workspaces/{id}Update a workspace's name and/or description (send at least one). A renamed workspace is disambiguated against the others.
Parameters
| id | path · string · uuid | Workspace UUID. |
Request body
{
"name": "Client work",
"description": "Active client projects."
}Request
curl -X PATCH https://mdflow.cz/api/v1/workspaces/6e0a2d3f-9b4c-5d8e-af21-3a5b7c9d1e23 \
-H "Authorization: Bearer mdf_your_token_here" \
-H "Content-Type: application/json" \
-d '{ "description": "Active client projects." }'Response200 — Workspace
{
"id": "6e0a2d3f-9b4c-5d8e-af21-3a5b7c9d1e23",
"name": "Client work",
"description": "Active client projects.",
"created_at": "2026-02-03T17:08:24.000Z",
"updated_at": "2026-02-03T17:12:00.000Z"
}/api/v1/workspaces/{id}Delete a workspace, cascading to its folders and their documents. Returns 409 if it is the owner's last workspace.
/api/v1/foldersReturns all folders owned by the authenticated user, each with its workspace_id and full path. Pass ?workspace_id= to list only the folders in one workspace.
Parameters
| workspace_id | query · string · uuid | Optional. Only list folders in this workspace. |
Request
curl https://mdflow.cz/api/v1/folders \
-H "Authorization: Bearer mdf_your_token_here"Response200 — array of Folder
[
{
"id": "3f2504e0-4f89-41d3-9a0c-0305e82c3301",
"name": "API documentation",
"description": "Reference docs and integration notes.",
"parent_id": null,
"workspace_id": "5d9f1c2e-8a3b-4c7d-9e10-2f4a6b8c0d12",
"path": [
{ "id": "5d9f1c2e-8a3b-4c7d-9e10-2f4a6b8c0d12", "name": "Personal", "type": "workspace" },
{ "id": "3f2504e0-4f89-41d3-9a0c-0305e82c3301", "name": "API documentation", "type": "folder" }
],
"path_string": "Personal / API documentation",
"created_at": "2026-01-12T09:24:00.000Z",
"updated_at": "2026-02-03T16:40:12.000Z"
}
]/api/v1/folders/{id}Returns one folder including its full path (workspace → … → folder) and its compounded description — the labeled cascade of descriptions from the workspace down through each ancestor folder to this folder. A folder owned by another user returns 404.
Parameters
| id | path · string · uuid | Folder UUID. |
Request
curl https://mdflow.cz/api/v1/folders/7c9e6679-7425-40de-944b-e07fc1f90ae7 \
-H "Authorization: Bearer mdf_your_token_here"Response200 — FolderDetail
{
"id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
"name": "Research",
"description": "Source notes and synthesis drafts.",
"parent_id": "3f2504e0-4f89-41d3-9a0c-0305e82c3301",
"workspace_id": "5d9f1c2e-8a3b-4c7d-9e10-2f4a6b8c0d12",
"path": [
{ "id": "5d9f1c2e-8a3b-4c7d-9e10-2f4a6b8c0d12", "name": "Personal", "type": "workspace" },
{ "id": "3f2504e0-4f89-41d3-9a0c-0305e82c3301", "name": "API documentation", "type": "folder" },
{ "id": "7c9e6679-7425-40de-944b-e07fc1f90ae7", "name": "Research", "type": "folder" }
],
"path_string": "Personal / API documentation / Research",
"compounded_description": "Workspace \"Personal\": Default workspace.\n\nFolder \"API documentation\": Reference docs and integration notes.\n\nFolder \"Research\": Source notes and synthesis drafts.",
"created_at": "2026-02-03T17:08:24.000Z",
"updated_at": "2026-02-03T17:22:00.000Z"
}/api/v1/foldersCreates a folder owned by the authenticated user. If a sibling folder already uses the requested name, MDflow appends the lowest available numeric suffix. Pass parent_id to create a subfolder nested under an existing folder, or workspace_id to place a top-level folder in a specific workspace (defaults to your oldest workspace).
Request body
{
"name": "Research",
"description": "Source notes and synthesis drafts.",
"parent_id": null,
"workspace_id": "5d9f1c2e-8a3b-4c7d-9e10-2f4a6b8c0d12"
}Request
curl -X POST https://mdflow.cz/api/v1/folders \
-H "Authorization: Bearer mdf_your_token_here" \
-H "Content-Type: application/json" \
-d '{
"name": "Research",
"description": "Source notes and synthesis drafts."
}'Response201 — Folder
{
"id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
"name": "Research",
"description": "Source notes and synthesis drafts.",
"parent_id": null,
"workspace_id": "5d9f1c2e-8a3b-4c7d-9e10-2f4a6b8c0d12",
"created_at": "2026-02-03T17:08:24.000Z",
"updated_at": "2026-02-03T17:08:24.000Z"
}/api/v1/folders/{id}Updates a folder owned by the authenticated user. Provide at least one of name, description, or parent_id. Renaming or moving disambiguates the name against the destination siblings. Setting parent_id reparents the folder (null moves it to the top level); moving a folder under itself, one of its own descendants, or into a different workspace is rejected with 400.
Parameters
| id | path · string · uuid | Folder UUID. |
Request body
{
"name": "Reference",
"description": "Reference docs and integration notes.",
"parent_id": "3f2504e0-4f89-41d3-9a0c-0305e82c3301"
}Request
curl -X PATCH https://mdflow.cz/api/v1/folders/7c9e6679-7425-40de-944b-e07fc1f90ae7 \
-H "Authorization: Bearer mdf_your_token_here" \
-H "Content-Type: application/json" \
-d '{ "description": "Reference docs and integration notes." }'Response200 — Folder
{
"id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
"name": "Research",
"description": "Reference docs and integration notes.",
"parent_id": "3f2504e0-4f89-41d3-9a0c-0305e82c3301",
"workspace_id": "5d9f1c2e-8a3b-4c7d-9e10-2f4a6b8c0d12",
"created_at": "2026-02-03T17:08:24.000Z",
"updated_at": "2026-02-03T17:22:00.000Z"
}/api/v1/folders/{id}Deletes a folder owned by the authenticated user. Documents inside the folder are deleted by database cascade.
/api/v1/folders/{id}/documentsReturns documents inside the folder. A folder owned by another user returns 404. Bodies are omitted from this list.
Parameters
| id | path · string · uuid | Folder UUID. |
Request
curl https://mdflow.cz/api/v1/folders/3f2504e0-4f89-41d3-9a0c-0305e82c3301/documents \
-H "Authorization: Bearer mdf_your_token_here"Response200 — array of DocumentListItem
[
{
"id": "9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d",
"title": "Getting started",
"folder_id": "3f2504e0-4f89-41d3-9a0c-0305e82c3301",
"is_public": false,
"created_at": "2026-01-12T09:30:00.000Z",
"updated_at": "2026-02-01T11:15:42.000Z"
}
]/api/v1/documentsReturns all documents owned by the authenticated user across every folder. Document bodies are omitted from this list response. Pass ?workspace_id= to list only documents in one workspace.
Parameters
| workspace_id | query · string · uuid | List only documents in this workspace. |
Request
curl https://mdflow.cz/api/v1/documents \
-H "Authorization: Bearer mdf_your_token_here"Response200 — array of DocumentListItem
[
{
"id": "9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d",
"title": "Getting started",
"folder_id": "3f2504e0-4f89-41d3-9a0c-0305e82c3301",
"is_public": false,
"workspace_id": "5d9f1c2e-8a3b-4c7d-9e10-2f4a6b8c0d12",
"path": [
{ "id": "5d9f1c2e-8a3b-4c7d-9e10-2f4a6b8c0d12", "name": "Personal", "type": "workspace" },
{ "id": "3f2504e0-4f89-41d3-9a0c-0305e82c3301", "name": "API documentation", "type": "folder" },
{ "id": "9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d", "name": "Getting started", "type": "document" }
],
"path_string": "Personal / API documentation / Getting started",
"created_at": "2026-01-12T09:30:00.000Z",
"updated_at": "2026-02-01T11:15:42.000Z"
}
]/api/v1/documentsCreates a markdown document inside a folder owned by the authenticated user. If a sibling document already uses the requested title, MDflow appends the lowest available numeric suffix.
Request body
{
"folder_id": "3f2504e0-4f89-41d3-9a0c-0305e82c3301",
"title": "Meeting notes.md",
"body": "# Meeting notes\n\nCaptured from the browser."
}Request
curl -X POST https://mdflow.cz/api/v1/documents \
-H "Authorization: Bearer mdf_your_token_here" \
-H "Content-Type: application/json" \
-d '{
"folder_id": "3f2504e0-4f89-41d3-9a0c-0305e82c3301",
"title": "Meeting notes.md",
"body": "# Meeting notes\n\nCaptured from the browser."
}'Response201 — DocumentListItem
{
"id": "b42e6ff7-7d9a-4f25-9305-1ce41f8b7eb3",
"title": "Meeting notes.md",
"folder_id": "3f2504e0-4f89-41d3-9a0c-0305e82c3301",
"is_public": false,
"created_at": "2026-02-03T17:08:24.000Z",
"updated_at": "2026-02-03T17:08:24.000Z"
}/api/v1/documents/{id}Renames a document owned by the authenticated user. The new title is disambiguated against the other documents in the same folder. Returns the document without its body.
Parameters
| id | path · string · uuid | Document UUID. |
Request body
{
"title": "Quarterly plan.md"
}Request
curl -X PATCH https://mdflow.cz/api/v1/documents/9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d \
-H "Authorization: Bearer mdf_your_token_here" \
-H "Content-Type: application/json" \
-d '{ "title": "Quarterly plan.md" }'Response200 — DocumentListItem
{
"id": "9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d",
"title": "Quarterly plan.md",
"folder_id": "3f2504e0-4f89-41d3-9a0c-0305e82c3301",
"is_public": false,
"created_at": "2026-01-12T09:30:00.000Z",
"updated_at": "2026-02-03T17:25:00.000Z"
}/api/v1/documents/{id}Returns one document including its markdown body. A document owned by another user returns 404.
Parameters
| id | path · string · uuid | Document UUID. |
Request
curl https://mdflow.cz/api/v1/documents/9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d \
-H "Authorization: Bearer mdf_your_token_here"Response200 — Document (includes body)
{
"id": "9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d",
"title": "Getting started",
"folder_id": "3f2504e0-4f89-41d3-9a0c-0305e82c3301",
"is_public": false,
"workspace_id": "5d9f1c2e-8a3b-4c7d-9e10-2f4a6b8c0d12",
"path": [
{ "id": "5d9f1c2e-8a3b-4c7d-9e10-2f4a6b8c0d12", "name": "Personal", "type": "workspace" },
{ "id": "3f2504e0-4f89-41d3-9a0c-0305e82c3301", "name": "API documentation", "type": "folder" },
{ "id": "9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d", "name": "Getting started", "type": "document" }
],
"path_string": "Personal / API documentation / Getting started",
"compounded_description": "Workspace \"Personal\": Default workspace.\n\nFolder \"API documentation\": Reference docs and integration notes.",
"created_at": "2026-01-12T09:30:00.000Z",
"updated_at": "2026-02-01T11:15:42.000Z",
"body": "# Getting started\n\nWelcome to your workspace."
}/api/v1/documents/{id}/bodyReplaces the markdown body of one document owned by the authenticated user. Title, folder, and sharing metadata are preserved. An empty body is refused with 400 unless the request also sends confirmEmpty: true, so a client with a cleared or unloaded buffer cannot wipe a document silently.
Parameters
| id | path · string · uuid | Document UUID. |
Request body
{
"body": "# Getting started\n\nUpdated from the API."
}Request
curl -X PUT https://mdflow.cz/api/v1/documents/9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d/body \
-H "Authorization: Bearer mdf_your_token_here" \
-H "Content-Type: application/json" \
-d '{ "body": "# Getting started\n\nUpdated from the API." }'Response200 — Document
{
"id": "9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d",
"title": "Getting started",
"folder_id": "3f2504e0-4f89-41d3-9a0c-0305e82c3301",
"is_public": false,
"created_at": "2026-01-12T09:30:00.000Z",
"updated_at": "2026-02-03T17:20:00.000Z",
"body": "# Getting started\n\nUpdated from the API."
}/api/v1/documents/{id}/folderMoves one document to another folder owned by the authenticated user. Duplicate titles in the target folder are automatically disambiguated.
Parameters
| id | path · string · uuid | Document UUID. |
Request body
{
"folder_id": "7c9e6679-7425-40de-944b-e07fc1f90ae7"
}Request
curl -X PUT https://mdflow.cz/api/v1/documents/9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d/folder \
-H "Authorization: Bearer mdf_your_token_here" \
-H "Content-Type: application/json" \
-d '{ "folder_id": "7c9e6679-7425-40de-944b-e07fc1f90ae7" }'Response200 — DocumentListItem
{
"id": "9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d",
"title": "Getting started",
"folder_id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
"is_public": false,
"created_at": "2026-01-12T09:30:00.000Z",
"updated_at": "2026-02-03T17:22:00.000Z"
}/api/v1/documents/{id}/sharingSets public sharing and commenting options. MDflow generates share slugs server-side and never accepts caller-provided slugs.
Parameters
| id | path · string · uuid | Document UUID. |
Request body
{
"is_public": true,
"allow_comments": true
}Request
curl -X PUT https://mdflow.cz/api/v1/documents/9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d/sharing \
-H "Authorization: Bearer mdf_your_token_here" \
-H "Content-Type: application/json" \
-d '{ "is_public": true, "allow_comments": true }'Response200 — SharingState
{
"is_public": true,
"allow_comments": true,
"share_slug": "6J4x...",
"share_path": "/share/6J4x...",
"public_url": "https://mdflow.cz/share/6J4x..."
}/api/v1/documents/{id}Deletes one document owned by the authenticated user.
Schemas
Workspace
| Field | Type | Description |
|---|---|---|
| id | string · uuid | Unique workspace identifier. |
| name | string | Workspace name. |
| description | string | null | Free-text workspace description. |
| created_at | string · date-time | ISO 8601. |
| updated_at | string · date-time | ISO 8601. |
Folder
| Field | Type | Description |
|---|---|---|
| id | string · uuid | Unique folder identifier. |
| name | string | Folder name. |
| description | string | null | Free-text description. The primary context signal for the documents inside. |
| parent_id | string · uuid | null | Parent folder UUID, or null for a top-level folder. |
| workspace_id | string · uuid | The workspace this folder belongs to. |
| path | PathSegment[] | Full path from the workspace root down to this folder, workspace first. Returned by list and get; omitted from create and update responses. |
| path_string | string | Path segment names joined by " / ". Returned by list and get; omitted from create and update responses. |
| created_at | string · date-time | ISO 8601. |
| updated_at | string · date-time | ISO 8601. |
PathSegment
| Field | Type | Description |
|---|---|---|
| id | string · uuid | Workspace, folder, or document identifier for this segment. |
| name | string | Workspace, folder, or document name. |
| type | "workspace" | "folder" | "document" | Whether this segment is the workspace root, an ancestor folder, or the document/folder leaf itself. |
FolderDetail
All Folder fields, plus (path and path_string are always present here):| Field | Type | Description |
|---|---|---|
| compounded_description | string | Labeled cascade of descriptions from the workspace down through each ancestor folder to this folder. Empty string when nothing in the chain has a description. |
CreateFolderInput
No extra fields are accepted.| Field | Type | Description |
|---|---|---|
| name | string · 1–100 chars | Requested folder name. Trimmed and automatically disambiguated. |
| description | string · ≤ 5000 chars | Optional folder description. Empty text is stored as null. |
| parent_id | string · uuid | null | Optional parent folder UUID to create a subfolder. Omit or null for a top-level folder. |
| workspace_id | string · uuid | Optional workspace for a top-level folder. Ignored when parent_id is set. Defaults to your oldest workspace. |
PatchFolderInput
No extra fields are accepted. Provide at least one field.| Field | Type | Description |
|---|---|---|
| name | string · 1–100 chars | Optional new folder name. Trimmed and disambiguated against destination siblings. |
| description | string · ≤ 5000 chars | Optional replacement description. Empty text is stored as null. |
| parent_id | string · uuid | null | Optional destination parent folder UUID, or null to move the folder to the top level. |
CreateDocumentInput
No extra fields are accepted.| Field | Type | Description |
|---|---|---|
| folder_id | string · uuid | ID of an existing folder owned by the authenticated user. |
| title | string · 1–100 chars | Requested title. Trimmed before creation and automatically disambiguated against sibling documents. |
| body | string · ≤ 512000 bytes | Markdown document body. UTF-8 encoded content must not exceed 500 KiB. |
UpdateDocumentBodyInput
No extra fields are accepted.| Field | Type | Description |
|---|---|---|
| body | string · ≤ 512000 bytes | Replacement markdown body. UTF-8 encoded content must not exceed 500 KiB. |
MoveDocumentInput
No extra fields are accepted.| Field | Type | Description |
|---|---|---|
| folder_id | string · uuid | ID of an existing destination folder owned by the authenticated user. |
UpdateSharingInput
No extra fields are accepted. share_slug is always generated server-side.| Field | Type | Description |
|---|---|---|
| is_public | boolean | Whether the public share link is active. |
| allow_comments | boolean | Whether signed-in visitors can comment on the shared document. |
DocumentListItem
| Field | Type | Description |
|---|---|---|
| id | string · uuid | Unique document identifier. |
| title | string | Document title. |
| folder_id | string · uuid | ID of the parent folder. |
| is_public | boolean | Whether a public share link is currently active. |
| workspace_id | string · uuid | The workspace this document belongs to (via its folder). Returned by list and get; omitted from create, rename, move, and body responses. |
| path | PathSegment[] | Full path from the workspace root down to and including this document, workspace first. Returned by list and get; omitted from mutation responses. |
| path_string | string | Path segment names joined by " / ". |
| created_at | string · date-time | ISO 8601. |
| updated_at | string · date-time | ISO 8601. |
Document
All DocumentListItem fields, plus (workspace_id, path, and path_string are always present here):| Field | Type | Description |
|---|---|---|
| body | string | The full markdown document body. |
| compounded_description | string | Labeled cascade of descriptions from the workspace down through each ancestor folder to this document's folder. Empty string when nothing in the chain has a description. |
SharingState
| Field | Type | Description |
|---|---|---|
| is_public | boolean | Whether the public share link is active. |
| allow_comments | boolean | Whether signed-in visitors can comment on the shared document. |
| share_slug | string | null | Server-generated share slug, or null when sharing is off. |
| share_path | string | null | Relative share path such as /share/{slug}. |
| public_url | string | null | Absolute share URL only when the app base URL is configured. |
CreateDocumentShareInput
No extra fields are accepted.| Field | Type | Description |
|---|---|---|
| string · email | Recipient email address. Trimmed and lowercased before storage. | |
| allow_comments | boolean | Whether the recipient may comment. Optional, defaults to false (view only). |
DocumentShare
| Field | Type | Description |
|---|---|---|
| id | string · uuid | Private share identifier. Pass it to the remove-one endpoint. |
| string · email | The invited email address. | |
| allow_comments | boolean | Whether the recipient may comment. |
| status | "pending" | "accepted" | pending until the recipient signs in with the invited email, then accepted. |
| created_at | string · date-time | ISO 8601. |
| accepted_at | string · date-time | null | When the recipient accepted, or null while pending. |
Error
| Field | Type | Description |
|---|---|---|
| error | string | Human-readable error message. |
Error responses
Errors return the matching HTTP status and a JSON body shaped like the Error schema. All error responses are sent with Cache-Control: no-store.
The JSON body is malformed or fails validation.
{ "error": "Invalid request body" }Missing, malformed, invalid, or revoked bearer token.
{ "error": "Invalid bearer token" }The token is valid but its owner is not on MDflow Pro. Agent control (the REST API and MCP) requires Pro, so every endpoint returns 403 without it. Creating a document also returns 403 once the account reaches its document limit.
{ "error": "Pro plan required" }The workspace, folder, or document does not exist, or is owned by another user.
{ "error": "Document not found" }The workspace is the owner's only workspace and cannot be deleted.
{ "error": "Cannot delete your last workspace" }The token or authenticated user exceeded 60 requests/minute. Includes a Retry-After header.
{ "error": "Rate limit exceeded" }Unexpected server error.
{ "error": "Unexpected API error" }For AI agents & crawlers
- ›/openapi.json — the full OpenAPI 3.1 spec, served as JSON with open CORS.
- ›/llms.txt — a concise index of MDflow's docs for language-model agents.
- ›This page embeds
schema.org/APIReferenceJSON-LD describing the API. - ›Prefer a turnkey integration? The MDflow MCP server wraps these endpoints as MCP tools.