{
    "openapi": "3.1.0",
    "info": {
        "title": "ProjectSend",
        "version": "1.0.0",
        "description": "Staff-authenticated REST API for ProjectSend. Authenticate with a bearer token created under Settings \u2192 API tokens. See docs/api-guide.md for the narrative guide."
    },
    "servers": [
        {
            "url": "/api/v1"
        }
    ],
    "security": [
        {
            "http": []
        }
    ],
    "paths": {
        "/uploads": {
            "post": {
                "operationId": "uploads.store",
                "description": "Declare the filename and size; the response returns an `uploadId`\nused by the remaining steps. The declared size is re-checked against\nthe assembled bytes when the upload completes.\n\nRequires a token with the ability: `upload`.",
                "summary": "Begin a resumable upload",
                "tags": [
                    "ChunkedUploads"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "filename": {
                                        "type": "string",
                                        "maxLength": 255
                                    },
                                    "size": {
                                        "type": "integer",
                                        "minimum": 1
                                    },
                                    "type": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "maxLength": 255
                                    },
                                    "description": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "maxLength": 2000
                                    },
                                    "folder_id": {
                                        "type": [
                                            "integer",
                                            "null"
                                        ]
                                    },
                                    "previous_file_id": {
                                        "type": [
                                            "integer",
                                            "null"
                                        ]
                                    }
                                },
                                "required": [
                                    "filename",
                                    "size"
                                ]
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "uploadId": {
                                            "type": "string"
                                        },
                                        "key": {
                                            "type": "string"
                                        }
                                    },
                                    "required": [
                                        "uploadId",
                                        "key"
                                    ]
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "An error",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "message": {
                                            "type": "string",
                                            "description": "Error overview.",
                                            "examples": [
                                                ""
                                            ]
                                        }
                                    },
                                    "required": [
                                        "message"
                                    ]
                                }
                            }
                        }
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationException"
                    },
                    "401": {
                        "$ref": "#/components/responses/AuthenticationException"
                    }
                }
            }
        },
        "/uploads/{session}/parts/{part}/sign": {
            "get": {
                "operationId": "uploads.parts.sign",
                "description": "Requires a token with the ability: `upload`.",
                "summary": "Get a short-lived signed URL for one part",
                "tags": [
                    "ChunkedUploads"
                ],
                "parameters": [
                    {
                        "name": "session",
                        "in": "path",
                        "required": true,
                        "description": "The session ID",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "part",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "url": {
                                            "type": "string"
                                        },
                                        "method": {
                                            "type": "string",
                                            "const": "PUT"
                                        }
                                    },
                                    "required": [
                                        "url",
                                        "method"
                                    ]
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "An error",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "message": {
                                            "type": "string",
                                            "description": "Error overview.",
                                            "examples": [
                                                ""
                                            ]
                                        }
                                    },
                                    "required": [
                                        "message"
                                    ]
                                }
                            }
                        }
                    },
                    "404": {
                        "$ref": "#/components/responses/ModelNotFoundException"
                    },
                    "401": {
                        "$ref": "#/components/responses/AuthenticationException"
                    }
                }
            }
        },
        "/uploads/{session}/parts/{part}": {
            "put": {
                "operationId": "uploads.parts.put",
                "description": "PUT the part's raw bytes to the signed URL returned by the sign\nendpoint. Parts may be sent in any order, and the response's `ETag`\nidentifies the stored part.\n\nRequires a token with the ability: `upload`.",
                "summary": "Upload one part",
                "tags": [
                    "ChunkedUploads"
                ],
                "parameters": [
                    {
                        "name": "session",
                        "in": "path",
                        "required": true,
                        "description": "The session ID",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "part",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "",
                        "headers": {
                            "ETag": {
                                "schema": {
                                    "type": "string"
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "An error",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "message": {
                                            "type": "string",
                                            "description": "Error overview.",
                                            "examples": [
                                                ""
                                            ]
                                        }
                                    },
                                    "required": [
                                        "message"
                                    ]
                                }
                            }
                        }
                    },
                    "413": {
                        "description": "An error",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "message": {
                                            "type": "string",
                                            "description": "Error overview.",
                                            "examples": [
                                                ""
                                            ]
                                        }
                                    },
                                    "required": [
                                        "message"
                                    ]
                                }
                            }
                        }
                    },
                    "404": {
                        "$ref": "#/components/responses/ModelNotFoundException"
                    },
                    "401": {
                        "$ref": "#/components/responses/AuthenticationException"
                    }
                }
            }
        },
        "/uploads/{session}/parts": {
            "get": {
                "operationId": "uploads.parts.index",
                "description": "Requires a token with the ability: `upload`.",
                "summary": "List the parts already received, so an interrupted upload can resume\nrather than start again",
                "tags": [
                    "ChunkedUploads"
                ],
                "parameters": [
                    {
                        "name": "session",
                        "in": "path",
                        "required": true,
                        "description": "The session ID",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "array",
                                    "items": {}
                                }
                            }
                        }
                    },
                    "404": {
                        "$ref": "#/components/responses/ModelNotFoundException"
                    },
                    "401": {
                        "$ref": "#/components/responses/AuthenticationException"
                    }
                }
            }
        },
        "/uploads/{session}/complete": {
            "post": {
                "operationId": "uploads.complete",
                "description": "Requires a token with the ability: `upload`.",
                "tags": [
                    "ChunkedUploads"
                ],
                "parameters": [
                    {
                        "name": "session",
                        "in": "path",
                        "required": true,
                        "description": "The session ID",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "location": {
                                            "type": "string"
                                        },
                                        "file_id": {
                                            "type": "integer"
                                        },
                                        "version_error": {
                                            "type": [
                                                "string",
                                                "null"
                                            ]
                                        }
                                    },
                                    "required": [
                                        "location",
                                        "file_id",
                                        "version_error"
                                    ]
                                }
                            }
                        }
                    },
                    "404": {
                        "$ref": "#/components/responses/ModelNotFoundException"
                    },
                    "401": {
                        "$ref": "#/components/responses/AuthenticationException"
                    }
                }
            }
        },
        "/uploads/{session}": {
            "delete": {
                "operationId": "uploads.destroy",
                "description": "Requires a token with the ability: `upload`.",
                "tags": [
                    "ChunkedUploads"
                ],
                "parameters": [
                    {
                        "name": "session",
                        "in": "path",
                        "required": true,
                        "description": "The session ID",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    }
                ],
                "responses": {
                    "204": {
                        "description": "No content"
                    },
                    "404": {
                        "$ref": "#/components/responses/ModelNotFoundException"
                    },
                    "401": {
                        "$ref": "#/components/responses/AuthenticationException"
                    }
                }
            }
        },
        "/clients": {
            "get": {
                "operationId": "clients.index",
                "description": "Requires a token with the ability: `manage_clients`.",
                "tags": [
                    "Clients"
                ],
                "parameters": [
                    {
                        "name": "updated_since",
                        "in": "query",
                        "schema": {
                            "type": [
                                "string",
                                "null"
                            ],
                            "format": "date-time"
                        }
                    },
                    {
                        "name": "per_page",
                        "in": "query",
                        "schema": {
                            "type": [
                                "integer",
                                "null"
                            ],
                            "minimum": 1,
                            "maximum": 100
                        }
                    },
                    {
                        "name": "cursor",
                        "in": "query",
                        "schema": {
                            "type": [
                                "string",
                                "null"
                            ]
                        }
                    },
                    {
                        "name": "search",
                        "in": "query",
                        "schema": {
                            "type": [
                                "string",
                                "null"
                            ],
                            "maxLength": 255
                        }
                    },
                    {
                        "name": "status",
                        "in": "query",
                        "schema": {
                            "type": [
                                "string",
                                "null"
                            ],
                            "enum": [
                                "active",
                                "inactive",
                                null
                            ]
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Paginated set of `ClientResource`",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "array",
                                            "items": {
                                                "$ref": "#/components/schemas/ClientResource"
                                            }
                                        },
                                        "links": {
                                            "type": "object",
                                            "properties": {
                                                "first": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ]
                                                },
                                                "last": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ]
                                                },
                                                "prev": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ]
                                                },
                                                "next": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ]
                                                }
                                            },
                                            "required": [
                                                "first",
                                                "last",
                                                "prev",
                                                "next"
                                            ]
                                        },
                                        "meta": {
                                            "type": "object",
                                            "properties": {
                                                "path": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "Base path for paginator generated URLs."
                                                },
                                                "per_page": {
                                                    "type": "integer",
                                                    "description": "Number of items shown per page.",
                                                    "minimum": 0
                                                },
                                                "next_cursor": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The \"cursor\" that points to the next set of items."
                                                },
                                                "prev_cursor": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The \"cursor\" that points to the previous set of items."
                                                }
                                            },
                                            "required": [
                                                "path",
                                                "per_page",
                                                "next_cursor",
                                                "prev_cursor"
                                            ]
                                        }
                                    },
                                    "required": [
                                        "data",
                                        "links",
                                        "meta"
                                    ]
                                }
                            }
                        }
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationException"
                    },
                    "401": {
                        "$ref": "#/components/responses/AuthenticationException"
                    }
                }
            },
            "post": {
                "operationId": "clients.store",
                "description": "Requires a token with the ability: `create_clients`.",
                "tags": [
                    "Clients"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "name": {
                                        "type": "string",
                                        "maxLength": 255
                                    },
                                    "email": {
                                        "type": "string",
                                        "format": "email",
                                        "maxLength": 255
                                    },
                                    "password": {
                                        "type": "string",
                                        "description": "No `confirmed`: repeating a password is a defence against a\nhuman mistyping into a form, and an API caller has no second\nfield to mistype. This installation's password policy still\napplies \u2014 a minimum length, and optionally a check against\nknown breaches. Both are configured under Settings \u2192\nSecurity, so read them from there rather than assuming the\ndefaults; a password this endpoint accepts on one\ninstallation may be refused on another."
                                    },
                                    "storage_quota_mb": {
                                        "type": [
                                            "integer",
                                            "null"
                                        ],
                                        "minimum": 0
                                    },
                                    "custom_field_values": {
                                        "type": "array",
                                        "items": {
                                            "type": "string"
                                        }
                                    }
                                },
                                "required": [
                                    "name",
                                    "email",
                                    "password"
                                ]
                            }
                        }
                    }
                },
                "responses": {
                    "201": {
                        "description": "`ClientResource`",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "$ref": "#/components/schemas/ClientResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                }
                            }
                        }
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationException"
                    },
                    "401": {
                        "$ref": "#/components/responses/AuthenticationException"
                    }
                }
            }
        },
        "/clients/{client}": {
            "get": {
                "operationId": "clients.show",
                "description": "Requires a token with the ability: `edit_clients`.",
                "tags": [
                    "Clients"
                ],
                "parameters": [
                    {
                        "name": "client",
                        "in": "path",
                        "required": true,
                        "description": "The client ID",
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "`ClientResource`",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "$ref": "#/components/schemas/ClientResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                }
                            }
                        }
                    },
                    "404": {
                        "$ref": "#/components/responses/ModelNotFoundException"
                    },
                    "401": {
                        "$ref": "#/components/responses/AuthenticationException"
                    }
                }
            },
            "patch": {
                "operationId": "clients.update",
                "description": "Requires a token with the ability: `edit_clients`.",
                "tags": [
                    "Clients"
                ],
                "parameters": [
                    {
                        "name": "client",
                        "in": "path",
                        "required": true,
                        "description": "The client ID",
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "name": {
                                        "type": "string",
                                        "maxLength": 255
                                    },
                                    "email": {
                                        "type": "string",
                                        "format": "email",
                                        "maxLength": 255
                                    },
                                    "active": {
                                        "type": "boolean"
                                    },
                                    "password": {
                                        "type": [
                                            "string",
                                            "null"
                                        ]
                                    },
                                    "storage_quota_mb": {
                                        "type": [
                                            "integer",
                                            "null"
                                        ],
                                        "minimum": 0
                                    },
                                    "custom_field_values": {
                                        "type": "array",
                                        "items": {
                                            "type": "string"
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "`ClientResource`",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "$ref": "#/components/schemas/ClientResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                }
                            }
                        }
                    },
                    "404": {
                        "$ref": "#/components/responses/ModelNotFoundException"
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationException"
                    },
                    "401": {
                        "$ref": "#/components/responses/AuthenticationException"
                    }
                }
            },
            "delete": {
                "operationId": "clients.destroy",
                "description": "If the client owns no files or folders, no body is needed.\n\nIf they do, you must say what happens to that content: send\n`content_action` as either `cascade_delete` (delete it along with the\naccount) or `reassign`, and in the latter case a `reassign_to_id`\nnaming the active account that inherits it. Omitting the choice is a\n422 \u2014 there is no default, because one would silently destroy a\nclient's files and the other would silently hand them to somebody\nelse.\n\n`GET /clients/{client}` reports the counts so you can decide before\ncalling this.\n\nRequires a token with the ability: `delete_clients`.",
                "summary": "Delete a client",
                "tags": [
                    "Clients"
                ],
                "parameters": [
                    {
                        "name": "client",
                        "in": "path",
                        "required": true,
                        "description": "The client ID",
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "responses": {
                    "204": {
                        "description": "No content",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "array",
                                    "items": {}
                                }
                            }
                        }
                    },
                    "404": {
                        "$ref": "#/components/responses/ModelNotFoundException"
                    },
                    "401": {
                        "$ref": "#/components/responses/AuthenticationException"
                    }
                }
            }
        },
        "/clients/{client}/two-factor": {
            "delete": {
                "operationId": "clients.two-factor.destroy",
                "description": "The remedy for a locked-out account: a client whose authenticator\napp and recovery codes are both gone cannot sign in, and nobody else\ncan open the account for them either. Afterwards they sign in with\ntheir password alone, and \u2014 if this installation enforces two-factor\nauthentication for clients \u2014 are asked to enrol again on their next\nrequest.\n\nThe client is emailed that this happened, and the action is recorded\nin the activity log against the caller. Answers 204 whether or not a\nsecond factor was actually in force.\n\nRequires a token with the ability: `edit_clients`.",
                "summary": "Remove a client's two-factor authentication",
                "tags": [
                    "Clients"
                ],
                "parameters": [
                    {
                        "name": "client",
                        "in": "path",
                        "required": true,
                        "description": "The client ID",
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "responses": {
                    "204": {
                        "description": "No content",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "array",
                                    "items": {}
                                }
                            }
                        }
                    },
                    "404": {
                        "$ref": "#/components/responses/ModelNotFoundException"
                    },
                    "401": {
                        "$ref": "#/components/responses/AuthenticationException"
                    }
                }
            }
        },
        "/comments/pending": {
            "get": {
                "operationId": "comments.pending",
                "description": "Scoped by the same library boundary as everything else: a\nclient-scoped token sees pending comments only on files its owner\ncould already open. Oldest first, so working through the list means\nworking through the backlog.\n\nRequires a token with the ability: `moderate_comments`.",
                "summary": "List comments awaiting approval",
                "tags": [
                    "CommentModeration"
                ],
                "responses": {
                    "200": {
                        "description": "Array of `FileCommentResource`",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "array",
                                            "items": {
                                                "$ref": "#/components/schemas/FileCommentResource"
                                            }
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/AuthenticationException"
                    }
                }
            }
        },
        "/comments/{comment}/approve": {
            "post": {
                "operationId": "comments.approve",
                "description": "Nobody can see it until this happens. Approving an already-approved\ncomment changes nothing and announces nothing, so a retried request\nis safe \u2014 which matters more here than on the web, where a human does\nnot retry automatically.\n\nRequires a token with the ability: `moderate_comments`.",
                "summary": "Approve a comment left by a visitor",
                "tags": [
                    "CommentModeration"
                ],
                "parameters": [
                    {
                        "name": "comment",
                        "in": "path",
                        "required": true,
                        "description": "The comment ID",
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "`FileCommentResource`",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "$ref": "#/components/schemas/FileCommentResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "An error",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "message": {
                                            "type": "string",
                                            "description": "Error overview.",
                                            "examples": [
                                                ""
                                            ]
                                        }
                                    },
                                    "required": [
                                        "message"
                                    ]
                                }
                            }
                        }
                    },
                    "404": {
                        "$ref": "#/components/responses/ModelNotFoundException"
                    },
                    "401": {
                        "$ref": "#/components/responses/AuthenticationException"
                    }
                }
            }
        },
        "/tokens/current": {
            "delete": {
                "operationId": "tokens.current.destroy",
                "tags": [
                    "CurrentToken"
                ],
                "responses": {
                    "204": {
                        "description": "No content",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "array",
                                    "items": {}
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/AuthenticationException"
                    }
                }
            }
        },
        "/files/{file}/assignments": {
            "post": {
                "operationId": "files.assignments.store",
                "description": "Requires a token with any of these abilities: `edit_files`, `edit_others_files`.",
                "tags": [
                    "FileAssignments"
                ],
                "parameters": [
                    {
                        "name": "file",
                        "in": "path",
                        "required": true,
                        "description": "The file ID",
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "`FileResource`",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "allOf": [
                                                {
                                                    "$ref": "#/components/schemas/FileResource"
                                                },
                                                {
                                                    "type": "object",
                                                    "required": [
                                                        "assignments"
                                                    ]
                                                }
                                            ]
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                }
                            }
                        }
                    },
                    "403": {
                        "$ref": "#/components/responses/AuthorizationException"
                    },
                    "404": {
                        "$ref": "#/components/responses/ModelNotFoundException"
                    },
                    "401": {
                        "$ref": "#/components/responses/AuthenticationException"
                    }
                }
            },
            "delete": {
                "operationId": "files.assignments.destroy",
                "description": "Requires a token with any of these abilities: `edit_files`, `edit_others_files`.",
                "tags": [
                    "FileAssignments"
                ],
                "parameters": [
                    {
                        "name": "file",
                        "in": "path",
                        "required": true,
                        "description": "The file ID",
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "`FileResource`",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "allOf": [
                                                {
                                                    "$ref": "#/components/schemas/FileResource"
                                                },
                                                {
                                                    "type": "object",
                                                    "required": [
                                                        "assignments"
                                                    ]
                                                }
                                            ]
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                }
                            }
                        }
                    },
                    "403": {
                        "$ref": "#/components/responses/AuthorizationException"
                    },
                    "404": {
                        "$ref": "#/components/responses/ModelNotFoundException"
                    },
                    "401": {
                        "$ref": "#/components/responses/AuthenticationException"
                    }
                }
            }
        },
        "/files/{file}/comments": {
            "get": {
                "operationId": "files.comments.index",
                "description": "Returns the comments the authenticated token's owner may read,\noldest first. A comment left by a visitor and not yet approved is\nincluded only for a token whose owner may moderate.\n\nRequires a token with any of these abilities: `upload`, `edit_files`, `edit_others_files`.",
                "summary": "List a file's comments",
                "tags": [
                    "FileComments"
                ],
                "parameters": [
                    {
                        "name": "file",
                        "in": "path",
                        "required": true,
                        "description": "The file ID",
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Array of `FileCommentResource`",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "array",
                                            "items": {
                                                "$ref": "#/components/schemas/FileCommentResource"
                                            }
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                }
                            }
                        }
                    },
                    "404": {
                        "$ref": "#/components/responses/ModelNotFoundException"
                    },
                    "401": {
                        "$ref": "#/components/responses/AuthenticationException"
                    }
                }
            },
            "post": {
                "operationId": "files.comments.store",
                "description": "`visibility` is one of `only_me` (a private note), `staff_only` (the\nteam, no client), `clients` (**the team and** every client the file\nis shared with \u2014 the name says who it adds, since staff can already\nsee everything on a file they can open) or `everyone` (all of the\nabove plus anyone who opens the file without logging in).\nWhich of them are available depends on the installation's comment\nsettings and on whether the file is publicly visible; asking for one\nthat is not available returns 403.\n\n`reply_to` is the id of a comment being answered. A reply inherits\nthat comment's audience, which is the only way a comment becomes\naddressed to one client rather than all of them \u2014 there is no field\nthat names a client directly. An id this token cannot already read\nis ignored, and the comment is posted as a fresh one.\n\nRequires a token with any of these abilities: `upload`, `edit_files`, `edit_others_files`.",
                "summary": "Post a comment on a file",
                "tags": [
                    "FileComments"
                ],
                "parameters": [
                    {
                        "name": "file",
                        "in": "path",
                        "required": true,
                        "description": "The file ID",
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "body": {
                                        "type": "string",
                                        "maxLength": 5000
                                    },
                                    "visibility": {
                                        "$ref": "#/components/schemas/CommentVisibility"
                                    },
                                    "reply_to": {
                                        "type": [
                                            "integer",
                                            "null"
                                        ]
                                    }
                                },
                                "required": [
                                    "body",
                                    "visibility"
                                ]
                            }
                        }
                    }
                },
                "responses": {
                    "201": {
                        "description": "`FileCommentResource`",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "$ref": "#/components/schemas/FileCommentResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                }
                            }
                        }
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationException"
                    },
                    "403": {
                        "$ref": "#/components/responses/AuthorizationException"
                    },
                    "404": {
                        "$ref": "#/components/responses/ModelNotFoundException"
                    },
                    "401": {
                        "$ref": "#/components/responses/AuthenticationException"
                    }
                }
            }
        },
        "/comments/{comment}": {
            "patch": {
                "operationId": "comments.update",
                "description": "Only its own author may, and only within the installation's editing\nwindow. Moderation rights do not extend to rewriting somebody\nelse's words.\n\nRequires a token with any of these abilities: `upload`, `edit_files`, `edit_others_files`.",
                "summary": "Edit a comment",
                "tags": [
                    "FileComments"
                ],
                "parameters": [
                    {
                        "name": "comment",
                        "in": "path",
                        "required": true,
                        "description": "The comment ID",
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "body": {
                                        "type": "string",
                                        "maxLength": 5000
                                    }
                                },
                                "required": [
                                    "body"
                                ]
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "`FileCommentResource`",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "$ref": "#/components/schemas/FileCommentResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                }
                            }
                        }
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationException"
                    },
                    "404": {
                        "$ref": "#/components/responses/ModelNotFoundException"
                    },
                    "401": {
                        "$ref": "#/components/responses/AuthenticationException"
                    }
                }
            },
            "delete": {
                "operationId": "comments.destroy",
                "description": "Its author may, within the editing window; a moderator may at any\ntime. The comment is soft-deleted, so a later dispute is not left\nwith a hole where the conversation was.\n\nRequires a token with any of these abilities: `upload`, `edit_files`, `edit_others_files`.",
                "summary": "Delete a comment",
                "tags": [
                    "FileComments"
                ],
                "parameters": [
                    {
                        "name": "comment",
                        "in": "path",
                        "required": true,
                        "description": "The comment ID",
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "responses": {
                    "204": {
                        "description": "No content",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "array",
                                    "items": {}
                                }
                            }
                        }
                    },
                    "404": {
                        "$ref": "#/components/responses/ModelNotFoundException"
                    },
                    "401": {
                        "$ref": "#/components/responses/AuthenticationException"
                    }
                }
            }
        },
        "/files/{file}/download": {
            "get": {
                "operationId": "files.download",
                "description": "Requires a token with any of these abilities: `upload`, `edit_files`, `edit_others_files`.",
                "tags": [
                    "FileDownload"
                ],
                "parameters": [
                    {
                        "name": "file",
                        "in": "path",
                        "required": true,
                        "description": "The file ID",
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "403": {
                        "$ref": "#/components/responses/AuthorizationException"
                    },
                    "404": {
                        "$ref": "#/components/responses/ModelNotFoundException"
                    },
                    "401": {
                        "$ref": "#/components/responses/AuthenticationException"
                    }
                }
            }
        },
        "/files/{file}/version": {
            "put": {
                "operationId": "files.version.store",
                "description": "The file named by `previous_file_id` must be one you may reach, and\nmust not already have been revised. **A revision is shared with the\nsame people as the original**: any recipients this file currently has\nare moved onto the original, and afterwards its own assignment\nendpoints refuse writes and point at the original instead.\n\nRequires a token with any of these abilities: `edit_files`, `edit_others_files`.",
                "summary": "Mark this file as a new version of another",
                "tags": [
                    "FileVersions"
                ],
                "parameters": [
                    {
                        "name": "file",
                        "in": "path",
                        "required": true,
                        "description": "The file ID",
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "previous_file_id": {
                                        "type": "integer"
                                    }
                                },
                                "required": [
                                    "previous_file_id"
                                ]
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "`FileResource`",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "$ref": "#/components/schemas/FileResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                }
                            }
                        }
                    },
                    "403": {
                        "$ref": "#/components/responses/AuthorizationException"
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationException"
                    },
                    "404": {
                        "$ref": "#/components/responses/ModelNotFoundException"
                    },
                    "401": {
                        "$ref": "#/components/responses/AuthenticationException"
                    }
                }
            },
            "delete": {
                "operationId": "files.version.destroy",
                "description": "It stops inheriting the original's recipients, so it keeps a copy of\nthem: unlinking never takes access away from someone who already has\nit.\n\nRequires a token with any of these abilities: `edit_files`, `edit_others_files`.",
                "summary": "Remove this file's version link, making it stand on its own again",
                "tags": [
                    "FileVersions"
                ],
                "parameters": [
                    {
                        "name": "file",
                        "in": "path",
                        "required": true,
                        "description": "The file ID",
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "`FileResource`",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "$ref": "#/components/schemas/FileResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                }
                            }
                        }
                    },
                    "403": {
                        "$ref": "#/components/responses/AuthorizationException"
                    },
                    "404": {
                        "$ref": "#/components/responses/ModelNotFoundException"
                    },
                    "401": {
                        "$ref": "#/components/responses/AuthenticationException"
                    }
                }
            }
        },
        "/files": {
            "get": {
                "operationId": "files.index",
                "description": "Requires a token with any of these abilities: `upload`, `edit_files`, `edit_others_files`.",
                "tags": [
                    "Files"
                ],
                "parameters": [
                    {
                        "name": "updated_since",
                        "in": "query",
                        "schema": {
                            "type": [
                                "string",
                                "null"
                            ],
                            "format": "date-time"
                        }
                    },
                    {
                        "name": "per_page",
                        "in": "query",
                        "schema": {
                            "type": [
                                "integer",
                                "null"
                            ],
                            "minimum": 1,
                            "maximum": 100
                        }
                    },
                    {
                        "name": "cursor",
                        "in": "query",
                        "schema": {
                            "type": [
                                "string",
                                "null"
                            ]
                        }
                    },
                    {
                        "name": "folder_id",
                        "in": "query",
                        "schema": {
                            "type": [
                                "integer",
                                "null"
                            ]
                        }
                    },
                    {
                        "name": "category_id",
                        "in": "query",
                        "schema": {
                            "type": [
                                "integer",
                                "null"
                            ]
                        }
                    },
                    {
                        "name": "uploaded_by",
                        "in": "query",
                        "schema": {
                            "type": [
                                "integer",
                                "null"
                            ]
                        }
                    },
                    {
                        "name": "search",
                        "in": "query",
                        "schema": {
                            "type": [
                                "string",
                                "null"
                            ],
                            "maxLength": 255
                        }
                    },
                    {
                        "name": "public",
                        "in": "query",
                        "schema": {
                            "type": [
                                "boolean",
                                "null"
                            ]
                        }
                    },
                    {
                        "name": "expired",
                        "in": "query",
                        "schema": {
                            "type": [
                                "boolean",
                                "null"
                            ]
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Paginated set of `FileResource`",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "array",
                                            "items": {
                                                "$ref": "#/components/schemas/FileResource"
                                            }
                                        },
                                        "links": {
                                            "type": "object",
                                            "properties": {
                                                "first": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ]
                                                },
                                                "last": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ]
                                                },
                                                "prev": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ]
                                                },
                                                "next": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ]
                                                }
                                            },
                                            "required": [
                                                "first",
                                                "last",
                                                "prev",
                                                "next"
                                            ]
                                        },
                                        "meta": {
                                            "type": "object",
                                            "properties": {
                                                "path": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "Base path for paginator generated URLs."
                                                },
                                                "per_page": {
                                                    "type": "integer",
                                                    "description": "Number of items shown per page.",
                                                    "minimum": 0
                                                },
                                                "next_cursor": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The \"cursor\" that points to the next set of items."
                                                },
                                                "prev_cursor": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The \"cursor\" that points to the previous set of items."
                                                }
                                            },
                                            "required": [
                                                "path",
                                                "per_page",
                                                "next_cursor",
                                                "prev_cursor"
                                            ]
                                        }
                                    },
                                    "required": [
                                        "data",
                                        "links",
                                        "meta"
                                    ]
                                }
                            }
                        }
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationException"
                    },
                    "401": {
                        "$ref": "#/components/responses/AuthenticationException"
                    }
                }
            },
            "post": {
                "operationId": "files.store",
                "description": "Send the file as multipart form data. The maximum accepted size is\nthis installation's configured upload limit; larger or unreliable\nuploads should use the resumable `/uploads` endpoints instead.\n\nThe stored content type is detected from the uploaded bytes, not from\nthe declared `Content-Type`.\n\nRequires a token with the ability: `upload`.",
                "summary": "Upload a file in a single request",
                "tags": [
                    "Files"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "multipart/form-data": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "file": {
                                        "type": "string",
                                        "format": "binary",
                                        "contentMediaType": "application/octet-stream"
                                    },
                                    "name": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "maxLength": 255
                                    },
                                    "description": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "maxLength": 2000
                                    },
                                    "folder_id": {
                                        "type": [
                                            "integer",
                                            "null"
                                        ]
                                    }
                                },
                                "required": [
                                    "file"
                                ]
                            }
                        }
                    }
                },
                "responses": {
                    "201": {
                        "description": "`FileResource`",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "allOf": [
                                                {
                                                    "$ref": "#/components/schemas/FileResource"
                                                },
                                                {
                                                    "type": "object",
                                                    "required": [
                                                        "folder",
                                                        "uploaded_by",
                                                        "categories"
                                                    ]
                                                }
                                            ]
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "An error",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "message": {
                                            "type": "string",
                                            "description": "Error overview.",
                                            "examples": [
                                                ""
                                            ]
                                        }
                                    },
                                    "required": [
                                        "message"
                                    ]
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "An error",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "message": {
                                            "type": "string",
                                            "description": "Error overview.",
                                            "examples": [
                                                ""
                                            ]
                                        }
                                    },
                                    "required": [
                                        "message"
                                    ]
                                }
                            }
                        }
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationException"
                    },
                    "401": {
                        "$ref": "#/components/responses/AuthenticationException"
                    }
                }
            }
        },
        "/files/{file}": {
            "get": {
                "operationId": "files.show",
                "description": "Requires a token with any of these abilities: `upload`, `edit_files`, `edit_others_files`.",
                "tags": [
                    "Files"
                ],
                "parameters": [
                    {
                        "name": "file",
                        "in": "path",
                        "required": true,
                        "description": "The file ID",
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "`FileResource`",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "$ref": "#/components/schemas/FileResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                }
                            }
                        }
                    },
                    "403": {
                        "$ref": "#/components/responses/AuthorizationException"
                    },
                    "404": {
                        "$ref": "#/components/responses/ModelNotFoundException"
                    },
                    "401": {
                        "$ref": "#/components/responses/AuthenticationException"
                    }
                }
            },
            "patch": {
                "operationId": "files.update",
                "description": "Only the fields present in the request are changed; omitting one\nleaves it as it was.\n\nSome fields need a permission of their own \u2014 `expires_at` needs\n`set_file_expiration_date`, `public` needs `upload_public`, and\n`categories` needs `set_file_categories`. Sending one of those\nwithout the matching permission leaves that field untouched rather\nthan failing the whole request, which mirrors the web interface.\n\n`commentable` only has an effect while the installation's comment\nsetting is \"only files marked as commentable\"; under any other\nsetting it is ignored, again rather than failing.\n\nRequires a token with any of these abilities: `edit_files`, `edit_others_files`.",
                "summary": "Update a file's metadata",
                "tags": [
                    "Files"
                ],
                "parameters": [
                    {
                        "name": "file",
                        "in": "path",
                        "required": true,
                        "description": "The file ID",
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "name": {
                                        "type": "string",
                                        "maxLength": 255
                                    },
                                    "description": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "maxLength": 2000
                                    },
                                    "folder_id": {
                                        "type": [
                                            "integer",
                                            "null"
                                        ]
                                    },
                                    "public": {
                                        "type": "boolean"
                                    },
                                    "commentable": {
                                        "type": "boolean"
                                    },
                                    "slug": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "pattern": "^[a-z0-9]+(-[a-z0-9]+)*$",
                                        "maxLength": 255
                                    },
                                    "categories": {
                                        "type": "array",
                                        "items": {
                                            "type": "integer"
                                        }
                                    },
                                    "expires_at": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "date-time"
                                    },
                                    "download_limit": {
                                        "type": [
                                            "integer",
                                            "null"
                                        ],
                                        "minimum": 1
                                    },
                                    "download_limit_scope": {
                                        "$ref": "#/components/schemas/DownloadLimitScope"
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "`FileResource`",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "allOf": [
                                                {
                                                    "$ref": "#/components/schemas/FileResource"
                                                },
                                                {
                                                    "type": "object",
                                                    "required": [
                                                        "folder",
                                                        "uploaded_by",
                                                        "categories"
                                                    ]
                                                }
                                            ]
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                }
                            }
                        }
                    },
                    "403": {
                        "$ref": "#/components/responses/AuthorizationException"
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationException"
                    },
                    "404": {
                        "$ref": "#/components/responses/ModelNotFoundException"
                    },
                    "401": {
                        "$ref": "#/components/responses/AuthenticationException"
                    }
                }
            },
            "delete": {
                "operationId": "files.destroy",
                "description": "Requires a token with any of these abilities: `delete_files`, `delete_others_files`.",
                "tags": [
                    "Files"
                ],
                "parameters": [
                    {
                        "name": "file",
                        "in": "path",
                        "required": true,
                        "description": "The file ID",
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "responses": {
                    "204": {
                        "description": "No content",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "array",
                                    "items": {}
                                }
                            }
                        }
                    },
                    "403": {
                        "$ref": "#/components/responses/AuthorizationException"
                    },
                    "404": {
                        "$ref": "#/components/responses/ModelNotFoundException"
                    },
                    "401": {
                        "$ref": "#/components/responses/AuthenticationException"
                    }
                }
            }
        },
        "/groups/{group}/members": {
            "post": {
                "operationId": "groups.members.store",
                "description": "Requires a token with the ability: `edit_groups`.",
                "tags": [
                    "GroupMembers"
                ],
                "parameters": [
                    {
                        "name": "group",
                        "in": "path",
                        "required": true,
                        "description": "The group ID",
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "user_id": {
                                        "type": "integer"
                                    }
                                },
                                "required": [
                                    "user_id"
                                ]
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "`GroupResource`",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "allOf": [
                                                {
                                                    "$ref": "#/components/schemas/GroupResource"
                                                },
                                                {
                                                    "type": "object",
                                                    "required": [
                                                        "members"
                                                    ]
                                                }
                                            ]
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                }
                            }
                        }
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationException"
                    },
                    "404": {
                        "$ref": "#/components/responses/ModelNotFoundException"
                    },
                    "401": {
                        "$ref": "#/components/responses/AuthenticationException"
                    }
                }
            }
        },
        "/groups/{group}/members/{member}": {
            "delete": {
                "operationId": "groups.members.destroy",
                "description": "Requires a token with the ability: `edit_groups`.",
                "tags": [
                    "GroupMembers"
                ],
                "parameters": [
                    {
                        "name": "group",
                        "in": "path",
                        "required": true,
                        "description": "The group ID",
                        "schema": {
                            "type": "integer"
                        }
                    },
                    {
                        "name": "member",
                        "in": "path",
                        "required": true,
                        "description": "The member ID",
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "`GroupResource`",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "allOf": [
                                                {
                                                    "$ref": "#/components/schemas/GroupResource"
                                                },
                                                {
                                                    "type": "object",
                                                    "required": [
                                                        "members"
                                                    ]
                                                }
                                            ]
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                }
                            }
                        }
                    },
                    "404": {
                        "$ref": "#/components/responses/ModelNotFoundException"
                    },
                    "401": {
                        "$ref": "#/components/responses/AuthenticationException"
                    }
                }
            }
        },
        "/groups": {
            "get": {
                "operationId": "groups.index",
                "description": "Requires a token with the ability: `manage_groups`.",
                "tags": [
                    "Groups"
                ],
                "parameters": [
                    {
                        "name": "updated_since",
                        "in": "query",
                        "schema": {
                            "type": [
                                "string",
                                "null"
                            ],
                            "format": "date-time"
                        }
                    },
                    {
                        "name": "per_page",
                        "in": "query",
                        "schema": {
                            "type": [
                                "integer",
                                "null"
                            ],
                            "minimum": 1,
                            "maximum": 100
                        }
                    },
                    {
                        "name": "cursor",
                        "in": "query",
                        "schema": {
                            "type": [
                                "string",
                                "null"
                            ]
                        }
                    },
                    {
                        "name": "search",
                        "in": "query",
                        "schema": {
                            "type": [
                                "string",
                                "null"
                            ],
                            "maxLength": 255
                        }
                    },
                    {
                        "name": "visibility",
                        "in": "query",
                        "schema": {
                            "type": [
                                "string",
                                "null"
                            ],
                            "enum": [
                                "public",
                                "private",
                                null
                            ]
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Paginated set of `GroupResource`",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "array",
                                            "items": {
                                                "$ref": "#/components/schemas/GroupResource"
                                            }
                                        },
                                        "links": {
                                            "type": "object",
                                            "properties": {
                                                "first": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ]
                                                },
                                                "last": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ]
                                                },
                                                "prev": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ]
                                                },
                                                "next": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ]
                                                }
                                            },
                                            "required": [
                                                "first",
                                                "last",
                                                "prev",
                                                "next"
                                            ]
                                        },
                                        "meta": {
                                            "type": "object",
                                            "properties": {
                                                "path": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "Base path for paginator generated URLs."
                                                },
                                                "per_page": {
                                                    "type": "integer",
                                                    "description": "Number of items shown per page.",
                                                    "minimum": 0
                                                },
                                                "next_cursor": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The \"cursor\" that points to the next set of items."
                                                },
                                                "prev_cursor": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The \"cursor\" that points to the previous set of items."
                                                }
                                            },
                                            "required": [
                                                "path",
                                                "per_page",
                                                "next_cursor",
                                                "prev_cursor"
                                            ]
                                        }
                                    },
                                    "required": [
                                        "data",
                                        "links",
                                        "meta"
                                    ]
                                }
                            }
                        }
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationException"
                    },
                    "401": {
                        "$ref": "#/components/responses/AuthenticationException"
                    }
                }
            },
            "post": {
                "operationId": "groups.store",
                "description": "Requires a token with the ability: `create_groups`.",
                "tags": [
                    "Groups"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "name": {
                                        "type": "string",
                                        "maxLength": 255
                                    },
                                    "slug": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "pattern": "^[a-z0-9]+(-[a-z0-9]+)*$",
                                        "maxLength": 255
                                    },
                                    "description": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "maxLength": 2000
                                    },
                                    "public": {
                                        "type": "boolean"
                                    }
                                },
                                "required": [
                                    "name",
                                    "public"
                                ]
                            }
                        }
                    }
                },
                "responses": {
                    "201": {
                        "description": "`GroupResource`",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "$ref": "#/components/schemas/GroupResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                }
                            }
                        }
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationException"
                    },
                    "401": {
                        "$ref": "#/components/responses/AuthenticationException"
                    }
                }
            }
        },
        "/groups/{group}": {
            "get": {
                "operationId": "groups.show",
                "description": "Requires a token with the ability: `edit_groups`.",
                "tags": [
                    "Groups"
                ],
                "parameters": [
                    {
                        "name": "group",
                        "in": "path",
                        "required": true,
                        "description": "The group ID",
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "`GroupResource`",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "allOf": [
                                                {
                                                    "$ref": "#/components/schemas/GroupResource"
                                                },
                                                {
                                                    "type": "object",
                                                    "required": [
                                                        "members"
                                                    ]
                                                }
                                            ]
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                }
                            }
                        }
                    },
                    "404": {
                        "$ref": "#/components/responses/ModelNotFoundException"
                    },
                    "401": {
                        "$ref": "#/components/responses/AuthenticationException"
                    }
                }
            },
            "patch": {
                "operationId": "groups.update",
                "description": "Requires a token with the ability: `edit_groups`.",
                "tags": [
                    "Groups"
                ],
                "parameters": [
                    {
                        "name": "group",
                        "in": "path",
                        "required": true,
                        "description": "The group ID",
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "name": {
                                        "type": "string",
                                        "maxLength": 255
                                    },
                                    "slug": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "pattern": "^[a-z0-9]+(-[a-z0-9]+)*$",
                                        "maxLength": 255
                                    },
                                    "description": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "maxLength": 2000
                                    },
                                    "public": {
                                        "type": "boolean"
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "`GroupResource`",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "$ref": "#/components/schemas/GroupResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                }
                            }
                        }
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationException"
                    },
                    "404": {
                        "$ref": "#/components/responses/ModelNotFoundException"
                    },
                    "401": {
                        "$ref": "#/components/responses/AuthenticationException"
                    }
                }
            },
            "delete": {
                "operationId": "groups.destroy",
                "description": "Requires a token with the ability: `delete_groups`.",
                "tags": [
                    "Groups"
                ],
                "parameters": [
                    {
                        "name": "group",
                        "in": "path",
                        "required": true,
                        "description": "The group ID",
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "responses": {
                    "204": {
                        "description": "No content",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "array",
                                    "items": {}
                                }
                            }
                        }
                    },
                    "404": {
                        "$ref": "#/components/responses/ModelNotFoundException"
                    },
                    "401": {
                        "$ref": "#/components/responses/AuthenticationException"
                    }
                }
            }
        },
        "/me": {
            "get": {
                "operationId": "me",
                "tags": [
                    "Me"
                ],
                "responses": {
                    "200": {
                        "description": "",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "id": {
                                                    "type": "integer"
                                                },
                                                "name": {
                                                    "type": "string"
                                                },
                                                "email": {
                                                    "type": "string"
                                                },
                                                "type": {
                                                    "type": "string"
                                                },
                                                "role": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ]
                                                },
                                                "locale": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ]
                                                },
                                                "abilities": {
                                                    "type": "array",
                                                    "description": "The *effective* set, not the token's stored list: a token\nminted before a demotion still carries abilities its owner\nhas since lost, and reporting those would tell an\nintegration it can do things every request will refuse.\nEnsureTokenCan enforces exactly this intersection.",
                                                    "items": {}
                                                },
                                                "token": {
                                                    "type": "object",
                                                    "properties": {
                                                        "name": {
                                                            "type": "string"
                                                        },
                                                        "expires_at": {
                                                            "type": [
                                                                "string",
                                                                "null"
                                                            ]
                                                        }
                                                    },
                                                    "required": [
                                                        "name",
                                                        "expires_at"
                                                    ]
                                                }
                                            },
                                            "required": [
                                                "id",
                                                "name",
                                                "email",
                                                "type",
                                                "role",
                                                "locale",
                                                "abilities",
                                                "token"
                                            ]
                                        },
                                        "meta": {
                                            "type": "object",
                                            "properties": {
                                                "edition": {
                                                    "type": "string"
                                                },
                                                "capabilities": {
                                                    "type": "array",
                                                    "items": {}
                                                },
                                                "modules": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "string"
                                                    }
                                                },
                                                "version": {
                                                    "type": "string"
                                                }
                                            },
                                            "required": [
                                                "edition",
                                                "capabilities",
                                                "modules",
                                                "version"
                                            ]
                                        }
                                    },
                                    "required": [
                                        "data",
                                        "meta"
                                    ]
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/AuthenticationException"
                    }
                }
            }
        },
        "/roles": {
            "get": {
                "operationId": "roles.index",
                "description": "`client_scoped` roles are the ones for which `assigned_clients`\nmeans anything on a user; for any other role the assignment is\ncleared. `is_administrator` marks the roles that hold every\npermission, which only an administrator may hand out.\n\nThe Client system role is never listed: clients are not staff and\nare managed through `/clients`.\n\nRequires a token with the ability: `manage_users`.",
                "summary": "List the roles you may assign to a staff account",
                "tags": [
                    "Roles"
                ],
                "responses": {
                    "200": {
                        "description": "",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "array",
                                            "items": {
                                                "type": "object",
                                                "properties": {
                                                    "id": {
                                                        "type": "integer"
                                                    },
                                                    "name": {
                                                        "type": "string"
                                                    },
                                                    "is_system": {
                                                        "type": "boolean"
                                                    },
                                                    "is_administrator": {
                                                        "type": "boolean"
                                                    },
                                                    "client_scoped": {
                                                        "type": "boolean"
                                                    }
                                                },
                                                "required": [
                                                    "id",
                                                    "name",
                                                    "is_system",
                                                    "is_administrator",
                                                    "client_scoped"
                                                ]
                                            }
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/AuthenticationException"
                    }
                }
            }
        },
        "/users": {
            "get": {
                "operationId": "users.index",
                "description": "Clients never appear here \u2014 they are a different population with\ntheir own endpoints under `/clients`.\n\nRequires a token with the ability: `manage_users`.",
                "summary": "List staff accounts",
                "tags": [
                    "Users"
                ],
                "parameters": [
                    {
                        "name": "updated_since",
                        "in": "query",
                        "schema": {
                            "type": [
                                "string",
                                "null"
                            ],
                            "format": "date-time"
                        }
                    },
                    {
                        "name": "per_page",
                        "in": "query",
                        "schema": {
                            "type": [
                                "integer",
                                "null"
                            ],
                            "minimum": 1,
                            "maximum": 100
                        }
                    },
                    {
                        "name": "cursor",
                        "in": "query",
                        "schema": {
                            "type": [
                                "string",
                                "null"
                            ]
                        }
                    },
                    {
                        "name": "search",
                        "in": "query",
                        "schema": {
                            "type": [
                                "string",
                                "null"
                            ],
                            "maxLength": 255
                        }
                    },
                    {
                        "name": "role_id",
                        "in": "query",
                        "schema": {
                            "type": [
                                "integer",
                                "null"
                            ]
                        }
                    },
                    {
                        "name": "status",
                        "in": "query",
                        "schema": {
                            "type": [
                                "string",
                                "null"
                            ],
                            "enum": [
                                "active",
                                "inactive",
                                null
                            ]
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Paginated set of `StaffUserResource`",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "array",
                                            "items": {
                                                "$ref": "#/components/schemas/StaffUserResource"
                                            }
                                        },
                                        "links": {
                                            "type": "object",
                                            "properties": {
                                                "first": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ]
                                                },
                                                "last": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ]
                                                },
                                                "prev": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ]
                                                },
                                                "next": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ]
                                                }
                                            },
                                            "required": [
                                                "first",
                                                "last",
                                                "prev",
                                                "next"
                                            ]
                                        },
                                        "meta": {
                                            "type": "object",
                                            "properties": {
                                                "path": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "Base path for paginator generated URLs."
                                                },
                                                "per_page": {
                                                    "type": "integer",
                                                    "description": "Number of items shown per page.",
                                                    "minimum": 0
                                                },
                                                "next_cursor": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The \"cursor\" that points to the next set of items."
                                                },
                                                "prev_cursor": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The \"cursor\" that points to the previous set of items."
                                                }
                                            },
                                            "required": [
                                                "path",
                                                "per_page",
                                                "next_cursor",
                                                "prev_cursor"
                                            ]
                                        }
                                    },
                                    "required": [
                                        "data",
                                        "links",
                                        "meta"
                                    ]
                                }
                            }
                        }
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationException"
                    },
                    "401": {
                        "$ref": "#/components/responses/AuthenticationException"
                    }
                }
            },
            "post": {
                "operationId": "users.store",
                "description": "`role_id` must name a role the calling token's owner could grant.\nYou cannot hand out authority you do not hold: a caller who is not\nan administrator may not create one, nor assign any role carrying a\npermission they lack. `GET /roles` lists what is available to you.\n\nThe account is created active and with its email already verified \u2014\nan administrator vouched for the address by sending it.\n\nRequires a token with the ability: `create_users`.",
                "summary": "Create a staff account",
                "tags": [
                    "Users"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "name": {
                                        "type": "string",
                                        "maxLength": 255
                                    },
                                    "email": {
                                        "type": "string",
                                        "format": "email",
                                        "maxLength": 255
                                    },
                                    "role_id": {
                                        "type": "integer"
                                    },
                                    "password": {
                                        "type": "string",
                                        "description": "No `confirmed`: repeating a password defends against a human\nmistyping into a form, and an API caller has no second field\nto mistype. Password::defaults() still applies."
                                    },
                                    "assigned_clients": {
                                        "type": "array",
                                        "items": {
                                            "type": "integer"
                                        }
                                    }
                                },
                                "required": [
                                    "name",
                                    "email",
                                    "role_id",
                                    "password"
                                ]
                            }
                        }
                    }
                },
                "responses": {
                    "201": {
                        "description": "`StaffUserResource`",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "$ref": "#/components/schemas/StaffUserResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                }
                            }
                        }
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationException"
                    },
                    "401": {
                        "$ref": "#/components/responses/AuthenticationException"
                    }
                }
            }
        },
        "/users/{user}": {
            "get": {
                "operationId": "users.show",
                "description": "Adds `assigned_client_ids` and the `content` counts that `DELETE`\nneeds, neither of which the listing carries.\n\nRequires a token with the ability: `edit_users`.",
                "summary": "Get one staff account",
                "tags": [
                    "Users"
                ],
                "parameters": [
                    {
                        "name": "user",
                        "in": "path",
                        "required": true,
                        "description": "The user ID",
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "`StaffUserResource`",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "$ref": "#/components/schemas/StaffUserResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                }
                            }
                        }
                    },
                    "404": {
                        "$ref": "#/components/responses/ModelNotFoundException"
                    },
                    "401": {
                        "$ref": "#/components/responses/AuthenticationException"
                    }
                }
            },
            "patch": {
                "operationId": "users.update",
                "description": "PATCH semantics: an absent key means \"leave alone\", not \"clear\".\nSending `assigned_clients` replaces the whole list; omitting it\nleaves it, except that moving to a role which is not client-scoped\nclears it either way.\n\nRefused with a 422 if the change would leave the installation with\nno active administrator, or if you would be deactivating yourself.\n\nRequires a token with the ability: `edit_users`.",
                "summary": "Update a staff account, including the role assigned to it",
                "tags": [
                    "Users"
                ],
                "parameters": [
                    {
                        "name": "user",
                        "in": "path",
                        "required": true,
                        "description": "The user ID",
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "name": {
                                        "type": "string",
                                        "maxLength": 255
                                    },
                                    "email": {
                                        "type": "string",
                                        "format": "email",
                                        "maxLength": 255
                                    },
                                    "role_id": {
                                        "type": "integer"
                                    },
                                    "active": {
                                        "type": "boolean"
                                    },
                                    "password": {
                                        "type": [
                                            "string",
                                            "null"
                                        ]
                                    },
                                    "assigned_clients": {
                                        "type": "array",
                                        "items": {
                                            "type": "integer"
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "`StaffUserResource`",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "$ref": "#/components/schemas/StaffUserResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                }
                            }
                        }
                    },
                    "404": {
                        "$ref": "#/components/responses/ModelNotFoundException"
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationException"
                    },
                    "401": {
                        "$ref": "#/components/responses/AuthenticationException"
                    }
                }
            },
            "delete": {
                "operationId": "users.destroy",
                "description": "If the account owns no files or folders, no body is needed.\n\nIf it does, you must say what happens to that content: send\n`content_action` as either `cascade_delete` (delete it along with\nthe account) or `reassign`, and in the latter case a\n`reassign_to_id` naming the active account that inherits it.\nOmitting the choice is a 422 \u2014 there is no default, because one\nwould silently destroy files and the other would silently hand them\nto somebody else. `GET /users/{user}` reports the counts.\n\nYou cannot delete your own account, and you cannot delete the last\nactive administrator.\n\nRequires a token with the ability: `delete_users`.",
                "summary": "Delete a staff account",
                "tags": [
                    "Users"
                ],
                "parameters": [
                    {
                        "name": "user",
                        "in": "path",
                        "required": true,
                        "description": "The user ID",
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "responses": {
                    "204": {
                        "description": "No content",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "array",
                                    "items": {}
                                }
                            }
                        }
                    },
                    "404": {
                        "$ref": "#/components/responses/ModelNotFoundException"
                    },
                    "401": {
                        "$ref": "#/components/responses/AuthenticationException"
                    }
                }
            }
        },
        "/users/{user}/two-factor": {
            "delete": {
                "operationId": "users.two-factor.destroy",
                "description": "The remedy for a locked-out account: somebody whose authenticator\napp and recovery codes are both gone cannot sign in, and nobody else\ncan open the account for them either. Afterwards the account signs\nin with its password alone, and \u2014 if this installation enforces\ntwo-factor authentication for staff \u2014 is asked to enrol again on its\nnext request.\n\nThe account holder is emailed that this happened, and the action is\nrecorded in the activity log against the caller. Answers 204 whether\nor not a second factor was actually in force.\n\nRequires a token with the ability: `edit_users`.",
                "summary": "Remove a staff account's two-factor authentication",
                "tags": [
                    "Users"
                ],
                "parameters": [
                    {
                        "name": "user",
                        "in": "path",
                        "required": true,
                        "description": "The user ID",
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "responses": {
                    "204": {
                        "description": "No content",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "array",
                                    "items": {}
                                }
                            }
                        }
                    },
                    "404": {
                        "$ref": "#/components/responses/ModelNotFoundException"
                    },
                    "401": {
                        "$ref": "#/components/responses/AuthenticationException"
                    }
                }
            }
        }
    },
    "components": {
        "securitySchemes": {
            "http": {
                "type": "http",
                "scheme": "bearer"
            }
        },
        "schemas": {
            "ClientResource": {
                "type": "object",
                "properties": {
                    "id": {
                        "type": "integer"
                    },
                    "name": {
                        "type": "string"
                    },
                    "email": {
                        "type": "string"
                    },
                    "active": {
                        "type": "boolean"
                    },
                    "account_requested": {
                        "type": "boolean"
                    },
                    "two_factor_enabled": {
                        "type": "boolean",
                        "description": "Whether, not what: the state of the second factor is what a\ncaller needs to see before removing it. The secret and the\nrecovery codes stay where they are."
                    },
                    "created_at": {
                        "type": [
                            "string",
                            "null"
                        ]
                    },
                    "updated_at": {
                        "type": [
                            "string",
                            "null"
                        ]
                    },
                    "storage": {
                        "type": "object",
                        "properties": {
                            "quota_mb": {
                                "type": "integer",
                                "description": "The client's own column, where 0 means \"inherit the site\n default\" rather than \"unlimited\" \u2014 both are reported so a\ncaller need not know that rule to display it correctly."
                            },
                            "effective_quota_mb": {
                                "type": "integer"
                            },
                            "unlimited": {
                                "type": "boolean"
                            },
                            "used_mb": {
                                "type": "integer"
                            }
                        },
                        "required": [
                            "quota_mb",
                            "effective_quota_mb",
                            "unlimited",
                            "used_mb"
                        ]
                    },
                    "custom_fields": {
                        "type": "array",
                        "items": {
                            "type": "object",
                            "properties": {
                                "id": {
                                    "type": "integer"
                                },
                                "name": {
                                    "type": "string"
                                },
                                "label": {
                                    "type": "string"
                                },
                                "type": {
                                    "type": "string"
                                },
                                "value": {
                                    "type": [
                                        "string",
                                        "null"
                                    ]
                                }
                            },
                            "required": [
                                "id",
                                "name",
                                "label",
                                "type",
                                "value"
                            ]
                        }
                    },
                    "content": {
                        "type": "string"
                    }
                },
                "required": [
                    "id",
                    "name",
                    "email",
                    "active",
                    "account_requested",
                    "two_factor_enabled",
                    "created_at",
                    "updated_at",
                    "storage",
                    "custom_fields",
                    "content"
                ],
                "title": "ClientResource"
            },
            "CommentVisibility": {
                "type": "string",
                "description": "Who a comment is addressed to. Four fixed audiences, and the list never changes \u2014 it does not grow with the number of clients a file is shared with. An earlier version made staff pick a recipient from a dropdown of every client on the file before they could write, which is not how anybody answers a message and reached 51 entries on a file shared with a 50-client group. Answering one client is a reply now (see FileComments::post's $replyTo), so the audience of a reply is inherited from the comment it answers rather than chosen.  **`Clients` includes staff.** The name says who it *adds* \u2014 the team can already see everything on a file they can open. Read it as \"the team and  * the clients\", never as \"clients instead of staff\"; the label a person sees says so out loud, because the short name did not and somebody reasonably concluded there was no staff-and-clients option at all.  It is one channel seen from two ends, which is why its label depends on who is reading: staff address \"Staff and clients\", a client addresses \"Staff\". That asymmetry is real, not cosmetic \u2014 a client's comment carries their own conversation and never fans out to the other clients, so for them the audience genuinely is the team alone. Narrowing to a single client is `client_context_id`, not a separate case: see Access\\VisibleCommentScope.  The case names avoid `Private`/`Public`: those words already mean something else here (a *file's* public flag, and CommentScope's `public_files`), and reading `CommentVisibility::Public` next to `$file->public` invites exactly the confusion this feature cannot afford.\n",
                "enum": [
                    "only_me",
                    "staff_only",
                    "clients",
                    "everyone"
                ],
                "title": "CommentVisibility"
            },
            "DownloadLimitScope": {
                "type": "string",
                "description": "What a file's download limit counts. `Total` caps the file itself: once it has been downloaded that many times by anyone, nobody may download it again. `PerUser` gives every person their own allowance, so one client exhausting theirs leaves everyone else untouched.  Both come from ProjectSend v1, which stored them in `tbl_files.download_limit_type` under these exact names \u2014 an imported install keeps behaving the way its administrator set it up.  A closed set on purpose: DownloadAllowance branches on it, and a third value arriving from a database someone edited by hand should fail loudly at the cast rather than silently fall through to \"no limit\".\n",
                "enum": [
                    "total",
                    "per_user"
                ],
                "title": "DownloadLimitScope"
            },
            "FileCommentResource": {
                "type": "object",
                "properties": {
                    "id": {
                        "type": "integer"
                    },
                    "file_id": {
                        "type": "integer"
                    },
                    "body": {
                        "type": "string"
                    },
                    "visibility": {
                        "type": "string"
                    },
                    "author": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": [
                                    "integer",
                                    "null"
                                ]
                            },
                            "name": {
                                "type": "string"
                            },
                            "type": {
                                "type": "string",
                                "enum": [
                                    "guest",
                                    "staff",
                                    "client"
                                ]
                            }
                        },
                        "required": [
                            "id",
                            "name",
                            "type"
                        ]
                    },
                    "conversation": {
                        "type": [
                            "object",
                            "null"
                        ],
                        "description": "Whose conversation this is, when it is one client's rather\nthan every client's. Staff only, and null on a comment\naddressed to all of them.",
                        "properties": {
                            "client_id": {
                                "type": [
                                    "integer",
                                    "null"
                                ]
                            },
                            "client_name": {
                                "type": [
                                    "string",
                                    "null"
                                ]
                            }
                        },
                        "required": [
                            "client_id",
                            "client_name"
                        ]
                    },
                    "approved": {
                        "type": "boolean"
                    },
                    "created_at": {
                        "type": [
                            "string",
                            "null"
                        ]
                    },
                    "edited_at": {
                        "type": [
                            "string",
                            "null"
                        ]
                    }
                },
                "required": [
                    "id",
                    "file_id",
                    "body",
                    "visibility",
                    "author",
                    "conversation",
                    "approved",
                    "created_at",
                    "edited_at"
                ],
                "title": "FileCommentResource"
            },
            "FileResource": {
                "type": "object",
                "properties": {
                    "id": {
                        "type": "integer"
                    },
                    "name": {
                        "type": "string"
                    },
                    "slug": {
                        "type": "string"
                    },
                    "description": {
                        "type": [
                            "string",
                            "null"
                        ]
                    },
                    "original_name": {
                        "type": "string"
                    },
                    "mime_type": {
                        "type": "string"
                    },
                    "size": {
                        "type": "integer"
                    },
                    "checksum": {
                        "type": "string"
                    },
                    "public": {
                        "type": "boolean"
                    },
                    "commentable": {
                        "type": "boolean",
                        "description": "Only consulted while the installation's comment setting is\n\"only files marked as commentable\"; published anyway, since a\ncaller that sets it wants to read it back."
                    },
                    "expires_at": {
                        "type": [
                            "string",
                            "null"
                        ]
                    },
                    "expired": {
                        "type": "boolean"
                    },
                    "download_limit": {
                        "type": [
                            "integer",
                            "null"
                        ],
                        "description": "Null when the file may be downloaded any number of times.\n`download_limit_scope` says what the number counts \u2014\n\"total\" across everyone, or \"per_user\" for each person\nseparately. It is always one of those two, and is\nmeaningless while the limit is null."
                    },
                    "download_limit_scope": {
                        "type": "string"
                    },
                    "downloads_used": {
                        "type": "integer",
                        "description": "The file's total downloads. Under a per_user limit this is\nstill the total, since \"how much has this caller used\" is a\ndifferent number for every caller.",
                        "minimum": 0
                    },
                    "created_at": {
                        "type": [
                            "string",
                            "null"
                        ]
                    },
                    "updated_at": {
                        "type": [
                            "string",
                            "null"
                        ]
                    },
                    "is_revision": {
                        "type": "boolean",
                        "description": "True when this file is a new version of an earlier one. A\nrevision is always shared with the same people as the file it\nreplaces, so it has no recipients of its own: assigning it\nreturns 422, and `sharing_root_id` names the file to assign\ninstead."
                    },
                    "sharing_root_id": {
                        "type": [
                            "integer",
                            "null"
                        ],
                        "description": "The oldest file in this version chain \u2014 the one whose\nrecipients govern the whole chain. Null when this file is not\na revision."
                    },
                    "previous_version": {
                        "type": [
                            "object",
                            "null"
                        ],
                        "description": "The file this one replaces. Null when there is none, or when\nit is one you cannot see.",
                        "properties": {
                            "id": {
                                "type": "integer"
                            },
                            "name": {
                                "type": "string"
                            }
                        },
                        "required": [
                            "id",
                            "name"
                        ]
                    },
                    "next_version": {
                        "type": [
                            "object",
                            "null"
                        ],
                        "description": "The file that replaced this one, on the same terms.",
                        "properties": {
                            "id": {
                                "type": "integer"
                            },
                            "name": {
                                "type": "string"
                            }
                        },
                        "required": [
                            "id",
                            "name"
                        ]
                    },
                    "folder": {
                        "type": [
                            "object",
                            "null"
                        ],
                        "properties": {
                            "id": {
                                "type": "integer"
                            },
                            "name": {
                                "type": "string"
                            }
                        },
                        "required": [
                            "id",
                            "name"
                        ]
                    },
                    "uploaded_by": {
                        "type": [
                            "object",
                            "null"
                        ],
                        "description": "Name only. The uploader is a user record; their email address\nis not part of what \"this file exists\" needs to say.",
                        "properties": {
                            "id": {
                                "type": "integer"
                            },
                            "name": {
                                "type": "string"
                            }
                        },
                        "required": [
                            "id",
                            "name"
                        ]
                    },
                    "categories": {
                        "type": "array",
                        "items": {
                            "type": "object",
                            "properties": {
                                "id": {
                                    "type": "integer"
                                },
                                "name": {
                                    "type": "string"
                                }
                            },
                            "required": [
                                "id",
                                "name"
                            ]
                        }
                    },
                    "assignments": {
                        "type": "array",
                        "items": {
                            "type": "object",
                            "properties": {
                                "type": {
                                    "type": "string",
                                    "enum": [
                                        "group",
                                        "client"
                                    ]
                                },
                                "id": {
                                    "type": "integer"
                                },
                                "name": {
                                    "description": "getAttribute() rather than ->name: the relation is a\nMorphTo over User|Group, so the property is only\nknowable at runtime. Both targets carry a name."
                                }
                            },
                            "required": [
                                "type",
                                "id",
                                "name"
                            ]
                        }
                    },
                    "links": {
                        "type": "object",
                        "properties": {
                            "download": {
                                "type": "string"
                            }
                        },
                        "required": [
                            "download"
                        ]
                    }
                },
                "required": [
                    "id",
                    "name",
                    "slug",
                    "description",
                    "original_name",
                    "mime_type",
                    "size",
                    "checksum",
                    "public",
                    "commentable",
                    "expires_at",
                    "expired",
                    "download_limit",
                    "download_limit_scope",
                    "downloads_used",
                    "created_at",
                    "updated_at",
                    "is_revision",
                    "sharing_root_id",
                    "links"
                ],
                "title": "FileResource"
            },
            "GroupResource": {
                "type": "object",
                "properties": {
                    "id": {
                        "type": "integer"
                    },
                    "name": {
                        "type": "string"
                    },
                    "slug": {
                        "type": "string"
                    },
                    "description": {
                        "type": [
                            "string",
                            "null"
                        ]
                    },
                    "public": {
                        "type": "boolean"
                    },
                    "members_count": {
                        "type": "integer"
                    },
                    "created_at": {
                        "type": [
                            "string",
                            "null"
                        ]
                    },
                    "updated_at": {
                        "type": [
                            "string",
                            "null"
                        ]
                    },
                    "members": {
                        "type": "array",
                        "items": {
                            "type": "object",
                            "properties": {
                                "id": {
                                    "type": "integer"
                                },
                                "name": {
                                    "type": "string"
                                },
                                "email": {
                                    "type": "string"
                                }
                            },
                            "required": [
                                "id",
                                "name",
                                "email"
                            ]
                        }
                    }
                },
                "required": [
                    "id",
                    "name",
                    "slug",
                    "description",
                    "public",
                    "created_at",
                    "updated_at"
                ],
                "title": "GroupResource"
            },
            "StaffUserResource": {
                "type": "object",
                "properties": {
                    "id": {
                        "type": "integer"
                    },
                    "name": {
                        "type": "string"
                    },
                    "email": {
                        "type": "string"
                    },
                    "active": {
                        "type": "boolean"
                    },
                    "two_factor_enabled": {
                        "type": "boolean"
                    },
                    "role": {
                        "type": [
                            "object",
                            "null"
                        ],
                        "description": "Nested rather than a bare role_id, so a caller can render a\nlist without a second request. `is_administrator` is the flag\nthat actually matters when reading one of these.",
                        "properties": {
                            "id": {
                                "type": "integer"
                            },
                            "name": {
                                "type": "string"
                            },
                            "is_system": {
                                "type": "boolean"
                            },
                            "is_administrator": {
                                "type": "boolean"
                            },
                            "client_scoped": {
                                "type": "boolean"
                            }
                        },
                        "required": [
                            "id",
                            "name",
                            "is_system",
                            "is_administrator",
                            "client_scoped"
                        ]
                    },
                    "created_at": {
                        "type": [
                            "string",
                            "null"
                        ]
                    },
                    "updated_at": {
                        "type": [
                            "string",
                            "null"
                        ]
                    },
                    "assigned_client_ids": {
                        "type": "string"
                    },
                    "content": {
                        "type": "string"
                    }
                },
                "required": [
                    "id",
                    "name",
                    "email",
                    "active",
                    "two_factor_enabled",
                    "role",
                    "created_at",
                    "updated_at",
                    "assigned_client_ids",
                    "content"
                ],
                "title": "StaffUserResource"
            }
        },
        "responses": {
            "AuthenticationException": {
                "description": "Unauthenticated",
                "content": {
                    "application/json": {
                        "schema": {
                            "type": "object",
                            "properties": {
                                "message": {
                                    "type": "string",
                                    "description": "Error overview."
                                }
                            },
                            "required": [
                                "message"
                            ]
                        }
                    }
                }
            },
            "ValidationException": {
                "description": "Validation error",
                "content": {
                    "application/json": {
                        "schema": {
                            "type": "object",
                            "properties": {
                                "message": {
                                    "type": "string",
                                    "description": "Errors overview."
                                },
                                "errors": {
                                    "type": "object",
                                    "description": "A detailed description of each field that failed validation.",
                                    "additionalProperties": {
                                        "type": "array",
                                        "items": {
                                            "type": "string"
                                        }
                                    }
                                }
                            },
                            "required": [
                                "message",
                                "errors"
                            ]
                        }
                    }
                }
            },
            "AuthorizationException": {
                "description": "Authorization error",
                "content": {
                    "application/json": {
                        "schema": {
                            "type": "object",
                            "properties": {
                                "message": {
                                    "type": "string",
                                    "description": "Error overview."
                                }
                            },
                            "required": [
                                "message"
                            ]
                        }
                    }
                }
            },
            "ModelNotFoundException": {
                "description": "Not found",
                "content": {
                    "application/json": {
                        "schema": {
                            "type": "object",
                            "properties": {
                                "message": {
                                    "type": "string",
                                    "description": "Error overview."
                                }
                            },
                            "required": [
                                "message"
                            ]
                        }
                    }
                }
            }
        }
    }
}