{
  "openapi": "3.1.0",
  "info": {
    "title": "MDflow Public API",
    "version": "1.0.0",
    "description": "HTTP API for reading and writing folders and markdown documents in an MDflow workspace. Authenticate with a Personal Access Token using the Authorization header."
  },
  "servers": [
    {
      "url": "https://mdflow.cz",
      "description": "Production"
    },
    {
      "url": "http://localhost:3000",
      "description": "Local development"
    }
  ],
  "security": [
    {
      "personalAccessToken": []
    }
  ],
  "paths": {
    "/api/v1/folders": {
      "get": {
        "operationId": "listFolders",
        "summary": "List folders",
        "description": "Returns all folders owned by the authenticated user.",
        "tags": [
          "Folders"
        ],
        "responses": {
          "200": {
            "description": "Folder list.",
            "headers": {
              "Cache-Control": {
                "$ref": "#/components/headers/NoStore"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Folder"
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/WorkspaceNotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      },
      "post": {
        "operationId": "createFolder",
        "summary": "Create a folder",
        "description": "Creates a folder owned by the authenticated user. Duplicate sibling names are automatically disambiguated.",
        "tags": [
          "Folders"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateFolderInput"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created folder.",
            "headers": {
              "Cache-Control": {
                "$ref": "#/components/headers/NoStore"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Folder"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "The parent folder (parent_id) or the target workspace (workspace_id) was not found or is not owned by the authenticated user.",
            "headers": {
              "Cache-Control": {
                "$ref": "#/components/headers/NoStore"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "parentFolderNotFound": {
                    "value": {
                      "error": "Parent folder not found"
                    }
                  },
                  "workspaceNotFound": {
                    "value": {
                      "error": "Workspace not found"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/api/v1/folders/{id}/documents": {
      "get": {
        "operationId": "listFolderDocuments",
        "summary": "List documents in a folder",
        "description": "Returns documents owned by the authenticated user inside the specified folder. A folder owned by another user returns 404.",
        "tags": [
          "Folders",
          "Documents"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/FolderId"
          }
        ],
        "responses": {
          "200": {
            "description": "Document list.",
            "headers": {
              "Cache-Control": {
                "$ref": "#/components/headers/NoStore"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/DocumentListItem"
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/FolderNotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/api/v1/folders/{id}": {
      "get": {
        "operationId": "getFolder",
        "summary": "Get a folder",
        "description": "Returns one folder owned by the authenticated user, 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.",
        "tags": [
          "Folders"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/FolderId"
          }
        ],
        "responses": {
          "200": {
            "description": "Folder details.",
            "headers": {
              "Cache-Control": {
                "$ref": "#/components/headers/NoStore"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FolderDetail"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/FolderNotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      },
      "patch": {
        "operationId": "updateFolder",
        "summary": "Update a folder",
        "description": "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.",
        "tags": [
          "Folders"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/FolderId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PatchFolderInput"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated folder.",
            "headers": {
              "Cache-Control": {
                "$ref": "#/components/headers/NoStore"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Folder"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/FolderNotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      },
      "delete": {
        "operationId": "deleteFolder",
        "summary": "Delete a folder",
        "description": "Deletes a folder owned by the authenticated user. Documents inside the folder are deleted by database cascade.",
        "tags": [
          "Folders"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/FolderId"
          }
        ],
        "responses": {
          "204": {
            "$ref": "#/components/responses/Deleted"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/FolderNotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/api/v1/documents": {
      "get": {
        "operationId": "listDocuments",
        "summary": "List documents",
        "description": "Returns all documents owned by the authenticated user across folders, optionally filtered to a single workspace with `?workspace_id=`. Document bodies are omitted from this list response.",
        "tags": [
          "Documents"
        ],
        "parameters": [
          {
            "name": "workspace_id",
            "in": "query",
            "required": false,
            "description": "List only documents whose folder belongs to this workspace.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Document list.",
            "headers": {
              "Cache-Control": {
                "$ref": "#/components/headers/NoStore"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/DocumentListItem"
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/WorkspaceNotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      },
      "post": {
        "operationId": "createDocument",
        "summary": "Create a document",
        "description": "Creates a markdown document inside a folder owned by the authenticated user. Duplicate sibling titles are automatically disambiguated.",
        "tags": [
          "Documents"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateDocumentInput"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created document.",
            "headers": {
              "Cache-Control": {
                "$ref": "#/components/headers/NoStore"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DocumentListItem"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/FolderNotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/api/v1/documents/{id}": {
      "get": {
        "operationId": "getDocument",
        "summary": "Get a document",
        "description": "Returns one document owned by the authenticated user, including its markdown body. A document owned by another user returns 404.",
        "tags": [
          "Documents"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/DocumentId"
          }
        ],
        "responses": {
          "200": {
            "description": "Document details.",
            "headers": {
              "Cache-Control": {
                "$ref": "#/components/headers/NoStore"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Document"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/DocumentNotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      },
      "patch": {
        "operationId": "renameDocument",
        "summary": "Rename a document",
        "description": "Renames a document owned by the authenticated user. The new title is disambiguated against the other documents in the same folder.",
        "tags": [
          "Documents"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/DocumentId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PatchDocumentInput"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated document (without body).",
            "headers": {
              "Cache-Control": {
                "$ref": "#/components/headers/NoStore"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DocumentListItem"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/DocumentNotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      },
      "delete": {
        "operationId": "deleteDocument",
        "summary": "Delete a document",
        "description": "Deletes one document owned by the authenticated user.",
        "tags": [
          "Documents"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/DocumentId"
          }
        ],
        "responses": {
          "204": {
            "$ref": "#/components/responses/Deleted"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/DocumentNotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/api/v1/documents/{id}/body": {
      "put": {
        "operationId": "updateDocumentBody",
        "summary": "Overwrite document body",
        "description": "Replaces the markdown body of one document owned by the authenticated user while preserving metadata.",
        "tags": [
          "Documents"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/DocumentId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateDocumentBodyInput"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated document.",
            "headers": {
              "Cache-Control": {
                "$ref": "#/components/headers/NoStore"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Document"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/DocumentNotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/api/v1/documents/{id}/folder": {
      "put": {
        "operationId": "moveDocument",
        "summary": "Move a document",
        "description": "Moves one document to another folder owned by the authenticated user. Duplicate target-folder titles are automatically disambiguated.",
        "tags": [
          "Documents"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/DocumentId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/MoveDocumentInput"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Moved document.",
            "headers": {
              "Cache-Control": {
                "$ref": "#/components/headers/NoStore"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DocumentListItem"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/DocumentNotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/api/v1/documents/{id}/sharing": {
      "put": {
        "operationId": "updateDocumentSharing",
        "summary": "Update document sharing",
        "description": "Sets public sharing and commenting options for one document owned by the authenticated user. Share slugs are generated server-side.",
        "tags": [
          "Documents"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/DocumentId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateSharingInput"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated sharing state.",
            "headers": {
              "Cache-Control": {
                "$ref": "#/components/headers/NoStore"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SharingState"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/DocumentNotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/api/v1/documents/{id}/shares": {
      "get": {
        "operationId": "listDocumentShares",
        "summary": "List private shares",
        "description": "Returns the people a document owned by the authenticated user is privately shared with. Revoked shares are omitted.",
        "tags": [
          "Documents"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/DocumentId"
          }
        ],
        "responses": {
          "200": {
            "description": "Private share list.",
            "headers": {
              "Cache-Control": {
                "$ref": "#/components/headers/NoStore"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/DocumentShare"
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/DocumentNotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      },
      "post": {
        "operationId": "addDocumentShare",
        "summary": "Share a document privately",
        "description": "Privately shares a document owned by the authenticated user with one email address. Re-posting the same email updates its commenting permission. No invitation email is sent; the invitee gains access the next time they sign in with that email.",
        "tags": [
          "Documents"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/DocumentId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateDocumentShareInput"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created or updated private share.",
            "headers": {
              "Cache-Control": {
                "$ref": "#/components/headers/NoStore"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DocumentShare"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/DocumentNotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      },
      "delete": {
        "operationId": "removeAllDocumentShares",
        "summary": "Remove all private shares",
        "description": "Revokes every private share on a document owned by the authenticated user. Idempotent.",
        "tags": [
          "Documents"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/DocumentId"
          }
        ],
        "responses": {
          "204": {
            "$ref": "#/components/responses/Deleted"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/DocumentNotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/api/v1/documents/{id}/shares/{shareId}": {
      "delete": {
        "operationId": "removeDocumentShare",
        "summary": "Remove one private share",
        "description": "Revokes one private share on a document owned by the authenticated user. A share id that does not belong to this document returns 404.",
        "tags": [
          "Documents"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/DocumentId"
          },
          {
            "$ref": "#/components/parameters/ShareId"
          }
        ],
        "responses": {
          "204": {
            "$ref": "#/components/responses/Deleted"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/ShareNotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/api/v1/workspaces": {
      "get": {
        "operationId": "listWorkspaces",
        "summary": "List workspaces",
        "description": "Returns all workspaces owned by the authenticated user, oldest first.",
        "tags": [
          "Workspaces"
        ],
        "responses": {
          "200": {
            "description": "Workspace list.",
            "headers": {
              "Cache-Control": {
                "$ref": "#/components/headers/NoStore"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Workspace"
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      },
      "post": {
        "operationId": "createWorkspace",
        "summary": "Create a workspace",
        "description": "Creates a workspace owned by the authenticated user. Duplicate names are automatically disambiguated.",
        "tags": [
          "Workspaces"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateWorkspaceInput"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created workspace.",
            "headers": {
              "Cache-Control": {
                "$ref": "#/components/headers/NoStore"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Workspace"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/api/v1/workspaces/{id}": {
      "patch": {
        "operationId": "updateWorkspace",
        "summary": "Update a workspace",
        "description": "Updates the name and/or description of a workspace owned by the authenticated user. Provide at least one field. A renamed workspace is disambiguated against the other workspaces.",
        "tags": [
          "Workspaces"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/WorkspaceId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateWorkspaceInput"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated workspace.",
            "headers": {
              "Cache-Control": {
                "$ref": "#/components/headers/NoStore"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Workspace"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/WorkspaceNotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      },
      "delete": {
        "operationId": "deleteWorkspace",
        "summary": "Delete a workspace",
        "description": "Deletes a workspace owned by the authenticated user, cascading to its folders and their documents. The owner's only remaining workspace cannot be deleted.",
        "tags": [
          "Workspaces"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/WorkspaceId"
          }
        ],
        "responses": {
          "204": {
            "$ref": "#/components/responses/Deleted"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/WorkspaceNotFound"
          },
          "409": {
            "$ref": "#/components/responses/CannotDeleteLastWorkspace"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "personalAccessToken": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "PAT",
        "description": "Use an MDflow Personal Access Token in the form `Authorization: Bearer mdf_...`."
      }
    },
    "parameters": {
      "FolderId": {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Folder UUID.",
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      },
      "DocumentId": {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Document UUID.",
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      },
      "ShareId": {
        "name": "shareId",
        "in": "path",
        "required": true,
        "description": "Private share UUID.",
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      },
      "WorkspaceId": {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Workspace UUID.",
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      }
    },
    "headers": {
      "NoStore": {
        "description": "API responses are not cacheable.",
        "schema": {
          "type": "string",
          "const": "no-store"
        }
      },
      "RetryAfter": {
        "description": "Seconds to wait before retrying after a rate-limit response.",
        "schema": {
          "type": "integer",
          "minimum": 1
        }
      },
      "WwwAuthenticate": {
        "description": "RFC 6750 Bearer challenge carrying a `resource_metadata` parameter (RFC 9728) that points to `/.well-known/oauth-protected-resource` for OAuth discovery. `Bearer realm=\"MDflow\", resource_metadata=\"…\"` when credentials are missing, or one that also includes `error=\"invalid_token\"` with an `error_description` when a token was rejected.",
        "schema": {
          "type": "string"
        }
      }
    },
    "responses": {
      "BadRequest": {
        "description": "Request body was malformed or failed validation.",
        "headers": {
          "Cache-Control": {
            "$ref": "#/components/headers/NoStore"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "examples": {
              "invalidRequestBody": {
                "value": {
                  "error": "Invalid request body"
                }
              }
            }
          }
        }
      },
      "Unauthorized": {
        "description": "Missing, malformed, invalid, or revoked bearer token. The body includes a `message` field with guidance for authenticating, and the response carries a `WWW-Authenticate` challenge.",
        "headers": {
          "Cache-Control": {
            "$ref": "#/components/headers/NoStore"
          },
          "WWW-Authenticate": {
            "$ref": "#/components/headers/WwwAuthenticate"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "examples": {
              "missingToken": {
                "value": {
                  "error": "Missing or malformed bearer token",
                  "message": "Authenticate with OAuth (in Claude or ChatGPT connectors, add https://mdflow.cz/api/mcp and complete the sign-in prompt) or with an MDflow Personal Access Token (send an 'Authorization: Bearer mdf_...' header, created at https://mdflow.cz/settings). Requires an MDflow Pro account. Documentation: https://mdflow.cz/docs/api"
                }
              },
              "invalidToken": {
                "value": {
                  "error": "Invalid bearer token",
                  "message": "Authenticate with OAuth (in Claude or ChatGPT connectors, add https://mdflow.cz/api/mcp and complete the sign-in prompt) or with an MDflow Personal Access Token (send an 'Authorization: Bearer mdf_...' header, created at https://mdflow.cz/settings). Requires an MDflow Pro account. Documentation: https://mdflow.cz/docs/api"
                }
              }
            }
          }
        }
      },
      "Forbidden": {
        "description": "The bearer token is valid but its owner cannot use the API. Agent control (REST + MCP) requires an MDflow Pro plan, so a token owned by a non-Pro account returns 403 on every endpoint. POST /api/v1/documents additionally returns 403 when the account reaches its document limit. The body includes a `message` field with guidance.",
        "headers": {
          "Cache-Control": {
            "$ref": "#/components/headers/NoStore"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "examples": {
              "proRequired": {
                "value": {
                  "error": "Pro plan required",
                  "message": "Authenticate with OAuth (in Claude or ChatGPT connectors, add https://mdflow.cz/api/mcp and complete the sign-in prompt) or with an MDflow Personal Access Token (send an 'Authorization: Bearer mdf_...' header, created at https://mdflow.cz/settings). Requires an MDflow Pro account. Documentation: https://mdflow.cz/docs/api"
                }
              },
              "documentLimit": {
                "value": {
                  "error": "Upgrade to Pro to create more than 100 documents."
                }
              }
            }
          }
        }
      },
      "DocumentNotFound": {
        "description": "Document was not found or is not owned by the authenticated user.",
        "headers": {
          "Cache-Control": {
            "$ref": "#/components/headers/NoStore"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "examples": {
              "notFound": {
                "value": {
                  "error": "Document not found"
                }
              }
            }
          }
        }
      },
      "ShareNotFound": {
        "description": "Document or private share was not found, or is not owned by the authenticated user.",
        "headers": {
          "Cache-Control": {
            "$ref": "#/components/headers/NoStore"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "examples": {
              "documentNotFound": {
                "value": {
                  "error": "Document not found"
                }
              },
              "shareNotFound": {
                "value": {
                  "error": "Share not found"
                }
              }
            }
          }
        }
      },
      "FolderNotFound": {
        "description": "Folder was not found or is not owned by the authenticated user.",
        "headers": {
          "Cache-Control": {
            "$ref": "#/components/headers/NoStore"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "examples": {
              "notFound": {
                "value": {
                  "error": "Folder not found"
                }
              }
            }
          }
        }
      },
      "WorkspaceNotFound": {
        "description": "Workspace was not found or is not owned by the authenticated user.",
        "headers": {
          "Cache-Control": {
            "$ref": "#/components/headers/NoStore"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "examples": {
              "notFound": {
                "value": {
                  "error": "Workspace not found"
                }
              }
            }
          }
        }
      },
      "CannotDeleteLastWorkspace": {
        "description": "The workspace is the owner's only workspace and cannot be deleted.",
        "headers": {
          "Cache-Control": {
            "$ref": "#/components/headers/NoStore"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "examples": {
              "lastWorkspace": {
                "value": {
                  "error": "Cannot delete your last workspace"
                }
              }
            }
          }
        }
      },
      "RateLimited": {
        "description": "The token or authenticated user exceeded a 60 requests per minute rate limit.",
        "headers": {
          "Cache-Control": {
            "$ref": "#/components/headers/NoStore"
          },
          "Retry-After": {
            "$ref": "#/components/headers/RetryAfter"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "examples": {
              "rateLimited": {
                "value": {
                  "error": "Rate limit exceeded"
                }
              }
            }
          }
        }
      },
      "ServerError": {
        "description": "Unexpected server error.",
        "headers": {
          "Cache-Control": {
            "$ref": "#/components/headers/NoStore"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "examples": {
              "unexpected": {
                "value": {
                  "error": "Unexpected API error"
                }
              }
            }
          }
        }
      },
      "Deleted": {
        "description": "Deleted successfully. No response body.",
        "headers": {
          "Cache-Control": {
            "$ref": "#/components/headers/NoStore"
          }
        }
      }
    },
    "schemas": {
      "Folder": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "id",
          "name",
          "description",
          "parent_id",
          "workspace_id",
          "created_at",
          "updated_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string"
          },
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "parent_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "workspace_id": {
            "type": "string",
            "format": "uuid",
            "description": "The workspace this folder belongs to."
          },
          "path": {
            "type": "array",
            "description": "Full path from the workspace root down to this folder, workspace first. Returned by the list and get endpoints; omitted from create and update responses.",
            "items": {
              "$ref": "#/components/schemas/PathSegment"
            }
          },
          "path_string": {
            "type": "string",
            "description": "Path segment names joined by \" / \". Returned by the list and get endpoints; omitted from create and update responses."
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "PathSegment": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "id",
          "name",
          "type"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string"
          },
          "type": {
            "type": "string",
            "enum": [
              "workspace",
              "folder",
              "document"
            ]
          }
        }
      },
      "FolderDetail": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "id",
          "name",
          "description",
          "parent_id",
          "workspace_id",
          "path",
          "path_string",
          "compounded_description",
          "created_at",
          "updated_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string"
          },
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "parent_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "workspace_id": {
            "type": "string",
            "format": "uuid",
            "description": "The workspace this folder belongs to."
          },
          "path": {
            "type": "array",
            "description": "Full path from the workspace root down to this folder, workspace first.",
            "items": {
              "$ref": "#/components/schemas/PathSegment"
            }
          },
          "path_string": {
            "type": "string",
            "description": "Path segment names joined by \" / \"."
          },
          "compounded_description": {
            "type": "string",
            "description": "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."
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "CreateFolderInput": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "name"
        ],
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 100
          },
          "description": {
            "type": "string",
            "maxLength": 5000
          },
          "parent_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "workspace_id": {
            "type": "string",
            "format": "uuid",
            "description": "Workspace for a top-level folder. Ignored when parent_id is set (the parent's workspace wins). Defaults to the owner's oldest workspace."
          }
        }
      },
      "PatchFolderInput": {
        "type": "object",
        "additionalProperties": false,
        "minProperties": 1,
        "description": "At least one of name, description, or parent_id must be provided.",
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 100
          },
          "description": {
            "type": "string",
            "maxLength": 5000
          },
          "parent_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          }
        }
      },
      "CreateDocumentInput": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "folder_id",
          "title",
          "body"
        ],
        "properties": {
          "folder_id": {
            "type": "string",
            "format": "uuid"
          },
          "title": {
            "type": "string",
            "minLength": 1,
            "maxLength": 100
          },
          "body": {
            "type": "string",
            "maxLength": 512000,
            "description": "Markdown document body. UTF-8 encoded content must not exceed 512000 bytes."
          }
        }
      },
      "UpdateDocumentBodyInput": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "body"
        ],
        "properties": {
          "body": {
            "type": "string",
            "maxLength": 512000,
            "description": "Markdown document body. UTF-8 encoded content must not exceed 512000 bytes."
          }
        }
      },
      "MoveDocumentInput": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "folder_id"
        ],
        "properties": {
          "folder_id": {
            "type": "string",
            "format": "uuid"
          }
        }
      },
      "UpdateSharingInput": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "is_public",
          "allow_comments"
        ],
        "properties": {
          "is_public": {
            "type": "boolean"
          },
          "allow_comments": {
            "type": "boolean"
          }
        }
      },
      "DocumentListItem": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "id",
          "title",
          "folder_id",
          "is_public",
          "created_at",
          "updated_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "title": {
            "type": "string"
          },
          "folder_id": {
            "type": "string",
            "format": "uuid"
          },
          "is_public": {
            "type": "boolean"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          },
          "workspace_id": {
            "type": "string",
            "format": "uuid",
            "description": "The workspace this document belongs to (via its folder). Returned by list/get responses; omitted from create/rename/move/body responses."
          },
          "path": {
            "type": "array",
            "description": "Full path from the workspace root down to this document. Returned by list/get responses; omitted from mutation responses.",
            "items": {
              "$ref": "#/components/schemas/PathSegment"
            }
          },
          "path_string": {
            "type": "string",
            "description": "Path segment names joined by \" / \"."
          }
        }
      },
      "Document": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "id",
          "title",
          "folder_id",
          "is_public",
          "workspace_id",
          "path",
          "path_string",
          "body",
          "compounded_description",
          "created_at",
          "updated_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "title": {
            "type": "string"
          },
          "folder_id": {
            "type": "string",
            "format": "uuid"
          },
          "is_public": {
            "type": "boolean"
          },
          "workspace_id": {
            "type": "string",
            "format": "uuid",
            "description": "The workspace this document belongs to (via its folder)."
          },
          "path": {
            "type": "array",
            "description": "Full path from the workspace root down to this document, workspace first, document last.",
            "items": {
              "$ref": "#/components/schemas/PathSegment"
            }
          },
          "path_string": {
            "type": "string",
            "description": "Path segment names joined by \" / \"."
          },
          "body": {
            "type": "string",
            "description": "Markdown document body."
          },
          "compounded_description": {
            "type": "string",
            "description": "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."
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "PatchDocumentInput": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "title"
        ],
        "properties": {
          "title": {
            "type": "string",
            "minLength": 1,
            "maxLength": 100
          }
        }
      },
      "SharingState": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "is_public",
          "allow_comments",
          "share_slug",
          "share_path",
          "public_url"
        ],
        "properties": {
          "is_public": {
            "type": "boolean"
          },
          "allow_comments": {
            "type": "boolean"
          },
          "share_slug": {
            "type": [
              "string",
              "null"
            ]
          },
          "share_path": {
            "type": [
              "string",
              "null"
            ]
          },
          "public_url": {
            "type": [
              "string",
              "null"
            ],
            "format": "uri"
          }
        }
      },
      "CreateDocumentShareInput": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "email"
        ],
        "properties": {
          "email": {
            "type": "string",
            "format": "email",
            "description": "Recipient email address. Trimmed and lowercased before storage."
          },
          "allow_comments": {
            "type": "boolean",
            "default": false,
            "description": "Whether the recipient may comment. Defaults to false (view only)."
          }
        }
      },
      "DocumentShare": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "id",
          "email",
          "allow_comments",
          "status",
          "created_at",
          "accepted_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "Private share identifier. Use it to remove this person."
          },
          "email": {
            "type": "string",
            "format": "email"
          },
          "allow_comments": {
            "type": "boolean",
            "description": "Whether the recipient may comment."
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "accepted"
            ],
            "description": "pending until the recipient signs in with the invited email, then accepted."
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "accepted_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        }
      },
      "Workspace": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "id",
          "name",
          "description",
          "created_at",
          "updated_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string"
          },
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "CreateWorkspaceInput": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "name"
        ],
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 100
          },
          "description": {
            "type": "string",
            "maxLength": 5000
          }
        }
      },
      "UpdateWorkspaceInput": {
        "type": "object",
        "additionalProperties": false,
        "minProperties": 1,
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 100
          },
          "description": {
            "type": "string",
            "maxLength": 5000
          }
        }
      },
      "Error": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "string"
          },
          "message": {
            "type": "string",
            "description": "Optional human-readable guidance for resolving the error, included on authentication (401) and authorization (403) failures."
          }
        }
      }
    }
  },
  "tags": [
    {
      "name": "Workspaces"
    },
    {
      "name": "Folders"
    },
    {
      "name": "Documents"
    }
  ]
}