{
  "openapi": "3.1.0",
  "info": {
    "title": "Nexo Share",
    "summary": "Self-hosted WeTransfer alternative — product REST API and documentation-site discovery API",
    "description": "Nexo Share is a self-hosted file transfer platform. The **product API** runs on each deployed instance (base path `/api`). The **documentation site** at https://nexoshare.nl exposes a small read-only discovery API. Agents should use this OpenAPI document for function-calling schemas and endpoint discovery.",
    "version": "1.0.0",
    "contact": {
      "name": "Nexo Share",
      "email": "info@nexoshare.nl",
      "url": "https://nexoshare.nl/contact"
    },
    "license": {
      "name": "MIT with Commons Clause",
      "url": "https://github.com/minemap-nl/nexoshare"
    }
  },
  "servers": [
    {
      "url": "https://nexoshare.nl",
      "description": "Public documentation site (discovery API only — does not store user files)"
    },
    {
      "url": "https://{instance}",
      "description": "Self-hosted Nexo Share product API (paths below include /api)",
      "variables": {
        "instance": {
          "default": "share.example.com",
          "description": "Hostname of your Nexo Share deployment"
        }
      }
    }
  ],
  "tags": [
    {
      "name": "Docs site",
      "description": "Read-only discovery endpoints on nexoshare.nl"
    },
    {
      "name": "Auth",
      "description": "Product API authentication (self-hosted instance)"
    },
    {
      "name": "Shares",
      "description": "Create and manage outbound file shares"
    },
    {
      "name": "Reverse shares",
      "description": "Guest upload / drop-off links"
    },
    {
      "name": "Public",
      "description": "Unauthenticated share access"
    },
    {
      "name": "Users",
      "description": "Admin user management"
    },
    {
      "name": "Config",
      "description": "Admin configuration"
    }
  ],
  "paths": {
    "/api/v1/docs": {
      "get": {
        "operationId": "listDocumentationPages",
        "tags": [
          "Docs site"
        ],
        "summary": "List Nexo Share documentation pages",
        "description": "Returns the documentation catalog for agents and developers, including links to OpenAPI and llms.txt.",
        "responses": {
          "200": {
            "description": "Documentation catalog",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DocsCatalog"
                }
              }
            }
          },
          "405": {
            "$ref": "#/components/responses/Problem"
          }
        }
      }
    },
    "/api/v1/docs/{slug}": {
      "get": {
        "operationId": "getDocumentationPage",
        "tags": [
          "Docs site"
        ],
        "summary": "Get one documentation page",
        "description": "Returns metadata and raw markdown for a single docs page by slug (for example `installation` or `api-reference`).",
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "description": "Documentation page id (filename without .md)",
            "schema": {
              "type": "string",
              "examples": [
                "installation",
                "api-reference",
                "cli-management"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Documentation page",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DocsPage"
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/Problem"
          },
          "405": {
            "$ref": "#/components/responses/Problem"
          }
        }
      }
    },
    "/openapi.json": {
      "get": {
        "operationId": "getOpenApiDocument",
        "tags": [
          "Docs site"
        ],
        "summary": "Download this OpenAPI document",
        "description": "Returns the OpenAPI 3.1 description for Nexo Share (docs site + product API).",
        "responses": {
          "200": {
            "description": "OpenAPI document",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          }
        }
      }
    },
    "/api/auth/login": {
      "post": {
        "operationId": "login",
        "tags": [
          "Auth"
        ],
        "summary": "Log in and obtain a session or JWT",
        "description": "Authenticate with email and password on a self-hosted instance. May return `requires2FA` when TOTP is enabled.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/LoginRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Authenticated or 2FA required",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/LoginSuccess"
                    },
                    {
                      "$ref": "#/components/schemas/LoginRequires2FA"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/ProductError"
          },
          "429": {
            "$ref": "#/components/responses/ProductError"
          }
        }
      }
    },
    "/api/auth/verify-2fa": {
      "post": {
        "operationId": "verify2fa",
        "tags": [
          "Auth"
        ],
        "summary": "Complete login with TOTP",
        "description": "Submit email, password, and 2FA code after login indicated `requires2FA`.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/Verify2FARequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "JWT and user",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TokenResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/ProductError"
          }
        }
      }
    },
    "/api/auth/logout": {
      "post": {
        "operationId": "logout",
        "tags": [
          "Auth"
        ],
        "summary": "Log out",
        "description": "Invalidate the current session/cookie on the self-hosted instance.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Logged out",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Success"
                }
              }
            }
          }
        }
      }
    },
    "/api/shares/init": {
      "post": {
        "operationId": "initShare",
        "tags": [
          "Shares"
        ],
        "summary": "Initialize a chunked share upload",
        "description": "Creates a share draft and returns `shareId` for subsequent chunk uploads.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ShareInitRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Share initialized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ShareInitResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/ProductError"
          }
        }
      }
    },
    "/api/shares/{shareId}/chunk": {
      "post": {
        "operationId": "uploadShareChunk",
        "tags": [
          "Shares"
        ],
        "summary": "Upload one file chunk",
        "description": "Upload a binary chunk for an initialized share. Repeat until all chunks are sent.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "shareId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "required": [
                  "chunk",
                  "chunkIndex",
                  "fileName",
                  "fileId"
                ],
                "properties": {
                  "chunk": {
                    "type": "string",
                    "format": "binary"
                  },
                  "chunkIndex": {
                    "type": "integer",
                    "minimum": 0
                  },
                  "fileName": {
                    "type": "string"
                  },
                  "fileId": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Chunk accepted",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Success"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/ProductError"
          },
          "413": {
            "$ref": "#/components/responses/ProductError"
          }
        }
      }
    },
    "/api/shares/{shareId}/finalize": {
      "post": {
        "operationId": "finalizeShare",
        "tags": [
          "Shares"
        ],
        "summary": "Finalize share after chunks",
        "description": "Marks the share complete and returns the public share URL.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "shareId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ShareFinalizeRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Share ready",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ShareFinalizeResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/ProductError"
          }
        }
      }
    },
    "/api/shares": {
      "get": {
        "operationId": "listShares",
        "tags": [
          "Shares"
        ],
        "summary": "List shares for the current user",
        "description": "Returns outbound shares created by the authenticated user.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Share list",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Share"
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/ProductError"
          }
        }
      }
    },
    "/api/shares/{shareId}": {
      "delete": {
        "operationId": "deleteShare",
        "tags": [
          "Shares"
        ],
        "summary": "Delete a share",
        "description": "Permanently delete a share and its files.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "shareId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Deleted",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Success"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/ProductError"
          },
          "404": {
            "$ref": "#/components/responses/ProductError"
          }
        }
      }
    },
    "/api/shares/{shareId}/download": {
      "get": {
        "operationId": "downloadShareZip",
        "tags": [
          "Public"
        ],
        "summary": "Download share as ZIP",
        "description": "Download all files in a share as a ZIP. May require prior password verification when protected.",
        "parameters": [
          {
            "name": "shareId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "ZIP body",
            "content": {
              "application/zip": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/ProductError"
          },
          "410": {
            "$ref": "#/components/responses/ProductError"
          }
        }
      }
    },
    "/api/shares/{shareId}/verify": {
      "post": {
        "operationId": "verifySharePassword",
        "tags": [
          "Public"
        ],
        "summary": "Verify share password",
        "description": "Unlock a password-protected share and return file metadata.",
        "parameters": [
          {
            "name": "shareId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "password"
                ],
                "properties": {
                  "password": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Password result",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ShareVerifyResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/ProductError"
          }
        }
      }
    },
    "/api/reverse": {
      "get": {
        "operationId": "listReverseShares",
        "tags": [
          "Reverse shares"
        ],
        "summary": "List reverse shares",
        "description": "List Reverse Share drop-off links owned by the authenticated user.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Reverse share list",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/ReverseShare"
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/ProductError"
          }
        }
      },
      "post": {
        "operationId": "createReverseShare",
        "tags": [
          "Reverse shares"
        ],
        "summary": "Create a reverse share",
        "description": "Create a guest upload link (Reverse Share) with optional password and size limits.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ReverseShareCreateRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ReverseShareCreateResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/ProductError"
          }
        }
      }
    },
    "/api/reverse/{reverseId}": {
      "delete": {
        "operationId": "deleteReverseShare",
        "tags": [
          "Reverse shares"
        ],
        "summary": "Delete a reverse share",
        "description": "Delete a Reverse Share and associated guest uploads.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "reverseId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Deleted",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Success"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/ProductError"
          },
          "404": {
            "$ref": "#/components/responses/ProductError"
          }
        }
      }
    },
    "/api/reverse/{reverseId}/files": {
      "get": {
        "operationId": "listReverseShareFiles",
        "tags": [
          "Reverse shares"
        ],
        "summary": "List files on a reverse share",
        "description": "List files guests uploaded to a Reverse Share.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "reverseId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "File list",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/ShareFile"
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/ProductError"
          }
        }
      }
    },
    "/api/public/shares/{shareId}": {
      "get": {
        "operationId": "getPublicShare",
        "tags": [
          "Public"
        ],
        "summary": "Get public share metadata",
        "description": "Public share info. When password-protected, `files` may be empty until verified.",
        "parameters": [
          {
            "name": "shareId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Share metadata",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicShare"
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/ProductError"
          },
          "410": {
            "$ref": "#/components/responses/ProductError"
          }
        }
      }
    },
    "/api/public/reverse/{reverseId}": {
      "get": {
        "operationId": "getPublicReverseShare",
        "tags": [
          "Public"
        ],
        "summary": "Get public reverse share metadata",
        "description": "Public Reverse Share info for the guest upload page.",
        "parameters": [
          {
            "name": "reverseId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Reverse share metadata",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicReverseShare"
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/ProductError"
          },
          "410": {
            "$ref": "#/components/responses/ProductError"
          }
        }
      }
    },
    "/api/users": {
      "get": {
        "operationId": "listUsers",
        "tags": [
          "Users"
        ],
        "summary": "List users (admin)",
        "description": "Admin-only list of user accounts.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Users",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/User"
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/ProductError"
          },
          "403": {
            "$ref": "#/components/responses/ProductError"
          }
        }
      },
      "post": {
        "operationId": "createUser",
        "tags": [
          "Users"
        ],
        "summary": "Create user (admin)",
        "description": "Admin-only user creation.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateUserRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Success"
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/ProductError"
          },
          "409": {
            "$ref": "#/components/responses/ProductError"
          }
        }
      }
    },
    "/api/users/{userId}": {
      "put": {
        "operationId": "updateUser",
        "tags": [
          "Users"
        ],
        "summary": "Update user (admin)",
        "description": "Admin-only user update.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "userId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateUserRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Success"
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/ProductError"
          },
          "404": {
            "$ref": "#/components/responses/ProductError"
          }
        }
      },
      "delete": {
        "operationId": "deleteUser",
        "tags": [
          "Users"
        ],
        "summary": "Delete user (admin)",
        "description": "Admin-only user deletion.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "userId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Deleted",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Success"
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/ProductError"
          },
          "404": {
            "$ref": "#/components/responses/ProductError"
          }
        }
      }
    },
    "/api/config": {
      "get": {
        "operationId": "getConfig",
        "tags": [
          "Config"
        ],
        "summary": "Get configuration",
        "description": "Admins receive full config; non-admins receive public branding fields only.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Config object",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/ProductError"
          }
        }
      },
      "put": {
        "operationId": "updateConfig",
        "tags": [
          "Config"
        ],
        "summary": "Update configuration (admin)",
        "description": "Admin-only partial config update.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": true
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Success"
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/ProductError"
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "JWT",
        "description": "JWT from login / verify-2fa. Cookie sessions are also used by the web UI."
      }
    },
    "schemas": {
      "Problem": {
        "type": "object",
        "required": [
          "type",
          "title",
          "status",
          "detail",
          "code"
        ],
        "properties": {
          "type": {
            "type": "string",
            "format": "uri"
          },
          "title": {
            "type": "string"
          },
          "status": {
            "type": "integer"
          },
          "detail": {
            "type": "string"
          },
          "code": {
            "type": "string"
          },
          "resolution_hint": {
            "type": "string"
          }
        }
      },
      "ProductError": {
        "type": "object",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "string",
            "description": "Human-readable error message from the self-hosted API"
          }
        }
      },
      "Success": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          }
        }
      },
      "DocsCatalog": {
        "type": "object",
        "properties": {
          "product": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "site": {
            "type": "string",
            "format": "uri"
          },
          "openapi": {
            "type": "string",
            "format": "uri"
          },
          "llms": {
            "type": "string",
            "format": "uri"
          },
          "developers": {
            "type": "string",
            "format": "uri"
          },
          "docs": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string"
                },
                "title": {
                  "type": "string"
                },
                "description": {
                  "type": "string"
                },
                "path": {
                  "type": "string"
                }
              }
            }
          }
        }
      },
      "DocsPage": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "title": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "path": {
            "type": "string"
          },
          "url": {
            "type": "string",
            "format": "uri"
          },
          "markdown_url": {
            "type": "string",
            "format": "uri"
          },
          "accept_hint": {
            "type": "string"
          },
          "markdown": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "LoginRequest": {
        "type": "object",
        "required": [
          "email",
          "password"
        ],
        "properties": {
          "email": {
            "type": "string",
            "format": "email"
          },
          "password": {
            "type": "string",
            "format": "password"
          }
        }
      },
      "LoginSuccess": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "token": {
            "type": "string"
          },
          "user": {
            "$ref": "#/components/schemas/User"
          }
        }
      },
      "LoginRequires2FA": {
        "type": "object",
        "required": [
          "requires2FA",
          "email"
        ],
        "properties": {
          "requires2FA": {
            "type": "boolean"
          },
          "email": {
            "type": "string",
            "format": "email"
          }
        }
      },
      "Verify2FARequest": {
        "type": "object",
        "required": [
          "email",
          "password",
          "code"
        ],
        "properties": {
          "email": {
            "type": "string",
            "format": "email"
          },
          "password": {
            "type": "string",
            "format": "password"
          },
          "code": {
            "type": "string",
            "pattern": "^[0-9]{6}$"
          }
        }
      },
      "TokenResponse": {
        "type": "object",
        "properties": {
          "token": {
            "type": "string"
          },
          "user": {
            "$ref": "#/components/schemas/User"
          }
        }
      },
      "User": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "email": {
            "type": "string",
            "format": "email"
          },
          "name": {
            "type": "string"
          },
          "is_admin": {
            "type": "boolean"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "ShareInitRequest": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string"
          },
          "password": {
            "type": "string"
          },
          "expirationVal": {
            "type": "integer"
          },
          "expirationUnit": {
            "type": "string",
            "enum": [
              "Hours",
              "Days",
              "Weeks",
              "Months"
            ]
          },
          "recipients": {
            "type": "string"
          },
          "message": {
            "type": "string"
          },
          "maxDownloads": {
            "type": "integer"
          }
        }
      },
      "ShareInitResponse": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "shareId": {
            "type": "string"
          }
        }
      },
      "ShareFinalizeRequest": {
        "type": "object",
        "required": [
          "files"
        ],
        "properties": {
          "files": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "fileName",
                "originalName",
                "fileId",
                "size"
              ],
              "properties": {
                "fileName": {
                  "type": "string"
                },
                "originalName": {
                  "type": "string"
                },
                "fileId": {
                  "type": "string"
                },
                "size": {
                  "type": "integer"
                },
                "mimeType": {
                  "type": "string"
                }
              }
            }
          }
        }
      },
      "ShareFinalizeResponse": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "shareUrl": {
            "type": "string",
            "format": "uri"
          }
        }
      },
      "Share": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "expires_at": {
            "type": "string",
            "format": "date-time"
          },
          "protected": {
            "type": "boolean"
          },
          "url": {
            "type": "string",
            "format": "uri"
          },
          "max_downloads": {
            "type": "integer"
          },
          "download_count": {
            "type": "integer"
          },
          "files": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ShareFile"
            }
          },
          "total_size": {
            "type": "integer"
          }
        }
      },
      "ShareFile": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "original_name": {
            "type": "string"
          },
          "size": {
            "type": "integer"
          },
          "mime_type": {
            "type": "string"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "ShareVerifyResponse": {
        "type": "object",
        "properties": {
          "valid": {
            "type": "boolean"
          },
          "files": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ShareFile"
            }
          }
        }
      },
      "PublicShare": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string"
          },
          "message": {
            "type": "string"
          },
          "protected": {
            "type": "boolean"
          },
          "files": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ShareFile"
            }
          }
        }
      },
      "ReverseShareCreateRequest": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string"
          },
          "maxSize": {
            "type": "integer"
          },
          "expirationVal": {
            "type": "integer"
          },
          "expirationUnit": {
            "type": "string",
            "enum": [
              "Hours",
              "Days",
              "Weeks",
              "Months"
            ]
          },
          "password": {
            "type": "string"
          },
          "notify": {
            "type": "boolean"
          },
          "sendEmailTo": {
            "type": "string",
            "format": "email"
          },
          "thankYouMessage": {
            "type": "string"
          }
        }
      },
      "ReverseShareCreateResponse": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "url": {
            "type": "string",
            "format": "uri"
          }
        }
      },
      "ReverseShare": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "max_size": {
            "type": "integer"
          },
          "expires_at": {
            "type": "string",
            "format": "date-time"
          },
          "notify_email": {
            "type": "boolean"
          },
          "url": {
            "type": "string",
            "format": "uri"
          },
          "file_count": {
            "type": "integer"
          }
        }
      },
      "PublicReverseShare": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string"
          },
          "maxSize": {
            "type": "integer"
          },
          "protected": {
            "type": "boolean"
          },
          "thankYouMessage": {
            "type": "string"
          }
        }
      },
      "CreateUserRequest": {
        "type": "object",
        "required": [
          "email",
          "password",
          "name"
        ],
        "properties": {
          "email": {
            "type": "string",
            "format": "email"
          },
          "password": {
            "type": "string",
            "format": "password"
          },
          "name": {
            "type": "string"
          },
          "is_admin": {
            "type": "boolean"
          }
        }
      },
      "UpdateUserRequest": {
        "type": "object",
        "properties": {
          "email": {
            "type": "string",
            "format": "email"
          },
          "name": {
            "type": "string"
          },
          "is_admin": {
            "type": "boolean"
          }
        }
      }
    },
    "responses": {
      "Problem": {
        "description": "RFC 9457 problem details (documentation site API)",
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            }
          }
        }
      },
      "ProductError": {
        "description": "JSON error from the self-hosted product API",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ProductError"
            }
          }
        }
      }
    }
  }
}
