> 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. Team accounts have their own content API under /api/team/v1, authenticated with a Team access token — see Team API below.
- 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" }Team API
An MDflow Team account is a shared tenant with its own members, roles, workspaces, folders, and markdown documents, kept apart from any member's personal workspaces. It has its own credentials and its own endpoints under /api/team/v1: personal mdf_ tokens are rejected on Team routes, and Team tokens are rejected on the personal API. The surface is content only — membership, invitations, billing, and sharing are deliberately not exposed.
Team access tokens
Any member creates a named token on the Team's API Access page (/teams/<accountId>/api-access). It starts with mdt_, is shown once, and only a SHA-256 hash is stored. Send it in the Authorization header on every call:
Authorization: Bearer mdt_your_team_token- ›A token is bound to one Team account, granted only the workspaces picked when it was created (never workspaces added later), and capped at read-only or read-and-write.
- ›Effective access is recomputed on every request: the token grant ∩ the creator's current membership and role ∩ their current per-workspace permission ∩ the Team account's access state. Downgrading a member turns their write tokens read-only instantly; removing a member deletes their tokens.
- ›Writes need an active Team account. Owners and admins reach every workspace they selected; members reach only the selected workspaces they currently have access to.
- ›Eligibility comes from the Team account and its seat, not from the creator's personal plan — no MDflow Pro is required. Every write is attributed to the creator in the Team audit feed and version history.
A minimal request:
curl https://mdflow.cz/api/team/v1/workspaces \
-H "Authorization: Bearer mdt_your_team_token"Same base URL, JSON format, Cache-Control: no-store, and 60 requests/minute limit as the personal API. The Team API accepts only Team access tokens today; OAuth for the hosted Claude.ai and ChatGPT connectors is a planned later phase, so its 401 challenge is a bare Bearer realm="MDflow Team" without OAuth discovery metadata. Prefer tools over HTTP? The Team MCP server wraps these endpoints.
Team API — endpoints
/api/team/v1/workspacesLists the Team workspaces this token can reach, sorted by name. Each row carries the effective access_level — read or write, after intersecting the token's cap with the creator's current workspace permission — and the Team account's access state. Start here: every other Team endpoint needs a workspace, folder, or document id from this tree.
Request
curl https://mdflow.cz/api/team/v1/workspaces \
-H "Authorization: Bearer mdt_your_team_token"Response200 — array of TeamWorkspace
[
{
"id": "0f6a3b1e-2c4d-4e5f-8a9b-1c2d3e4f5a6b",
"account_id": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
"name": "Engineering",
"description": "Runbooks, architecture notes, and incident reviews.",
"created_at": "2026-08-01T09:00:00.000Z",
"updated_at": "2026-08-20T14:32:10.000Z",
"access_level": "write",
"account_access_state": "active"
}
]/api/team/v1/foldersLists folders across every Team workspace the token can read, oldest first. Pass ?workspace_id= to list only one workspace; a workspace outside the token's grant returns 404.
Parameters
| workspace_id | query · string · uuid | Optional. Only list folders in this Team workspace. |
Request
curl "https://mdflow.cz/api/team/v1/folders?workspace_id=0f6a3b1e-2c4d-4e5f-8a9b-1c2d3e4f5a6b" \
-H "Authorization: Bearer mdt_your_team_token"Response200 — array of TeamFolder
[
{
"id": "8d2f5a7c-1b3e-4f60-9a1b-2c3d4e5f6a7b",
"workspace_id": "0f6a3b1e-2c4d-4e5f-8a9b-1c2d3e4f5a6b",
"parent_id": null,
"name": "Runbooks",
"description": "Step-by-step operational procedures for production services.",
"created_at": "2026-08-01T09:05:00.000Z",
"updated_at": "2026-08-01T09:05:00.000Z"
}
]/api/team/v1/foldersCreates a folder in a Team workspace where the token has write access. A top-level folder needs workspace_id — a Team token can span several workspaces, so MDflow never guesses one and answers 400 without it. A subfolder inherits its parent's workspace (a conflicting workspace_id is a 400). Duplicate sibling names get a numeric suffix.
Request body
{
"name": "Incident playbooks",
"description": "What to do, in order, when a named alert fires.",
"parent_id": "8d2f5a7c-1b3e-4f60-9a1b-2c3d4e5f6a7b"
}Request
curl -X POST https://mdflow.cz/api/team/v1/folders \
-H "Authorization: Bearer mdt_your_team_token" \
-H "Content-Type: application/json" \
-d '{
"name": "Incident playbooks",
"description": "What to do, in order, when a named alert fires.",
"parent_id": "8d2f5a7c-1b3e-4f60-9a1b-2c3d4e5f6a7b"
}'Response201 — TeamFolder
{
"id": "c3d4e5f6-a7b8-4c9d-8e0f-1a2b3c4d5e6f",
"workspace_id": "0f6a3b1e-2c4d-4e5f-8a9b-1c2d3e4f5a6b",
"parent_id": "8d2f5a7c-1b3e-4f60-9a1b-2c3d4e5f6a7b",
"name": "Incident playbooks",
"description": "What to do, in order, when a named alert fires.",
"created_at": "2026-08-20T14:40:00.000Z",
"updated_at": "2026-08-20T14:40:00.000Z"
}/api/team/v1/folders/{id}Returns one folder with its description, parent, and workspace. A folder in a workspace the token cannot read returns 404, without revealing whether it exists.
Parameters
| id | path · string · uuid | Team folder UUID. |
Request
curl https://mdflow.cz/api/team/v1/folders/c3d4e5f6-a7b8-4c9d-8e0f-1a2b3c4d5e6f \
-H "Authorization: Bearer mdt_your_team_token"Response200 — TeamFolder
{
"id": "c3d4e5f6-a7b8-4c9d-8e0f-1a2b3c4d5e6f",
"workspace_id": "0f6a3b1e-2c4d-4e5f-8a9b-1c2d3e4f5a6b",
"parent_id": "8d2f5a7c-1b3e-4f60-9a1b-2c3d4e5f6a7b",
"name": "Incident playbooks",
"description": "What to do, in order, when a named alert fires.",
"created_at": "2026-08-20T14:40:00.000Z",
"updated_at": "2026-08-20T14:40:00.000Z"
}/api/team/v1/folders/{id}Renames, re-describes, or moves a Team folder. Provide at least one of name, description, or parent_id. Renaming or moving disambiguates the name against the destination siblings. parent_id null moves the folder to the workspace top level; a parent in another workspace returns 404, and making a folder its own parent or a descendant's child is rejected with 400. Folders never move across workspaces.
Parameters
| id | path · string · uuid | Team folder UUID. |
Request body
{
"description": "Ordered response steps for every paged alert. Start with the alert name."
}Request
curl -X PATCH https://mdflow.cz/api/team/v1/folders/c3d4e5f6-a7b8-4c9d-8e0f-1a2b3c4d5e6f \
-H "Authorization: Bearer mdt_your_team_token" \
-H "Content-Type: application/json" \
-d '{ "description": "Ordered response steps for every paged alert. Start with the alert name." }'Response200 — TeamFolder
{
"id": "c3d4e5f6-a7b8-4c9d-8e0f-1a2b3c4d5e6f",
"workspace_id": "0f6a3b1e-2c4d-4e5f-8a9b-1c2d3e4f5a6b",
"parent_id": "8d2f5a7c-1b3e-4f60-9a1b-2c3d4e5f6a7b",
"name": "Incident playbooks",
"description": "Ordered response steps for every paged alert. Start with the alert name.",
"created_at": "2026-08-20T14:40:00.000Z",
"updated_at": "2026-08-20T14:45:30.000Z"
}/api/team/v1/folders/{id}Permanently deletes a Team folder together with every subfolder and document inside it, including their images and attached files. Requires write access to the folder's workspace. The deletion is recorded in the Team audit feed under the token's creator.
/api/team/v1/folders/{id}/documentsLists the documents directly inside one Team folder, sorted by title, without bodies. An optional ?workspace_id= must match the folder's workspace; a mismatch is a 400 rather than another workspace's documents.
Parameters
| id | path · string · uuid | Team folder UUID. |
| workspace_id | query · string · uuid | Optional. Must be the folder's own workspace. |
Request
curl https://mdflow.cz/api/team/v1/folders/c3d4e5f6-a7b8-4c9d-8e0f-1a2b3c4d5e6f/documents \
-H "Authorization: Bearer mdt_your_team_token"Response200 — array of TeamDocumentListItem
[
{
"id": "4e5f6a7b-8c9d-4e0f-a1b2-3c4d5e6f7a8b",
"workspace_id": "0f6a3b1e-2c4d-4e5f-8a9b-1c2d3e4f5a6b",
"folder_id": "c3d4e5f6-a7b8-4c9d-8e0f-1a2b3c4d5e6f",
"title": "Deploy checklist",
"created_at": "2026-08-20T15:00:00.000Z",
"updated_at": "2026-08-21T08:12:45.000Z"
}
]/api/team/v1/documentsLists documents across every Team workspace the token can read, most recently updated first, without bodies. Pass ?workspace_id= to stay inside one workspace. Pass ?ids= with up to 10 comma-separated document UUIDs to fetch exactly those documents with their bodies in one request — the batch read the Team MCP server uses for topic retrieval. Ids the token cannot read are silently left out.
Parameters
| workspace_id | query · string · uuid | Optional. Only list documents in this Team workspace. |
| ids | query · string · comma-separated uuids | Optional. Up to 10 document UUIDs; the response then includes each document's body. |
Request
curl "https://mdflow.cz/api/team/v1/documents?workspace_id=0f6a3b1e-2c4d-4e5f-8a9b-1c2d3e4f5a6b" \
-H "Authorization: Bearer mdt_your_team_token"Response200 — array of TeamDocumentListItem (TeamDocument with ?ids=)
[
{
"id": "4e5f6a7b-8c9d-4e0f-a1b2-3c4d5e6f7a8b",
"workspace_id": "0f6a3b1e-2c4d-4e5f-8a9b-1c2d3e4f5a6b",
"folder_id": "c3d4e5f6-a7b8-4c9d-8e0f-1a2b3c4d5e6f",
"title": "Deploy checklist",
"created_at": "2026-08-20T15:00:00.000Z",
"updated_at": "2026-08-21T08:12:45.000Z"
}
]/api/team/v1/documentsCreates a markdown document in a Team workspace where the token has write access. Pass folder_id to file it into a folder (the folder's workspace wins; a conflicting workspace_id is a 400), or workspace_id alone to create it at the workspace root. Duplicate sibling titles get a numeric suffix. Answers 400 once the Team account reaches its 10,000-document cap.
Request body
{
"folder_id": "c3d4e5f6-a7b8-4c9d-8e0f-1a2b3c4d5e6f",
"title": "Deploy checklist",
"body": "# Deploy checklist\n\n- [ ] Announce in #ops\n- [ ] Run migrations"
}Request
curl -X POST https://mdflow.cz/api/team/v1/documents \
-H "Authorization: Bearer mdt_your_team_token" \
-H "Content-Type: application/json" \
-d '{
"folder_id": "c3d4e5f6-a7b8-4c9d-8e0f-1a2b3c4d5e6f",
"title": "Deploy checklist",
"body": "# Deploy checklist\n\n- [ ] Announce in #ops\n- [ ] Run migrations"
}'Response201 — TeamDocumentListItem
{
"id": "4e5f6a7b-8c9d-4e0f-a1b2-3c4d5e6f7a8b",
"workspace_id": "0f6a3b1e-2c4d-4e5f-8a9b-1c2d3e4f5a6b",
"folder_id": "c3d4e5f6-a7b8-4c9d-8e0f-1a2b3c4d5e6f",
"title": "Deploy checklist",
"created_at": "2026-08-20T15:00:00.000Z",
"updated_at": "2026-08-20T15:00:00.000Z"
}/api/team/v1/documents/{id}Returns one Team document including its markdown body. A document in a workspace the token cannot read returns 404.
Parameters
| id | path · string · uuid | Team document UUID. |
Request
curl https://mdflow.cz/api/team/v1/documents/4e5f6a7b-8c9d-4e0f-a1b2-3c4d5e6f7a8b \
-H "Authorization: Bearer mdt_your_team_token"Response200 — TeamDocument (includes body)
{
"id": "4e5f6a7b-8c9d-4e0f-a1b2-3c4d5e6f7a8b",
"workspace_id": "0f6a3b1e-2c4d-4e5f-8a9b-1c2d3e4f5a6b",
"folder_id": "c3d4e5f6-a7b8-4c9d-8e0f-1a2b3c4d5e6f",
"title": "Deploy checklist",
"body": "# Deploy checklist\n\n- [ ] Announce in #ops\n- [ ] Run migrations",
"created_at": "2026-08-20T15:00:00.000Z",
"updated_at": "2026-08-21T08:12:45.000Z"
}/api/team/v1/documents/{id}Retitles one Team document. The new title is disambiguated against the other documents in the same folder (or at the same workspace root). Returns the document without its body.
Parameters
| id | path · string · uuid | Team document UUID. |
Request body
{
"title": "Deploy checklist (blue/green)"
}Request
curl -X PATCH https://mdflow.cz/api/team/v1/documents/4e5f6a7b-8c9d-4e0f-a1b2-3c4d5e6f7a8b \
-H "Authorization: Bearer mdt_your_team_token" \
-H "Content-Type: application/json" \
-d '{ "title": "Deploy checklist (blue/green)" }'Response200 — TeamDocumentListItem
{
"id": "4e5f6a7b-8c9d-4e0f-a1b2-3c4d5e6f7a8b",
"workspace_id": "0f6a3b1e-2c4d-4e5f-8a9b-1c2d3e4f5a6b",
"folder_id": "c3d4e5f6-a7b8-4c9d-8e0f-1a2b3c4d5e6f",
"title": "Deploy checklist (blue/green)",
"created_at": "2026-08-20T15:00:00.000Z",
"updated_at": "2026-08-21T09:00:00.000Z"
}/api/team/v1/documents/{id}/bodyReplaces the entire markdown body of one Team document; title and folder 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 shared document silently. The edit is attributed to the token's creator in version history and the audit feed. Returns the document without its body.
Parameters
| id | path · string · uuid | Team document UUID. |
Request body
{
"body": "# Deploy checklist\n\n- [x] Announce in #ops\n- [ ] Run migrations\n- [ ] Verify canary"
}Request
curl -X PUT https://mdflow.cz/api/team/v1/documents/4e5f6a7b-8c9d-4e0f-a1b2-3c4d5e6f7a8b/body \
-H "Authorization: Bearer mdt_your_team_token" \
-H "Content-Type: application/json" \
-d '{ "body": "# Deploy checklist\n\n- [x] Announce in #ops\n- [ ] Run migrations\n- [ ] Verify canary" }'Response200 — TeamDocumentListItem
{
"id": "4e5f6a7b-8c9d-4e0f-a1b2-3c4d5e6f7a8b",
"workspace_id": "0f6a3b1e-2c4d-4e5f-8a9b-1c2d3e4f5a6b",
"folder_id": "c3d4e5f6-a7b8-4c9d-8e0f-1a2b3c4d5e6f",
"title": "Deploy checklist",
"created_at": "2026-08-20T15:00:00.000Z",
"updated_at": "2026-08-21T09:05:12.000Z"
}/api/team/v1/documents/{id}/folderMoves one Team document into another folder of the same workspace, or to the workspace root with folder_id null. A destination folder in another workspace returns 404 — documents never change workspace. Duplicate titles at the destination are disambiguated.
Parameters
| id | path · string · uuid | Team document UUID. |
Request body
{
"folder_id": "8d2f5a7c-1b3e-4f60-9a1b-2c3d4e5f6a7b"
}Request
curl -X PUT https://mdflow.cz/api/team/v1/documents/4e5f6a7b-8c9d-4e0f-a1b2-3c4d5e6f7a8b/folder \
-H "Authorization: Bearer mdt_your_team_token" \
-H "Content-Type: application/json" \
-d '{ "folder_id": "8d2f5a7c-1b3e-4f60-9a1b-2c3d4e5f6a7b" }'Response200 — TeamDocumentListItem
{
"id": "4e5f6a7b-8c9d-4e0f-a1b2-3c4d5e6f7a8b",
"workspace_id": "0f6a3b1e-2c4d-4e5f-8a9b-1c2d3e4f5a6b",
"folder_id": "8d2f5a7c-1b3e-4f60-9a1b-2c3d4e5f6a7b",
"title": "Deploy checklist",
"created_at": "2026-08-20T15:00:00.000Z",
"updated_at": "2026-08-21T09:10:00.000Z"
}/api/team/v1/documents/{id}Permanently deletes one Team document with its images and attached files. Requires write access to the document's workspace. Recorded in the Team audit feed under the token's creator.
Team API — schemas
Team objects are flat: no path, path_string, compounded_description, or is_public. Documents may live at the workspace root, so folder_id is nullable.
TeamWorkspace
| Field | Type | Description |
|---|---|---|
| id | string · uuid | Unique workspace identifier. |
| account_id | string · uuid | The Team account this workspace belongs to. |
| name | string | Workspace name. |
| description | string | null | Free-text workspace description. |
| access_level | "read" | "write" | The token's effective access in this workspace right now: its cap intersected with the creator's current permission. |
| account_access_state | "setup" | "active" | "grace" | "read_only" | "deleting" | The Team account's lifecycle state. Writes succeed only while it is active. |
| created_at | string · date-time | ISO 8601. |
| updated_at | string · date-time | ISO 8601. |
TeamFolder
| Field | Type | Description |
|---|---|---|
| id | string · uuid | Unique folder identifier. |
| workspace_id | string · uuid | The Team workspace this folder belongs to. Never changes. |
| parent_id | string · uuid | null | Parent folder UUID, or null for a top-level folder. |
| name | string | Folder name. |
| description | string | null | Free-text description. The primary retrieval signal for the documents inside. |
| created_at | string · date-time | ISO 8601. |
| updated_at | string · date-time | ISO 8601. |
CreateTeamFolderInput
No extra fields are accepted.| Field | Type | Description |
|---|---|---|
| name | string · 1–100 chars | Requested folder name. Trimmed and automatically disambiguated. |
| description | string · ≤ 5000 chars | null | Optional folder description. Empty text is stored as null. |
| parent_id | string · uuid | null | Optional parent folder UUID for a subfolder; the parent's workspace is used. |
| workspace_id | string · uuid | Team workspace for a top-level folder. Required when parent_id is not set; must match the parent's workspace when it is. |
PatchTeamFolderInput
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 | null | Optional replacement description. Empty text or null clears it; an absent key leaves it untouched. |
| parent_id | string · uuid | null | Optional destination parent in the same workspace, or null for the workspace top level. |
TeamDocumentListItem
| Field | Type | Description |
|---|---|---|
| id | string · uuid | Unique document identifier. |
| workspace_id | string · uuid | The Team workspace this document belongs to. Never changes. |
| folder_id | string · uuid | null | Containing folder, or null for a document at the workspace root. |
| title | string | Document title. |
| created_at | string · date-time | ISO 8601. |
| updated_at | string · date-time | ISO 8601. |
TeamDocument
All TeamDocumentListItem fields, plus:| Field | Type | Description |
|---|---|---|
| body | string | The full markdown document body. Returned by get and by the ?ids= batch list; every mutation returns the item without it. |
CreateTeamDocumentInput
No extra fields are accepted.| Field | Type | Description |
|---|---|---|
| title | string · 1–100 chars | Requested title. Trimmed and disambiguated against sibling documents. |
| body | string · ≤ 512000 bytes | Markdown document body. UTF-8 encoded content must not exceed 500 KiB. |
| folder_id | string · uuid | null | Optional folder to create the document in; the folder's workspace is used. Omit or null for the workspace root. |
| workspace_id | string · uuid | Team workspace for a root document. Required when folder_id is not set; must match the folder's workspace when it is. |
UpdateTeamDocumentBodyInput
No extra fields are accepted.| Field | Type | Description |
|---|---|---|
| body | string · ≤ 512000 bytes | Replacement markdown body. UTF-8 encoded content must not exceed 500 KiB. |
| confirmEmpty | boolean | Must be true when body is an empty string; otherwise an empty body is refused with 400. |
MoveTeamDocumentInput
No extra fields are accepted.| Field | Type | Description |
|---|---|---|
| folder_id | string · uuid | null | Destination folder in the document's own workspace, or null for the workspace root. The key is required. |
Team API — error responses
Same Error shape and Cache-Control: no-store as the personal API. 401 and 403 bodies add a message with Team token guidance. What differs is the meaning of 403 and 404: they reflect the token's live, per-workspace access rather than a plan.
The JSON body is malformed or fails validation; a top-level folder or root document was created without workspace_id; workspace_id contradicts the parent folder; an empty body was sent without confirmEmpty; or the Team account is at its 10,000-document cap.
{ "error": "workspace_id is required" }Missing, malformed, invalid, or revoked Team access token — including a personal mdf_ token sent to a Team route, and a token whose creator has left the team. The challenge is WWW-Authenticate: Bearer realm="MDflow Team"; the body carries a message with setup guidance.
{ "error": "Invalid bearer token", "message": "Authenticate with an MDflow Team access token …" }The token is valid but the operation exceeds its effective access: a write from a read-only token or from a creator whose workspace permission is read-only, a write while the Team account is not active (in setup, grace, or read-only), or any request while the account is being deleted. No Pro plan is involved — eligibility comes from the Team seat.
{ "error": "Write access required", "message": "Authenticate with an MDflow Team access token …" }The workspace is outside the token's grant, or the folder, parent folder, or document does not exist in a workspace the token can read. MDflow never reveals whether the object exists elsewhere.
{ "error": "Workspace not found" }The token, or the creator across all their Team tokens, exceeded 60 requests/minute. Includes a Retry-After header.
{ "error": "Rate limit exceeded" }Unexpected server error, or the live membership lookup failed — retry rather than discarding the token.
{ "error": "Could not verify team access" }For AI agents & crawlers
- ›/openapi.json — the full OpenAPI 3.1 spec covering both the personal and the Team API, 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.