{
  "openapi": "3.1.0",
  "info": {
    "title": "FacturaHub API",
    "version": "1.0.0",
    "summary": "REST API for AI-native invoicing & ERP (Spain). Also exposed as an MCP server for AI agents.",
    "description": "FacturaHub is an AI-native invoicing & light ERP for freelancers and SMEs in Spain. Everything is unlimited and free; the only metered resource is AI usage.\n\nThis REST API lets you create and manage invoices, clients, expenses, catalog items and tasks programmatically. The same capabilities are exposed as agent tools through a public **MCP server** (OAuth 2.0 / API key) at `/mcp`, so assistants like Claude, Cursor or ChatGPT can act on your data directly — see https://facturahub.com/es/spain/docs.\n\nAuthentication: send your API key in the `x-api-key` header, or a JWT in `Authorization: Bearer <token>` (obtained from `/auth/login`).",
    "contact": { "name": "FacturaHub", "url": "https://facturahub.com" },
    "license": { "name": "Proprietary" }
  },
  "servers": [
    { "url": "https://api.facturahub.com", "description": "Production API base (set to your API host)" }
  ],
  "security": [{ "ApiKeyAuth": [] }, { "BearerAuth": [] }],
  "tags": [
    { "name": "Auth", "description": "Register, log in and fetch the current account + AI token balance." },
    { "name": "Invoices", "description": "Create, send, mark paid and manage invoices (with VAT/IRPF, PDF, Verifactu)." },
    { "name": "Clients", "description": "Manage your client CRM (used by the POS too)." },
    { "name": "Expenses", "description": "Track expenses, scan receipts with AI (OCR), and pull P&L / VAT / cashflow." },
    { "name": "Catalog", "description": "Products & services with stock; used by the POS and WooCommerce." },
    { "name": "Tasks", "description": "Kanban tasks with assignees, priorities and due dates." },
    { "name": "Teams", "description": "Multi-user workspaces: members, roles, invites and team API keys." },
    { "name": "Context", "description": "Business context documentation fed to the AI agent (entries + executive summary)." },
    { "name": "Tax Declarations", "description": "Generate and manage periodic tax declarations (e.g. Modelo 303) from invoices & expenses." },
    { "name": "Vendors", "description": "Suppliers/vendors CRM, with expense and accounts-payable summaries." },
    { "name": "Supplier Invoices", "description": "Accounts payable: supplier invoices, payments, aging and alerts." },
    { "name": "E-invoice", "description": "Country-agnostic electronic invoicing facade (Verifactu/AEAT, Factura Fácil, etc.)." },
    { "name": "Cash Register", "description": "POS cash drawer: open, register movements, close with reconciliation." }
  ],
  "paths": {
    "/auth/register": {
      "post": {
        "tags": ["Auth"], "summary": "Register a new account", "security": [],
        "requestBody": { "required": true, "content": { "application/json": { "schema": {
          "type": "object", "required": ["email", "password"],
          "properties": {
            "email": { "type": "string", "format": "email" },
            "password": { "type": "string", "minLength": 8 },
            "country": { "type": "string", "example": "ES" },
            "currency": { "type": "string", "example": "EUR" }
          } } } } },
        "responses": { "200": { "description": "Account created", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AuthResponse" } } } }, "400": { "$ref": "#/components/responses/Error" } }
      }
    },
    "/auth/login": {
      "post": {
        "tags": ["Auth"], "summary": "Log in and obtain a JWT + API key", "security": [],
        "requestBody": { "required": true, "content": { "application/json": { "schema": {
          "type": "object", "required": ["email", "password"],
          "properties": { "email": { "type": "string", "format": "email" }, "password": { "type": "string" } } } } } },
        "responses": { "200": { "description": "Authenticated", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AuthResponse" } } } }, "401": { "$ref": "#/components/responses/Error" } }
      }
    },
    "/auth/me": {
      "get": {
        "tags": ["Auth"], "summary": "Current account, modules and AI token balance",
        "responses": { "200": { "description": "Account", "content": { "application/json": { "schema": {
          "type": "object", "properties": {
            "user": { "$ref": "#/components/schemas/User" },
            "tokens": { "$ref": "#/components/schemas/TokenBalance" },
            "modules": { "type": "array", "items": { "type": "string" } }
          } } } } }, "401": { "$ref": "#/components/responses/Error" } }
      }
    },
    "/api/invoices": {
      "get": {
        "tags": ["Invoices"], "summary": "List invoices",
        "parameters": [
          { "name": "status", "in": "query", "schema": { "type": "string", "enum": ["draft", "sent", "paid", "overdue"] } },
          { "name": "page", "in": "query", "schema": { "type": "integer", "minimum": 1 } },
          { "name": "search", "in": "query", "schema": { "type": "string" } }
        ],
        "responses": { "200": { "description": "List of invoices", "content": { "application/json": { "schema": { "type": "array", "items": { "$ref": "#/components/schemas/Invoice" } } } } }, "401": { "$ref": "#/components/responses/Error" } }
      },
      "post": {
        "tags": ["Invoices"], "summary": "Create an invoice",
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/InvoiceInput" } } } },
        "responses": { "201": { "description": "Created", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Invoice" } } } }, "400": { "$ref": "#/components/responses/Error" } }
      }
    },
    "/api/invoices/{id}": {
      "parameters": [{ "name": "id", "in": "path", "required": true, "schema": { "type": "string" } }],
      "get": { "tags": ["Invoices"], "summary": "Get an invoice", "responses": { "200": { "description": "Invoice", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Invoice" } } } }, "404": { "$ref": "#/components/responses/Error" } } },
      "put": { "tags": ["Invoices"], "summary": "Update an invoice", "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/InvoiceInput" } } } }, "responses": { "200": { "description": "Updated", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Invoice" } } } } } },
      "delete": { "tags": ["Invoices"], "summary": "Delete an invoice (soft delete)", "responses": { "200": { "description": "Deleted" } } }
    },
    "/api/invoices/{id}/pay": {
      "patch": { "tags": ["Invoices"], "summary": "Mark invoice as paid", "parameters": [{ "name": "id", "in": "path", "required": true, "schema": { "type": "string" } }], "requestBody": { "content": { "application/json": { "schema": { "type": "object", "properties": { "paidAt": { "type": "string", "format": "date" } } } } } }, "responses": { "200": { "description": "Marked paid", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Invoice" } } } } } }
    },
    "/api/invoices/{id}/send": {
      "patch": { "tags": ["Invoices"], "summary": "Send the invoice by email", "parameters": [{ "name": "id", "in": "path", "required": true, "schema": { "type": "string" } }], "responses": { "200": { "description": "Sent" } } }
    },
    "/api/invoices/{id}/duplicate": {
      "post": { "tags": ["Invoices"], "summary": "Duplicate an invoice", "parameters": [{ "name": "id", "in": "path", "required": true, "schema": { "type": "string" } }], "responses": { "201": { "description": "Duplicated", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Invoice" } } } } } }
    },
    "/api/invoices/{id}/pdf": {
      "get": { "tags": ["Invoices"], "summary": "Download the invoice PDF", "parameters": [{ "name": "id", "in": "path", "required": true, "schema": { "type": "string" } }], "responses": { "200": { "description": "PDF file", "content": { "application/pdf": { "schema": { "type": "string", "format": "binary" } } } } } }
    },
    "/api/clients": {
      "get": { "tags": ["Clients"], "summary": "List clients", "parameters": [{ "name": "search", "in": "query", "schema": { "type": "string" } }], "responses": { "200": { "description": "Clients", "content": { "application/json": { "schema": { "type": "array", "items": { "$ref": "#/components/schemas/Client" } } } } } } },
      "post": { "tags": ["Clients"], "summary": "Create a client", "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ClientInput" } } } }, "responses": { "201": { "description": "Created", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Client" } } } } } }
    },
    "/api/clients/{id}": {
      "parameters": [{ "name": "id", "in": "path", "required": true, "schema": { "type": "string" } }],
      "get": { "tags": ["Clients"], "summary": "Get a client", "responses": { "200": { "description": "Client", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Client" } } } } } },
      "put": { "tags": ["Clients"], "summary": "Update a client", "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ClientInput" } } } }, "responses": { "200": { "description": "Updated", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Client" } } } } } },
      "delete": { "tags": ["Clients"], "summary": "Delete a client", "responses": { "200": { "description": "Deleted" } } }
    },
    "/api/expenses": {
      "get": { "tags": ["Expenses"], "summary": "List expenses", "parameters": [{ "name": "category", "in": "query", "schema": { "type": "string" } }, { "name": "page", "in": "query", "schema": { "type": "integer" } }], "responses": { "200": { "description": "Expenses", "content": { "application/json": { "schema": { "type": "array", "items": { "$ref": "#/components/schemas/Expense" } } } } } } },
      "post": { "tags": ["Expenses"], "summary": "Create an expense", "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ExpenseInput" } } } }, "responses": { "201": { "description": "Created", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Expense" } } } } } }
    },
    "/api/expenses/{id}": {
      "parameters": [{ "name": "id", "in": "path", "required": true, "schema": { "type": "string" } }],
      "get": { "tags": ["Expenses"], "summary": "Get an expense", "responses": { "200": { "description": "Expense", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Expense" } } } } } },
      "put": { "tags": ["Expenses"], "summary": "Update an expense", "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ExpenseInput" } } } }, "responses": { "200": { "description": "Updated" } } },
      "delete": { "tags": ["Expenses"], "summary": "Delete an expense", "responses": { "200": { "description": "Deleted" } } }
    },
    "/api/expenses/scan-receipt": {
      "post": {
        "tags": ["Expenses"], "summary": "Extract expense data from a receipt image (AI/OCR)",
        "description": "Uses Claude Vision to read a receipt/ticket image and return structured expense data. Consumes 1 AI action (token).",
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": ["image"], "properties": { "image": { "type": "string", "description": "base64 data URL (image/jpeg|png|webp)" } } } } } },
        "responses": {
          "200": { "description": "Extracted fields", "content": { "application/json": { "schema": { "type": "object", "properties": { "description": { "type": "string" }, "amount": { "type": "number" }, "vendor": { "type": "string" }, "date": { "type": "string", "format": "date" }, "category": { "type": "string" }, "taxRate": { "type": "number" }, "currency": { "type": "string" } } } } } },
          "402": { "description": "Out of AI tokens — top up to continue", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }
        }
      }
    },
    "/api/expenses/profit-loss": { "get": { "tags": ["Expenses"], "summary": "Profit & loss report", "parameters": [{ "name": "from", "in": "query", "schema": { "type": "string", "format": "date" } }, { "name": "to", "in": "query", "schema": { "type": "string", "format": "date" } }], "responses": { "200": { "description": "P&L" } } } },
    "/api/expenses/tax-summary": { "get": { "tags": ["Expenses"], "summary": "VAT/tax summary for a period (Modelo 303 inputs)", "parameters": [{ "name": "quarter", "in": "query", "schema": { "type": "integer" } }, { "name": "year", "in": "query", "schema": { "type": "integer" } }], "responses": { "200": { "description": "Tax summary" } } } },
    "/api/expenses/cashflow": { "get": { "tags": ["Expenses"], "summary": "Cashflow report", "responses": { "200": { "description": "Cashflow" } } } },
    "/api/catalog": {
      "get": { "tags": ["Catalog"], "summary": "List catalog items", "parameters": [{ "name": "search", "in": "query", "schema": { "type": "string" } }, { "name": "type", "in": "query", "schema": { "type": "string", "enum": ["product", "service"] } }], "responses": { "200": { "description": "Items", "content": { "application/json": { "schema": { "type": "array", "items": { "$ref": "#/components/schemas/CatalogItem" } } } } } } },
      "post": { "tags": ["Catalog"], "summary": "Create a catalog item", "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CatalogItem" } } } }, "responses": { "201": { "description": "Created" } } }
    },
    "/api/catalog/categories": { "get": { "tags": ["Catalog"], "summary": "List catalog categories", "responses": { "200": { "description": "Categories" } } } },
    "/api/catalog/{id}": {
      "parameters": [{ "name": "id", "in": "path", "required": true, "schema": { "type": "string" } }],
      "put": { "tags": ["Catalog"], "summary": "Update a catalog item", "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CatalogItem" } } } }, "responses": { "200": { "description": "Updated" } } },
      "delete": { "tags": ["Catalog"], "summary": "Deactivate a catalog item", "responses": { "200": { "description": "Deactivated" } } }
    },
    "/api/catalog/{id}/stock": {
      "patch": { "tags": ["Catalog"], "summary": "Adjust stock", "parameters": [{ "name": "id", "in": "path", "required": true, "schema": { "type": "string" } }], "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "properties": { "delta": { "type": "number" }, "stock": { "type": "number" } } } } } }, "responses": { "200": { "description": "Adjusted" } } }
    },
    "/api/tasks": {
      "get": { "tags": ["Tasks"], "summary": "List tasks", "parameters": [{ "name": "status", "in": "query", "schema": { "type": "string" } }], "responses": { "200": { "description": "Tasks", "content": { "application/json": { "schema": { "type": "array", "items": { "$ref": "#/components/schemas/Task" } } } } } } },
      "post": { "tags": ["Tasks"], "summary": "Create a task", "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TaskInput" } } } }, "responses": { "201": { "description": "Created", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Task" } } } } } }
    },
    "/api/tasks/{id}": {
      "parameters": [{ "name": "id", "in": "path", "required": true, "schema": { "type": "string" } }],
      "get": { "tags": ["Tasks"], "summary": "Get a task", "responses": { "200": { "description": "Task", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Task" } } } } } },
      "put": { "tags": ["Tasks"], "summary": "Update a task", "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TaskInput" } } } }, "responses": { "200": { "description": "Updated" } } },
      "delete": { "tags": ["Tasks"], "summary": "Delete a task", "responses": { "200": { "description": "Deleted" } } }
    },
    "/api/tasks/{id}/status": {
      "patch": { "tags": ["Tasks"], "summary": "Change task status", "parameters": [{ "name": "id", "in": "path", "required": true, "schema": { "type": "string" } }], "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": ["status"], "properties": { "status": { "type": "string", "enum": ["backlog", "todo", "in_progress", "review", "done"] } } } } } }, "responses": { "200": { "description": "Updated" } } }
    },
    "/api/invoices/{id}/share": {
      "parameters": [{ "name": "id", "in": "path", "required": true, "schema": { "type": "string" } }],
      "post": { "tags": ["Invoices"], "summary": "Create a public shareable link for the invoice", "responses": { "200": { "description": "Share link", "content": { "application/json": { "schema": { "type": "object", "properties": { "shareToken": { "type": "string" }, "shareUrl": { "type": "string", "format": "uri" } } } } } }, "404": { "$ref": "#/components/responses/Error" } } },
      "delete": { "tags": ["Invoices"], "summary": "Revoke the invoice's shareable link", "responses": { "200": { "description": "Revoked", "content": { "application/json": { "schema": { "type": "object", "properties": { "ok": { "type": "boolean" } } } } } }, "404": { "$ref": "#/components/responses/Error" } } }
    },
    "/api/invoices/context": {
      "get": { "tags": ["Invoices"], "summary": "Financial context/summary (used by the AI agent)", "responses": { "200": { "description": "Financial context", "content": { "application/json": { "schema": { "type": "object", "additionalProperties": true } } } } } }
    },
    "/api/invoices/activity/feed": {
      "get": { "tags": ["Invoices"], "summary": "Recent team activity feed (requires team context)", "parameters": [{ "name": "limit", "in": "query", "schema": { "type": "integer", "maximum": 100, "default": 50 } }], "responses": { "200": { "description": "Activity feed", "content": { "application/json": { "schema": { "type": "array", "items": { "$ref": "#/components/schemas/ActivityLog" } } } } }, "400": { "$ref": "#/components/responses/Error" } } }
    },
    "/api/expenses/categorize": {
      "post": { "tags": ["Expenses"], "summary": "Suggest an expense category with AI", "description": "Uses Claude to classify an expense by description/vendor. Consumes 1 AI action (token).", "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "properties": { "description": { "type": "string" }, "vendor": { "type": "string" } } } } } }, "responses": { "200": { "description": "Suggested category", "content": { "application/json": { "schema": { "type": "object", "properties": { "category": { "type": "string" }, "confidence": { "type": "number", "minimum": 0, "maximum": 1 } } } } } }, "400": { "$ref": "#/components/responses/Error" }, "402": { "description": "Out of AI tokens — top up to continue", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } } }
    },
    "/api/expenses/vendors": {
      "get": { "tags": ["Expenses"], "summary": "List unique expense vendors (for autocomplete)", "responses": { "200": { "description": "Vendors", "content": { "application/json": { "schema": { "type": "array", "items": { "type": "object", "properties": { "name": { "type": "string" }, "count": { "type": "integer" }, "lastCategory": { "type": "string" } } } } } } } } }
    },
    "/api/expenses/vat-balance": {
      "get": { "tags": ["Expenses"], "summary": "VAT balance (output VAT minus deductible input VAT)", "parameters": [{ "name": "quarter", "in": "query", "schema": { "type": "integer" } }, { "name": "year", "in": "query", "schema": { "type": "integer" } }], "responses": { "200": { "description": "VAT balance", "content": { "application/json": { "schema": { "type": "object", "additionalProperties": true } } } } } }
    },
    "/api/expenses/income-summary": {
      "get": { "tags": ["Expenses"], "summary": "Income summary for a period", "parameters": [{ "name": "from", "in": "query", "schema": { "type": "string", "format": "date" } }, { "name": "to", "in": "query", "schema": { "type": "string", "format": "date" } }], "responses": { "200": { "description": "Income summary", "content": { "application/json": { "schema": { "type": "object", "additionalProperties": true } } } } } }
    },
    "/api/catalog/low-stock": {
      "get": { "tags": ["Catalog"], "summary": "List items at or below their low-stock threshold", "responses": { "200": { "description": "Items", "content": { "application/json": { "schema": { "type": "array", "items": { "$ref": "#/components/schemas/CatalogItem" } } } } } } }
    },
    "/api/catalog/export": {
      "get": { "tags": ["Catalog"], "summary": "Export the catalog as CSV", "responses": { "200": { "description": "CSV file", "content": { "text/csv": { "schema": { "type": "string" } } } } } }
    },
    "/api/catalog/import": {
      "post": { "tags": ["Catalog"], "summary": "Bulk-import catalog items from rows", "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": ["rows"], "properties": { "rows": { "type": "array", "maxItems": 500, "items": { "$ref": "#/components/schemas/CatalogItem" } } } } } } }, "responses": { "200": { "description": "Import result", "content": { "application/json": { "schema": { "type": "object", "properties": { "imported": { "type": "integer" }, "errors": { "type": "array", "items": { "type": "string" } } } } } } }, "400": { "$ref": "#/components/responses/Error" } } }
    },
    "/api/catalog/bulk-stock": {
      "post": { "tags": ["Catalog"], "summary": "Bulk stock adjustment", "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": ["adjustments"], "properties": { "adjustments": { "type": "array", "maxItems": 200, "items": { "type": "object", "properties": { "itemId": { "type": "string" }, "adjustment": { "type": "number" } } } } } } } } }, "responses": { "200": { "description": "Adjusted", "content": { "application/json": { "schema": { "type": "object", "properties": { "updated": { "type": "integer" } } } } } }, "400": { "$ref": "#/components/responses/Error" } } }
    },
    "/api/catalog/{id}/variant-stock": {
      "patch": { "tags": ["Catalog"], "summary": "Adjust stock of a product variant", "parameters": [{ "name": "id", "in": "path", "required": true, "schema": { "type": "string" } }], "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": ["variantIndex", "adjustment"], "properties": { "variantIndex": { "type": "integer" }, "adjustment": { "type": "number" } } } } } }, "responses": { "200": { "description": "Adjusted", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CatalogItem" } } } }, "400": { "$ref": "#/components/responses/Error" }, "404": { "$ref": "#/components/responses/Error" } } }
    },
    "/api/catalog/import-invoice": {
      "post": { "tags": ["Catalog"], "summary": "Analyze a supplier invoice image with AI", "description": "Uses Claude Vision to read a supplier (purchase) invoice and extract vendor + line items for catalog import. Consumes 1 AI action (token).", "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": ["image"], "properties": { "image": { "type": "string", "description": "base64 data URL (image/jpeg|png|gif|webp), max 10MB" } } } } } }, "responses": { "200": { "description": "Extracted analysis", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SupplierInvoiceAnalysis" } } } }, "400": { "$ref": "#/components/responses/Error" }, "402": { "description": "Out of AI tokens — top up to continue (OUT_OF_TOKENS)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "413": { "$ref": "#/components/responses/Error" } } }
    },
    "/api/catalog/confirm-import": {
      "post": { "tags": ["Catalog"], "summary": "Apply a confirmed supplier-invoice analysis to the catalog", "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": ["analysis"], "properties": { "analysis": { "$ref": "#/components/schemas/SupplierInvoiceAnalysis" }, "answers": { "type": "array", "items": { "type": "string" } } } } } } }, "responses": { "200": { "description": "Apply result", "content": { "application/json": { "schema": { "type": "object", "properties": { "created": { "type": "integer" }, "updated": { "type": "integer" }, "itemResults": { "type": "array", "items": { "type": "object", "properties": { "name": { "type": "string" }, "action": { "type": "string" } } } } } } } } }, "400": { "$ref": "#/components/responses/Error" } } }
    },
    "/api/tasks/my": {
      "get": { "tags": ["Tasks"], "summary": "Tasks assigned to the current user", "responses": { "200": { "description": "Tasks", "content": { "application/json": { "schema": { "type": "array", "items": { "$ref": "#/components/schemas/Task" } } } } } } }
    },
    "/api/tasks/overview": {
      "get": { "tags": ["Tasks"], "summary": "Task overview: counts by status and by assignee", "responses": { "200": { "description": "Overview", "content": { "application/json": { "schema": { "type": "object", "properties": { "byStatus": { "type": "object", "additionalProperties": { "type": "integer" } }, "byAssignee": { "type": "array", "items": { "type": "object", "properties": { "_id": { "type": "string" }, "name": { "type": "string" }, "email": { "type": "string" }, "count": { "type": "integer" } } } } } } } } } } }
    },
    "/api/tasks/{id}/assign": {
      "patch": { "tags": ["Tasks"], "summary": "Assign a task to a user", "parameters": [{ "name": "id", "in": "path", "required": true, "schema": { "type": "string" } }], "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": ["assignedTo"], "properties": { "assignedTo": { "type": "string", "description": "User ID (must be a team member)" } } } } } }, "responses": { "200": { "description": "Assigned", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Task" } } } }, "400": { "$ref": "#/components/responses/Error" }, "404": { "$ref": "#/components/responses/Error" } } }
    },
    "/api/tasks/{id}/complete": {
      "patch": { "tags": ["Tasks"], "summary": "Mark a task as done (must be in review)", "parameters": [{ "name": "id", "in": "path", "required": true, "schema": { "type": "string" } }], "responses": { "200": { "description": "Completed", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Task" } } } }, "400": { "$ref": "#/components/responses/Error" }, "404": { "$ref": "#/components/responses/Error" } } }
    },
    "/api/tasks/{id}/history": {
      "get": { "tags": ["Tasks"], "summary": "Activity history for a task", "parameters": [{ "name": "id", "in": "path", "required": true, "schema": { "type": "string" } }], "responses": { "200": { "description": "History", "content": { "application/json": { "schema": { "type": "array", "items": { "$ref": "#/components/schemas/ActivityLog" } } } } }, "404": { "$ref": "#/components/responses/Error" } } }
    },
    "/api/teams": {
      "post": { "tags": ["Teams"], "summary": "Create a team", "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": ["name", "country"], "properties": { "name": { "type": "string" }, "company": { "type": "string" }, "country": { "type": "string" }, "currency": { "type": "string" }, "taxId": { "type": "string" }, "logo": { "type": "string" } } } } } }, "responses": { "201": { "description": "Created", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Team" } } } }, "400": { "$ref": "#/components/responses/Error" } } }
    },
    "/api/teams/current": {
      "get": { "tags": ["Teams"], "summary": "Get the active team and its members", "responses": { "200": { "description": "Active team", "content": { "application/json": { "schema": { "type": "object", "properties": { "team": { "$ref": "#/components/schemas/Team" }, "members": { "type": "array", "items": { "$ref": "#/components/schemas/TeamMember" } } } } } } }, "404": { "$ref": "#/components/responses/Error" } } },
      "put": { "tags": ["Teams"], "summary": "Update the active team's profile (owner/admin)", "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TeamInput" } } } }, "responses": { "200": { "description": "Updated", "content": { "application/json": { "schema": { "type": "object", "properties": { "team": { "$ref": "#/components/schemas/Team" } } } } } } } }
    },
    "/api/teams/current/invite": {
      "post": { "tags": ["Teams"], "summary": "Invite a member by email (owner/admin)", "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": ["email"], "properties": { "email": { "type": "string", "format": "email" }, "role": { "type": "string", "enum": ["admin", "finance", "operations", "member", "viewer"], "default": "member" } } } } } }, "responses": { "201": { "description": "Member added", "content": { "application/json": { "schema": { "type": "object", "properties": { "member": { "$ref": "#/components/schemas/TeamMember" } } } } } }, "400": { "$ref": "#/components/responses/Error" }, "403": { "$ref": "#/components/responses/Error" }, "404": { "description": "User not registered — invitation email sent", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } } }
    },
    "/api/teams/current/members": {
      "get": { "tags": ["Teams"], "summary": "List members of the active team", "responses": { "200": { "description": "Members", "content": { "application/json": { "schema": { "type": "array", "items": { "$ref": "#/components/schemas/TeamMember" } } } } }, "404": { "$ref": "#/components/responses/Error" } } }
    },
    "/api/teams/current/members/{memberId}/role": {
      "patch": { "tags": ["Teams"], "summary": "Change a member's role (owner/admin)", "parameters": [{ "name": "memberId", "in": "path", "required": true, "schema": { "type": "string" } }], "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": ["role"], "properties": { "role": { "type": "string", "enum": ["admin", "finance", "operations", "member", "viewer"] } } } } } }, "responses": { "200": { "description": "Updated", "content": { "application/json": { "schema": { "type": "object", "properties": { "member": { "$ref": "#/components/schemas/TeamMember" } } } } } }, "400": { "$ref": "#/components/responses/Error" }, "404": { "$ref": "#/components/responses/Error" } } }
    },
    "/api/teams/current/members/{memberId}": {
      "delete": { "tags": ["Teams"], "summary": "Remove a member from the active team (owner/admin)", "parameters": [{ "name": "memberId", "in": "path", "required": true, "schema": { "type": "string" } }], "responses": { "200": { "description": "Removed" }, "400": { "$ref": "#/components/responses/Error" }, "404": { "$ref": "#/components/responses/Error" } } }
    },
    "/api/teams/current/regenerate-key": {
      "post": { "tags": ["Teams"], "summary": "Regenerate the team API key (owner only)", "responses": { "200": { "description": "New API key", "content": { "application/json": { "schema": { "type": "object", "properties": { "apiKey": { "type": "string" } } } } } } } }
    },
    "/api/teams/switch/{teamId}": {
      "post": { "tags": ["Teams"], "summary": "Switch the active team", "parameters": [{ "name": "teamId", "in": "path", "required": true, "schema": { "type": "string" } }], "responses": { "200": { "description": "Switched", "content": { "application/json": { "schema": { "type": "object", "properties": { "team": { "$ref": "#/components/schemas/Team" } } } } } }, "403": { "$ref": "#/components/responses/Error" } } }
    },
    "/api/teams/my-teams": {
      "get": { "tags": ["Teams"], "summary": "List all teams the user belongs to", "responses": { "200": { "description": "Teams", "content": { "application/json": { "schema": { "type": "array", "items": { "allOf": [{ "$ref": "#/components/schemas/Team" }, { "type": "object", "properties": { "role": { "type": "string" }, "isActive": { "type": "boolean" } } }] } } } } } } }
    },
    "/api/teams/my-role": {
      "get": { "tags": ["Teams"], "summary": "Current user's role in the active team", "responses": { "200": { "description": "Role", "content": { "application/json": { "schema": { "type": "object", "properties": { "role": { "type": "string" }, "teamId": { "type": "string", "nullable": true } } } } } }, "404": { "$ref": "#/components/responses/Error" } } }
    },
    "/api/context": {
      "get": { "tags": ["Context"], "summary": "Get the full business context document", "responses": { "200": { "description": "Business context", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BusinessContext" } } } } } }
    },
    "/api/context/markdown": {
      "get": { "tags": ["Context"], "summary": "Get the business context rendered as AI-optimized markdown", "responses": { "200": { "description": "Markdown", "content": { "application/json": { "schema": { "type": "object", "properties": { "markdown": { "type": "string" }, "entryCount": { "type": "integer" } } } } } } } }
    },
    "/api/context/entry": {
      "put": { "tags": ["Context"], "summary": "Create or update a context entry by key (owner/admin)", "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BusinessEntry" } } } }, "responses": { "200": { "description": "Entry updated", "content": { "application/json": { "schema": { "type": "object", "properties": { "message": { "type": "string" }, "entry": { "$ref": "#/components/schemas/BusinessEntry" } } } } } }, "201": { "description": "Entry created", "content": { "application/json": { "schema": { "type": "object", "properties": { "message": { "type": "string" }, "entry": { "$ref": "#/components/schemas/BusinessEntry" } } } } } }, "400": { "$ref": "#/components/responses/Error" }, "403": { "$ref": "#/components/responses/Error" } } }
    },
    "/api/context/entry/{key}": {
      "delete": { "tags": ["Context"], "summary": "Remove a context entry by key (owner/admin)", "parameters": [{ "name": "key", "in": "path", "required": true, "schema": { "type": "string" } }], "responses": { "200": { "description": "Removed" }, "403": { "$ref": "#/components/responses/Error" }, "404": { "$ref": "#/components/responses/Error" } } }
    },
    "/api/context/summary": {
      "put": { "tags": ["Context"], "summary": "Update the executive summary (owner/admin)", "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": ["summary"], "properties": { "summary": { "type": "string", "maxLength": 5000 } } } } } }, "responses": { "200": { "description": "Summary updated" }, "400": { "$ref": "#/components/responses/Error" }, "403": { "$ref": "#/components/responses/Error" } } }
    },
    "/api/tax-declarations/supported": {
      "get": { "tags": ["Tax Declarations"], "summary": "List supported countries", "responses": { "200": { "description": "Supported countries", "content": { "application/json": { "schema": { "type": "object", "properties": { "countries": { "type": "array", "items": { "type": "string" } } } } } } } } }
    },
    "/api/tax-declarations/generate": {
      "post": { "tags": ["Tax Declarations"], "summary": "Generate (or regenerate) a tax declaration", "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": ["country", "year", "period"], "properties": { "country": { "type": "string", "example": "ES" }, "year": { "type": "integer", "minimum": 2000, "maximum": 2100 }, "period": { "type": "string", "example": "Q1" } } } } } }, "responses": { "200": { "description": "Generated", "content": { "application/json": { "schema": { "type": "object", "properties": { "declaration": { "$ref": "#/components/schemas/TaxDeclaration" }, "invoiceCount": { "type": "integer" }, "expenseCount": { "type": "integer" } } } } } }, "400": { "$ref": "#/components/responses/Error" } } }
    },
    "/api/tax-declarations": {
      "get": { "tags": ["Tax Declarations"], "summary": "List tax declarations", "parameters": [{ "name": "country", "in": "query", "schema": { "type": "string" } }, { "name": "year", "in": "query", "schema": { "type": "integer" } }], "responses": { "200": { "description": "Declarations", "content": { "application/json": { "schema": { "type": "object", "properties": { "declarations": { "type": "array", "items": { "$ref": "#/components/schemas/TaxDeclaration" } } } } } } } } }
    },
    "/api/tax-declarations/{id}": {
      "parameters": [{ "name": "id", "in": "path", "required": true, "schema": { "type": "string" } }],
      "get": { "tags": ["Tax Declarations"], "summary": "Get a tax declaration", "responses": { "200": { "description": "Declaration", "content": { "application/json": { "schema": { "type": "object", "properties": { "declaration": { "$ref": "#/components/schemas/TaxDeclaration" } } } } } }, "404": { "$ref": "#/components/responses/Error" } } },
      "patch": { "tags": ["Tax Declarations"], "summary": "Update manual overrides / notes (draft only)", "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "properties": { "manualOverrides": { "type": "object", "additionalProperties": true }, "notes": { "type": "string", "maxLength": 5000 } } } } } }, "responses": { "200": { "description": "Updated", "content": { "application/json": { "schema": { "type": "object", "properties": { "declaration": { "$ref": "#/components/schemas/TaxDeclaration" } } } } } }, "400": { "$ref": "#/components/responses/Error" }, "404": { "$ref": "#/components/responses/Error" } } }
    },
    "/api/tax-declarations/{id}/submit": {
      "patch": { "tags": ["Tax Declarations"], "summary": "Mark a declaration as submitted (draft only)", "parameters": [{ "name": "id", "in": "path", "required": true, "schema": { "type": "string" } }], "responses": { "200": { "description": "Submitted", "content": { "application/json": { "schema": { "type": "object", "properties": { "declaration": { "$ref": "#/components/schemas/TaxDeclaration" } } } } } }, "404": { "$ref": "#/components/responses/Error" } } }
    },
    "/api/vendors": {
      "get": { "tags": ["Vendors"], "summary": "List vendors", "parameters": [{ "name": "search", "in": "query", "schema": { "type": "string" } }, { "name": "page", "in": "query", "schema": { "type": "integer", "minimum": 1 } }, { "name": "limit", "in": "query", "schema": { "type": "integer" } }], "responses": { "200": { "description": "Vendors", "content": { "application/json": { "schema": { "type": "array", "items": { "$ref": "#/components/schemas/Vendor" } } } } } } },
      "post": { "tags": ["Vendors"], "summary": "Create a vendor", "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/VendorInput" } } } }, "responses": { "201": { "description": "Created", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Vendor" } } } }, "400": { "$ref": "#/components/responses/Error" }, "409": { "$ref": "#/components/responses/Error" } } }
    },
    "/api/vendors/{id}": {
      "parameters": [{ "name": "id", "in": "path", "required": true, "schema": { "type": "string" } }],
      "get": { "tags": ["Vendors"], "summary": "Get a vendor with expense summary", "responses": { "200": { "description": "Vendor", "content": { "application/json": { "schema": { "allOf": [{ "$ref": "#/components/schemas/Vendor" }, { "type": "object", "properties": { "summary": { "type": "object", "properties": { "totalSpent": { "type": "number" }, "expenseCount": { "type": "integer" }, "lastExpenseDate": { "type": "string", "format": "date", "nullable": true }, "categories": { "type": "array", "items": { "type": "string" } } } } } }] } } } }, "404": { "$ref": "#/components/responses/Error" } } },
      "put": { "tags": ["Vendors"], "summary": "Update a vendor", "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/VendorInput" } } } }, "responses": { "200": { "description": "Updated", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Vendor" } } } }, "400": { "$ref": "#/components/responses/Error" }, "404": { "$ref": "#/components/responses/Error" } } },
      "delete": { "tags": ["Vendors"], "summary": "Delete a vendor (only if no expenses reference it)", "responses": { "200": { "description": "Deleted" }, "400": { "$ref": "#/components/responses/Error" }, "404": { "$ref": "#/components/responses/Error" } } }
    },
    "/api/vendors/{id}/expenses": {
      "get": { "tags": ["Vendors"], "summary": "List expenses for a vendor", "parameters": [{ "name": "id", "in": "path", "required": true, "schema": { "type": "string" } }], "responses": { "200": { "description": "Expenses", "content": { "application/json": { "schema": { "type": "array", "items": { "$ref": "#/components/schemas/Expense" } } } } }, "404": { "$ref": "#/components/responses/Error" } } }
    },
    "/api/supplier-invoices": {
      "get": { "tags": ["Supplier Invoices"], "summary": "List supplier invoices", "parameters": [{ "name": "vendorId", "in": "query", "schema": { "type": "string" } }, { "name": "status", "in": "query", "schema": { "type": "string", "enum": ["pending", "partial", "paid", "overdue", "cancelled"] } }, { "name": "overdue", "in": "query", "schema": { "type": "boolean" } }, { "name": "dateFrom", "in": "query", "schema": { "type": "string", "format": "date" } }, { "name": "dateTo", "in": "query", "schema": { "type": "string", "format": "date" } }, { "name": "amountMin", "in": "query", "schema": { "type": "number" } }, { "name": "amountMax", "in": "query", "schema": { "type": "number" } }, { "name": "search", "in": "query", "schema": { "type": "string" } }, { "name": "sort", "in": "query", "schema": { "type": "string", "enum": ["invoiceDate", "dueDate", "total", "balance", "status", "createdAt"] } }, { "name": "order", "in": "query", "schema": { "type": "string", "enum": ["asc", "desc"] } }, { "name": "page", "in": "query", "schema": { "type": "integer", "minimum": 1 } }], "responses": { "200": { "description": "Supplier invoices", "content": { "application/json": { "schema": { "type": "array", "items": { "$ref": "#/components/schemas/SupplierInvoice" } } } } } } },
      "post": { "tags": ["Supplier Invoices"], "summary": "Create a supplier invoice", "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SupplierInvoiceInput" } } } }, "responses": { "201": { "description": "Created", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SupplierInvoice" } } } }, "400": { "$ref": "#/components/responses/Error" }, "404": { "$ref": "#/components/responses/Error" }, "409": { "$ref": "#/components/responses/Error" } } }
    },
    "/api/supplier-invoices/summary": {
      "get": { "tags": ["Supplier Invoices"], "summary": "Accounts-payable dashboard summary", "responses": { "200": { "description": "Summary", "content": { "application/json": { "schema": { "type": "object", "properties": { "totalPending": { "type": "number" }, "totalOverdue": { "type": "number" }, "upcomingDueCount": { "type": "integer" }, "monthPayments": { "type": "number" }, "monthPaymentCount": { "type": "integer" }, "activeVendors": { "type": "integer" }, "partialCount": { "type": "integer" } } } } } } } }
    },
    "/api/supplier-invoices/aging": {
      "get": { "tags": ["Supplier Invoices"], "summary": "Aging report (outstanding balances by bucket)", "responses": { "200": { "description": "Aging report", "content": { "application/json": { "schema": { "type": "object", "properties": { "buckets": { "type": "object", "properties": { "current": { "type": "number" }, "days30": { "type": "number" }, "days60": { "type": "number" }, "days90": { "type": "number" }, "days120": { "type": "number" }, "over120": { "type": "number" } } }, "details": { "type": "object", "additionalProperties": { "type": "array", "items": { "$ref": "#/components/schemas/SupplierInvoice" } } } } } } } } } }
    },
    "/api/supplier-invoices/accounts-payable": {
      "get": { "tags": ["Supplier Invoices"], "summary": "Accounts payable grouped by vendor", "responses": { "200": { "description": "Accounts payable", "content": { "application/json": { "schema": { "type": "array", "items": { "type": "object", "properties": { "vendorId": { "type": "string" }, "vendorName": { "type": "string" }, "vendorTaxId": { "type": "string" }, "totalInvoiced": { "type": "number" }, "totalPaid": { "type": "number" }, "balance": { "type": "number" }, "invoiceCount": { "type": "integer" }, "overdueCount": { "type": "integer" }, "nextDue": { "type": "string", "format": "date" } } } } } } } } }
    },
    "/api/supplier-invoices/alerts": {
      "get": { "tags": ["Supplier Invoices"], "summary": "Upcoming and overdue supplier invoices", "responses": { "200": { "description": "Alerts", "content": { "application/json": { "schema": { "type": "object", "properties": { "dueToday": { "type": "array", "items": { "$ref": "#/components/schemas/SupplierInvoice" } }, "dueIn7Days": { "type": "array", "items": { "$ref": "#/components/schemas/SupplierInvoice" } }, "overdue": { "type": "array", "items": { "$ref": "#/components/schemas/SupplierInvoice" } }, "overdue30Plus": { "type": "array", "items": { "$ref": "#/components/schemas/SupplierInvoice" } } } } } } } } }
    },
    "/api/supplier-invoices/payments/all": {
      "get": { "tags": ["Supplier Invoices"], "summary": "List all supplier payments (payment history)", "parameters": [{ "name": "vendorId", "in": "query", "schema": { "type": "string" } }, { "name": "paymentMethod", "in": "query", "schema": { "type": "string" } }, { "name": "dateFrom", "in": "query", "schema": { "type": "string", "format": "date" } }, { "name": "dateTo", "in": "query", "schema": { "type": "string", "format": "date" } }, { "name": "page", "in": "query", "schema": { "type": "integer", "minimum": 1 } }], "responses": { "200": { "description": "Payments", "content": { "application/json": { "schema": { "type": "array", "items": { "$ref": "#/components/schemas/SupplierPayment" } } } } } } }
    },
    "/api/supplier-invoices/{id}": {
      "get": { "tags": ["Supplier Invoices"], "summary": "Get a supplier invoice with its payments", "parameters": [{ "name": "id", "in": "path", "required": true, "schema": { "type": "string" } }], "responses": { "200": { "description": "Supplier invoice", "content": { "application/json": { "schema": { "allOf": [{ "$ref": "#/components/schemas/SupplierInvoice" }, { "type": "object", "properties": { "payments": { "type": "array", "items": { "$ref": "#/components/schemas/SupplierPayment" } } } }] } } } }, "404": { "$ref": "#/components/responses/Error" } } }
    },
    "/api/supplier-invoices/{id}/payments": {
      "parameters": [{ "name": "id", "in": "path", "required": true, "schema": { "type": "string" } }],
      "get": { "tags": ["Supplier Invoices"], "summary": "List payments for a supplier invoice", "responses": { "200": { "description": "Payments", "content": { "application/json": { "schema": { "type": "array", "items": { "$ref": "#/components/schemas/SupplierPayment" } } } } }, "404": { "$ref": "#/components/responses/Error" } } },
      "post": { "tags": ["Supplier Invoices"], "summary": "Register a payment on a supplier invoice", "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": ["amount", "paymentMethod"], "properties": { "amount": { "type": "number" }, "paymentDate": { "type": "string", "format": "date" }, "paymentMethod": { "type": "string" }, "bank": { "type": "string" }, "reference": { "type": "string" }, "notes": { "type": "string" }, "attachmentUrl": { "type": "string" } } } } } }, "responses": { "201": { "description": "Payment registered", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SupplierPayment" } } } }, "400": { "$ref": "#/components/responses/Error" }, "404": { "$ref": "#/components/responses/Error" } } }
    },
    "/api/supplier-invoices/{id}/cancel": {
      "put": { "tags": ["Supplier Invoices"], "summary": "Cancel a supplier invoice", "parameters": [{ "name": "id", "in": "path", "required": true, "schema": { "type": "string" } }], "requestBody": { "content": { "application/json": { "schema": { "type": "object", "properties": { "reason": { "type": "string" } } } } } }, "responses": { "200": { "description": "Cancelled", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SupplierInvoice" } } } }, "400": { "$ref": "#/components/responses/Error" }, "404": { "$ref": "#/components/responses/Error" } } }
    },
    "/api/einvoice/providers": {
      "get": { "tags": ["E-invoice"], "summary": "List available e-invoice providers for your country", "responses": { "200": { "description": "Providers", "content": { "application/json": { "schema": { "type": "object", "properties": { "country": { "type": "string" }, "hasEInvoice": { "type": "boolean" }, "hasPAC": { "type": "boolean" }, "supportedCountries": { "type": "array", "items": { "type": "string" } } } } } } } } }
    },
    "/api/einvoice/emit": {
      "post": { "tags": ["E-invoice"], "summary": "Emit an invoice through the country's e-invoice system", "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": ["invoiceId"], "properties": { "invoiceId": { "type": "string" }, "pos": { "type": "string" }, "receiverType": { "type": "string" }, "paymentType": { "type": "string" }, "saleType": { "type": "string" }, "receiverDv": { "type": "string" }, "receiverEmail": { "type": "string", "format": "email" }, "receiverLocation": { "type": "string" }, "receiverRucType": { "type": "string" } } } } } }, "responses": { "200": { "description": "Emitted", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/EInvoiceResult" } } } }, "400": { "$ref": "#/components/responses/Error" }, "402": { "description": "E-invoice plan limit reached", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "404": { "$ref": "#/components/responses/Error" }, "422": { "description": "Rejected by the fiscal authority", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } } }
    },
    "/api/einvoice/status/{id}": {
      "get": { "tags": ["E-invoice"], "summary": "Check a fiscal document's status", "parameters": [{ "name": "id", "in": "path", "required": true, "schema": { "type": "string" } }], "responses": { "200": { "description": "Status", "content": { "application/json": { "schema": { "type": "object", "additionalProperties": true } } } }, "400": { "$ref": "#/components/responses/Error" } } }
    },
    "/api/einvoice/annul": {
      "post": { "tags": ["E-invoice"], "summary": "Annul a fiscal document", "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": ["fiscalId", "reason"], "properties": { "fiscalId": { "type": "string" }, "reason": { "type": "string" } } } } } }, "responses": { "200": { "description": "Annulled", "content": { "application/json": { "schema": { "type": "object", "additionalProperties": true } } } }, "400": { "$ref": "#/components/responses/Error" } } }
    },
    "/api/einvoice/credit-note": {
      "post": { "tags": ["E-invoice"], "summary": "Emit a credit note against an original document", "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": ["invoiceId", "originalFiscalId", "originalDate"], "properties": { "invoiceId": { "type": "string" }, "originalFiscalId": { "type": "string" }, "originalDate": { "type": "string", "format": "date" }, "pos": { "type": "string" }, "receiverType": { "type": "string" } } } } } }, "responses": { "200": { "description": "Credit note emitted", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/EInvoiceResult" } } } }, "400": { "$ref": "#/components/responses/Error" }, "404": { "$ref": "#/components/responses/Error" } } }
    },
    "/api/einvoice/download/{id}": {
      "get": { "tags": ["E-invoice"], "summary": "Download the fiscal PDF", "parameters": [{ "name": "id", "in": "path", "required": true, "schema": { "type": "string" } }, { "name": "fiscalId", "in": "query", "required": true, "schema": { "type": "string" } }], "responses": { "200": { "description": "PDF file", "content": { "application/pdf": { "schema": { "type": "string", "format": "binary" } } } }, "400": { "$ref": "#/components/responses/Error" } } }
    },
    "/api/einvoice/xml/{id}": {
      "get": { "tags": ["E-invoice"], "summary": "Download the fiscal XML", "parameters": [{ "name": "id", "in": "path", "required": true, "schema": { "type": "string" } }, { "name": "fiscalId", "in": "query", "required": true, "schema": { "type": "string" } }], "responses": { "200": { "description": "XML file", "content": { "application/xml": { "schema": { "type": "string" } } } }, "400": { "$ref": "#/components/responses/Error" } } }
    },
    "/api/einvoice/send-email/{id}": {
      "post": { "tags": ["E-invoice"], "summary": "Send the fiscal document by email", "parameters": [{ "name": "id", "in": "path", "required": true, "schema": { "type": "string" } }], "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": ["email"], "properties": { "email": { "type": "string", "format": "email" } } } } } }, "responses": { "200": { "description": "Sent", "content": { "application/json": { "schema": { "type": "object", "additionalProperties": true } } } }, "400": { "$ref": "#/components/responses/Error" } } }
    },
    "/api/cash-register": {
      "post": { "tags": ["Cash Register"], "summary": "Open a new cash register", "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": ["openingAmount"], "properties": { "openingAmount": { "type": "number", "minimum": 0 }, "currency": { "type": "string" }, "notes": { "type": "string" } } } } } }, "responses": { "201": { "description": "Opened", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CashRegister" } } } }, "400": { "$ref": "#/components/responses/Error" }, "409": { "$ref": "#/components/responses/Error" } } }
    },
    "/api/cash-register/summary": {
      "get": { "tags": ["Cash Register"], "summary": "Aggregated stats for closed registers in a period", "parameters": [{ "name": "from", "in": "query", "schema": { "type": "string", "format": "date" } }, { "name": "to", "in": "query", "schema": { "type": "string", "format": "date" } }], "responses": { "200": { "description": "Summary", "content": { "application/json": { "schema": { "type": "object", "properties": { "registerCount": { "type": "integer" }, "totalSales": { "type": "number" }, "totalCash": { "type": "number" }, "totalCard": { "type": "number" }, "totalTransfer": { "type": "number" }, "totalDifference": { "type": "number" }, "avgDifference": { "type": "number" }, "salesCount": { "type": "integer" } } } } } } } }
    },
    "/api/cash-register/current": {
      "get": { "tags": ["Cash Register"], "summary": "Get the current user's open register (or null)", "responses": { "200": { "description": "Open register or null", "content": { "application/json": { "schema": { "oneOf": [{ "$ref": "#/components/schemas/CashRegister" }, { "type": "null" }] } } } } } }
    },
    "/api/cash-register/history": {
      "get": { "tags": ["Cash Register"], "summary": "Closed registers history (paginated)", "parameters": [{ "name": "page", "in": "query", "schema": { "type": "integer", "minimum": 1 } }, { "name": "limit", "in": "query", "schema": { "type": "integer" } }], "responses": { "200": { "description": "History", "content": { "application/json": { "schema": { "type": "object", "properties": { "registers": { "type": "array", "items": { "$ref": "#/components/schemas/CashRegister" } }, "total": { "type": "integer" }, "page": { "type": "integer" }, "pages": { "type": "integer" } } } } } } } }
    },
    "/api/cash-register/{id}/movement": {
      "post": { "tags": ["Cash Register"], "summary": "Add a movement to an open register", "parameters": [{ "name": "id", "in": "path", "required": true, "schema": { "type": "string" } }], "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": ["type", "amount", "description"], "properties": { "type": { "type": "string", "enum": ["sale", "refund", "cash_in", "cash_out"] }, "amount": { "type": "number" }, "description": { "type": "string", "maxLength": 500 }, "invoiceId": { "type": "string" }, "consumerFinal": { "type": "boolean" }, "lineItems": { "type": "array", "items": { "type": "object", "properties": { "catalogItemId": { "type": "string" }, "description": { "type": "string" }, "quantity": { "type": "number" }, "unitPrice": { "type": "number" }, "taxRate": { "type": "number" } } } } } } } } }, "responses": { "200": { "description": "Updated register", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CashRegister" } } } }, "400": { "$ref": "#/components/responses/Error" }, "404": { "$ref": "#/components/responses/Error" } } }
    },
    "/api/cash-register/{id}/close": {
      "post": { "tags": ["Cash Register"], "summary": "Close a register with reconciliation", "parameters": [{ "name": "id", "in": "path", "required": true, "schema": { "type": "string" } }], "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": ["closingAmount"], "properties": { "closingAmount": { "type": "number", "minimum": 0 }, "notes": { "type": "string" } } } } } }, "responses": { "200": { "description": "Closed register", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CashRegister" } } } }, "400": { "$ref": "#/components/responses/Error" }, "404": { "$ref": "#/components/responses/Error" } } }
    },
    "/api/cash-register/{id}": {
      "get": { "tags": ["Cash Register"], "summary": "Get a specific register by ID", "parameters": [{ "name": "id", "in": "path", "required": true, "schema": { "type": "string" } }], "responses": { "200": { "description": "Register", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CashRegister" } } } }, "404": { "$ref": "#/components/responses/Error" } } }
    }
  },
  "components": {
    "securitySchemes": {
      "ApiKeyAuth": { "type": "apiKey", "in": "header", "name": "x-api-key", "description": "Your account or team API key. Get it in Settings → Integrations." },
      "BearerAuth": { "type": "http", "scheme": "bearer", "bearerFormat": "JWT", "description": "JWT returned by /auth/login or /auth/register." }
    },
    "responses": {
      "Error": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }
    },
    "schemas": {
      "Error": { "type": "object", "properties": { "error": { "type": "string" }, "message": { "type": "string" } } },
      "AuthResponse": { "type": "object", "properties": { "token": { "type": "string", "description": "JWT" }, "apiKey": { "type": "string" }, "user": { "$ref": "#/components/schemas/User" } } },
      "TokenBalance": { "type": "object", "properties": { "free": { "type": "integer", "description": "Free AI actions left this month" }, "purchased": { "type": "integer" }, "total": { "type": "integer" }, "freeMonthly": { "type": "integer", "example": 25 } } },
      "User": { "type": "object", "properties": { "_id": { "type": "string" }, "name": { "type": "string" }, "email": { "type": "string" }, "company": { "type": "string" }, "country": { "type": "string" }, "currency": { "type": "string" }, "taxId": { "type": "string" }, "plan": { "type": "string" } } },
      "InvoiceItem": { "type": "object", "properties": { "description": { "type": "string" }, "quantity": { "type": "number" }, "unitPrice": { "type": "number" }, "taxRate": { "type": "number", "description": "VAT %" } } },
      "Invoice": { "type": "object", "properties": { "_id": { "type": "string" }, "number": { "type": "string" }, "status": { "type": "string", "enum": ["draft", "sent", "paid", "overdue"] }, "client": { "$ref": "#/components/schemas/Client" }, "items": { "type": "array", "items": { "$ref": "#/components/schemas/InvoiceItem" } }, "issueDate": { "type": "string", "format": "date" }, "dueDate": { "type": "string", "format": "date" }, "subtotal": { "type": "number" }, "taxTotal": { "type": "number" }, "retentionRate": { "type": "number", "description": "IRPF %" }, "total": { "type": "number" }, "currency": { "type": "string" }, "einvoiceStatus": { "type": "string" } } },
      "InvoiceInput": { "type": "object", "required": ["items"], "properties": { "clientId": { "type": "string" }, "client": { "$ref": "#/components/schemas/ClientInput" }, "items": { "type": "array", "items": { "$ref": "#/components/schemas/InvoiceItem" } }, "issueDate": { "type": "string", "format": "date" }, "dueDate": { "type": "string", "format": "date" }, "retentionRate": { "type": "number" }, "currency": { "type": "string" }, "status": { "type": "string", "enum": ["draft", "sent"] } } },
      "Client": { "type": "object", "properties": { "_id": { "type": "string" }, "name": { "type": "string" }, "taxId": { "type": "string" }, "email": { "type": "string" }, "address": { "type": "string" }, "country": { "type": "string" } } },
      "ClientInput": { "type": "object", "required": ["name"], "properties": { "name": { "type": "string" }, "taxId": { "type": "string" }, "email": { "type": "string" }, "address": { "type": "string" }, "country": { "type": "string" } } },
      "Expense": { "type": "object", "properties": { "_id": { "type": "string" }, "description": { "type": "string" }, "amount": { "type": "number" }, "subtotal": { "type": "number" }, "taxAmount": { "type": "number", "description": "Deductible input VAT" }, "taxRate": { "type": "number" }, "vendor": { "type": "string" }, "category": { "type": "string" }, "date": { "type": "string", "format": "date" }, "currency": { "type": "string" } } },
      "ExpenseInput": { "type": "object", "required": ["amount"], "properties": { "description": { "type": "string" }, "amount": { "type": "number" }, "taxRate": { "type": "number" }, "vendor": { "type": "string" }, "category": { "type": "string" }, "date": { "type": "string", "format": "date" } } },
      "CatalogItem": { "type": "object", "properties": { "_id": { "type": "string" }, "name": { "type": "string" }, "type": { "type": "string", "enum": ["product", "service"] }, "unitPrice": { "type": "number" }, "taxRate": { "type": "number" }, "sku": { "type": "string" }, "stock": { "type": "number" }, "trackInventory": { "type": "boolean" }, "category": { "type": "string" } } },
      "Task": { "type": "object", "properties": { "_id": { "type": "string" }, "title": { "type": "string" }, "status": { "type": "string", "enum": ["todo", "in_progress", "done"] }, "priority": { "type": "string", "enum": ["low", "medium", "high"] }, "dueDate": { "type": "string", "format": "date" }, "assignee": { "type": "string" } } },
      "TaskInput": { "type": "object", "required": ["title"], "properties": { "title": { "type": "string" }, "status": { "type": "string", "enum": ["backlog", "todo", "in_progress", "review", "done"] }, "priority": { "type": "string", "enum": ["low", "medium", "high", "urgent"] }, "dueDate": { "type": "string", "format": "date" }, "assignee": { "type": "string" } } },
      "ActivityLog": { "type": "object", "properties": { "_id": { "type": "string" }, "entityType": { "type": "string" }, "entityId": { "type": "string" }, "action": { "type": "string" }, "fromStatus": { "type": "string" }, "toStatus": { "type": "string" }, "metadata": { "type": "object", "additionalProperties": true }, "createdAt": { "type": "string", "format": "date-time" } } },
      "Team": { "type": "object", "properties": { "_id": { "type": "string" }, "name": { "type": "string" }, "company": { "type": "string" }, "country": { "type": "string" }, "currency": { "type": "string" }, "taxId": { "type": "string" }, "logo": { "type": "string" }, "ownerId": { "type": "string" }, "plan": { "type": "string" }, "maxMembers": { "type": "integer" }, "address": { "type": "string" }, "city": { "type": "string" }, "postalCode": { "type": "string" }, "phone": { "type": "string" } } },
      "TeamInput": { "type": "object", "properties": { "name": { "type": "string" }, "company": { "type": "string" }, "country": { "type": "string" }, "currency": { "type": "string" }, "taxId": { "type": "string" }, "address": { "type": "string" }, "city": { "type": "string" }, "postalCode": { "type": "string" }, "taxRate": { "type": "number" }, "logo": { "type": "string" }, "phone": { "type": "string" }, "bankName": { "type": "string" }, "bankIban": { "type": "string" }, "bankSwift": { "type": "string" }, "bankAccountHolder": { "type": "string" }, "businessType": { "type": "string" } } },
      "TeamMember": { "type": "object", "properties": { "id": { "type": "string" }, "user": { "$ref": "#/components/schemas/User" }, "email": { "type": "string" }, "name": { "type": "string" }, "role": { "type": "string", "enum": ["owner", "admin", "finance", "operations", "member", "viewer"] }, "joinedAt": { "type": "string", "format": "date-time" } } },
      "BusinessEntry": { "type": "object", "required": ["key", "title", "content", "category"], "properties": { "key": { "type": "string", "maxLength": 100 }, "title": { "type": "string", "maxLength": 200 }, "content": { "type": "string", "maxLength": 10000 }, "category": { "type": "string", "enum": ["company", "clients", "financial", "operations", "products", "team", "notes"] }, "updatedAt": { "type": "string", "format": "date-time" } } },
      "BusinessContext": { "type": "object", "properties": { "_id": { "type": "string" }, "summary": { "type": "string" }, "entries": { "type": "array", "items": { "$ref": "#/components/schemas/BusinessEntry" } } } },
      "TaxDeclaration": { "type": "object", "properties": { "_id": { "type": "string" }, "country": { "type": "string" }, "formName": { "type": "string", "example": "Modelo 303" }, "year": { "type": "integer" }, "period": { "type": "string" }, "frequency": { "type": "string" }, "periodLabel": { "type": "string" }, "startDate": { "type": "string", "format": "date" }, "endDate": { "type": "string", "format": "date" }, "totals": { "type": "object", "additionalProperties": true }, "fields": { "type": "object", "additionalProperties": true }, "manualOverrides": { "type": "object", "additionalProperties": true }, "warnings": { "type": "array", "items": { "type": "string" } }, "notes": { "type": "string" }, "status": { "type": "string", "enum": ["draft", "submitted"] }, "submittedAt": { "type": "string", "format": "date-time" } } },
      "Vendor": { "type": "object", "properties": { "_id": { "type": "string" }, "name": { "type": "string" }, "legalName": { "type": "string" }, "email": { "type": "string" }, "phone": { "type": "string" }, "taxId": { "type": "string" }, "dv": { "type": "string" }, "contactPerson": { "type": "string" }, "address": { "type": "string" }, "country": { "type": "string" }, "category": { "type": "string" }, "vendorType": { "type": "string" }, "notes": { "type": "string" }, "creditEnabled": { "type": "boolean" }, "creditDays": { "type": "integer", "enum": [30, 60, 90, 120] }, "creditLimit": { "type": "number" }, "creditCurrency": { "type": "string" }, "active": { "type": "boolean" }, "isAutoCreated": { "type": "boolean" } } },
      "VendorInput": { "type": "object", "required": ["name"], "properties": { "name": { "type": "string", "maxLength": 200 }, "legalName": { "type": "string" }, "email": { "type": "string", "format": "email" }, "phone": { "type": "string" }, "taxId": { "type": "string" }, "dv": { "type": "string" }, "contactPerson": { "type": "string" }, "address": { "type": "string" }, "country": { "type": "string" }, "category": { "type": "string" }, "vendorType": { "type": "string" }, "notes": { "type": "string", "maxLength": 2000 }, "creditEnabled": { "type": "boolean" }, "creditDays": { "type": "integer", "enum": [30, 60, 90, 120] }, "creditLimit": { "type": "number" }, "creditCurrency": { "type": "string" } } },
      "SupplierInvoice": { "type": "object", "properties": { "_id": { "type": "string" }, "vendorId": { "oneOf": [{ "type": "string" }, { "$ref": "#/components/schemas/Vendor" }] }, "invoiceNumber": { "type": "string" }, "invoiceDate": { "type": "string", "format": "date" }, "dueDate": { "type": "string", "format": "date" }, "paymentTermDays": { "type": "integer" }, "subtotal": { "type": "number" }, "taxRate": { "type": "number" }, "tax": { "type": "number" }, "total": { "type": "number" }, "totalPaid": { "type": "number" }, "balance": { "type": "number" }, "currency": { "type": "string" }, "status": { "type": "string", "enum": ["pending", "partial", "paid", "overdue", "cancelled"] }, "documentType": { "type": "string" }, "notes": { "type": "string" }, "cancelledAt": { "type": "string", "format": "date-time" }, "cancelledReason": { "type": "string" } } },
      "SupplierInvoiceInput": { "type": "object", "required": ["vendorId", "invoiceNumber", "total"], "properties": { "vendorId": { "type": "string" }, "invoiceNumber": { "type": "string" }, "invoiceDate": { "type": "string", "format": "date" }, "paymentTermDays": { "type": "integer", "enum": [30, 60, 90, 120] }, "subtotal": { "type": "number" }, "taxRate": { "type": "number" }, "total": { "type": "number" }, "currency": { "type": "string" }, "notes": { "type": "string" }, "documentType": { "type": "string" }, "accountingAccountId": { "type": "string" }, "costCenterId": { "type": "string" } } },
      "SupplierPayment": { "type": "object", "properties": { "_id": { "type": "string" }, "supplierInvoiceId": { "type": "string" }, "vendorId": { "type": "string" }, "amount": { "type": "number" }, "currency": { "type": "string" }, "paymentDate": { "type": "string", "format": "date" }, "paymentMethod": { "type": "string" }, "bank": { "type": "string" }, "reference": { "type": "string" }, "notes": { "type": "string" }, "attachmentUrl": { "type": "string" } } },
      "SupplierInvoiceAnalysis": { "type": "object", "properties": { "vendor": { "type": "object", "properties": { "name": { "type": "string" }, "taxId": { "type": "string" } } }, "items": { "type": "array", "items": { "type": "object", "properties": { "name": { "type": "string" }, "quantity": { "type": "number" }, "unitPrice": { "type": "number" }, "category": { "type": "string" }, "existingMatch": { "type": "string", "nullable": true }, "action": { "type": "string", "enum": ["create", "update", "skip"] } } } }, "total": { "type": "number" }, "date": { "type": "string", "format": "date" }, "invoiceNumber": { "type": "string" }, "currency": { "type": "string" }, "questions": { "type": "array", "items": { "type": "string" } } } },
      "EInvoiceResult": { "type": "object", "properties": { "provider": { "type": "string" }, "docId": { "type": "string" }, "fiscalId": { "type": "string" }, "docNumber": { "type": "string" }, "qrData": { "type": "string" }, "qrImageBase64": { "type": "string" }, "pdfUrl": { "type": "string" }, "rejected": { "type": "boolean" }, "messages": { "type": "array", "items": { "type": "string" } } } },
      "CashMovement": { "type": "object", "properties": { "type": { "type": "string", "enum": ["sale", "refund", "cash_in", "cash_out"] }, "amount": { "type": "number" }, "description": { "type": "string" }, "invoiceId": { "type": "string" }, "consumerFinal": { "type": "boolean" }, "lineItems": { "type": "array", "items": { "type": "object", "properties": { "catalogItemId": { "type": "string" }, "description": { "type": "string" }, "quantity": { "type": "number" }, "unitPrice": { "type": "number" }, "taxRate": { "type": "number" } } } }, "createdAt": { "type": "string", "format": "date-time" } } },
      "CashRegister": { "type": "object", "properties": { "_id": { "type": "string" }, "status": { "type": "string", "enum": ["open", "closing", "closed"] }, "currency": { "type": "string" }, "openingAmount": { "type": "number" }, "closingAmount": { "type": "number" }, "expectedAmount": { "type": "number" }, "difference": { "type": "number" }, "salesCount": { "type": "integer" }, "salesTotal": { "type": "number" }, "cashPayments": { "type": "number" }, "cardPayments": { "type": "number" }, "transferPayments": { "type": "number" }, "movements": { "type": "array", "items": { "$ref": "#/components/schemas/CashMovement" } }, "notes": { "type": "string" }, "openedBy": { "type": "string" }, "closedBy": { "type": "string" }, "openedAt": { "type": "string", "format": "date-time" }, "closedAt": { "type": "string", "format": "date-time" } } }
    }
  }
}
