{
  "openapi": "3.1.0",
  "info": {
    "title": "Frihet API",
    "version": "2026-03-18",
    "description": "The Frihet REST API provides programmatic access to your business data\nin Frihet, the AI-native business management platform for modern businesses.\n\n## Authentication\n\nAll API requests require an API key passed via the `X-API-Key` header.\nGenerate keys from **Settings > API Keys** in the Frihet app.\n\n```\nX-API-Key: fri_your_api_key_here\n```\n\n## Rate Limiting\n\nThe API enforces a rate limit of **100 requests per minute** per API key.\nWhen exceeded, the API returns `429 Too Many Requests` with a `retryAfter` field.\n\nEvery authenticated response includes rate limit headers:\n\n| Header | Description |\n|--------|-------------|\n| `X-RateLimit-Limit` | Maximum requests per window (100) |\n| `X-RateLimit-Remaining` | Remaining requests in current window |\n| `X-RateLimit-Reset` | Unix timestamp (seconds) when the window resets |\n\n## Idempotency\n\nPOST requests accept an `Idempotency-Key` header to prevent duplicate resource\ncreation from network retries. If the same key is sent within 24 hours,\nthe API returns the original response with an `X-Idempotent-Replayed: true` header.\n\n```\nIdempotency-Key: 550e8400-e29b-41d4-a716-446655440000\n```\n\nKeys must be at most 64 characters. We recommend UUID v4.\n\n## API Versioning\n\nEvery response includes an `X-API-Version` header (e.g., `2026-03-18`)\nindicating the current API version. Monitor this header to detect changes.\n\n## Pagination\n\nList endpoints support two pagination strategies:\n\n**Offset pagination:** Use `limit` and `offset` query parameters.\nDefault limit is 50, maximum is 100.\n\n**Cursor pagination:** Use `cursor` and `limit` query parameters.\nPass the `nextCursor` value from a previous response to fetch the next page.\nCursor pagination is more efficient for large datasets and avoids skipped/duplicated\nitems when data changes between requests. When `cursor` is provided, `offset` is ignored.\n\nResponses include `total`, `limit`, `offset`, and optionally `nextCursor`.\n\n## Filtering\n\nList endpoints support filtering by `status` (where applicable), date\nranges using `from` and `to` query parameters in ISO 8601 format (`YYYY-MM-DD`),\nand resource-specific filters like `clientId`, `seriesId`, `vendorId`,\n`category`, `isActive`, and `stage`.\n\n## Field Selection\n\nAll GET endpoints support a `fields` query parameter to select specific fields.\nPass a comma-separated list of field names: `?fields=id,name,total`.\nThe `id` field is always included.\n\n## Errors\n\nAll errors follow a consistent format:\n\n```json\n{\n  \"error\": \"Human-readable error message\",\n  \"details\": [],\n  \"meta\": { \"requestId\": \"uuid\" }\n}\n```\n\nThe `details` array is only present on validation errors (Zod issues).\nThe `meta.requestId` is included on every error response for tracing.\n\n## Resources\n\n- [Documentation](https://docs.frihet.io/desarrolladores/api-rest)\n- [MCP Server](https://mcp.frihet.io)\n- [Status](https://status.frihet.io)\n",
    "contact": {
      "name": "Frihet API Support",
      "url": "https://docs.frihet.io/desarrolladores/api-rest",
      "email": "api@frihet.io"
    },
    "license": {
      "name": "MIT",
      "url": "https://opensource.org/licenses/MIT"
    },
    "x-logo": {
      "url": "https://frihet.io/logos/frihet-logo.svg"
    }
  },
  "servers": [
    {
      "url": "https://api.frihet.io",
      "description": "Production"
    }
  ],
  "security": [
    {
      "ApiKeyAuth": []
    }
  ],
  "tags": [
    {
      "name": "Invoices",
      "description": "Create, read, update, and delete invoices. Includes PDF generation, email sending, and payment tracking."
    },
    {
      "name": "Expenses",
      "description": "Manage business expenses with categories, tax deductions, and receipt attachments."
    },
    {
      "name": "Clients",
      "description": "Manage your client database with contact details, tax IDs, and addresses."
    },
    {
      "name": "Products",
      "description": "Product and service catalog with pricing, tax rates, and SKUs."
    },
    {
      "name": "Quotes",
      "description": "Create and manage quotes with PDF generation and email delivery. Convert accepted quotes to invoices."
    },
    {
      "name": "Vendors",
      "description": "Manage your vendor database with contact details, tax IDs, and addresses."
    },
    {
      "name": "Summary",
      "description": "Financial dashboard data including revenue, expenses, and profit aggregations."
    },
    {
      "name": "Intelligence",
      "description": "AI-optimized endpoints providing business context, monthly P&L, and quarterly tax figures in a single call."
    },
    {
      "name": "Webhooks",
      "description": "CRUD endpoints for managing webhook subscriptions that receive real-time event notifications."
    },
    {
      "name": "Contacts",
      "description": "Contact persons associated with a client. Manage multiple contacts per client for CRM."
    },
    {
      "name": "Activities",
      "description": "Immutable activity timeline for a client. System activities are auto-generated; manual activities can be created via API."
    },
    {
      "name": "Notes",
      "description": "Free-form notes attached to a client."
    },
    {
      "name": "Deposits",
      "description": "Manage client deposits and prepayments. Apply deposits against invoices or process refunds."
    },
    {
      "name": "Batch",
      "description": "Batch creation of resources (up to 50 items per request)."
    }
  ],
  "paths": {
    "/v1/invoices": {
      "get": {
        "operationId": "listInvoices",
        "summary": "List invoices",
        "description": "Retrieve a paginated list of invoices with optional filters for status, date range, and search.",
        "tags": [
          "Invoices"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Offset"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "name": "status",
            "in": "query",
            "description": "Filter by invoice status",
            "schema": {
              "$ref": "#/components/schemas/InvoiceStatus"
            }
          },
          {
            "$ref": "#/components/parameters/From"
          },
          {
            "$ref": "#/components/parameters/To"
          },
          {
            "$ref": "#/components/parameters/Search"
          },
          {
            "$ref": "#/components/parameters/Fields"
          },
          {
            "$ref": "#/components/parameters/FilterClientId"
          },
          {
            "$ref": "#/components/parameters/FilterSeriesId"
          }
        ],
        "responses": {
          "200": {
            "description": "A paginated list of invoices",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/PaginatedResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/Invoice"
                          }
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "post": {
        "operationId": "createInvoice",
        "summary": "Create an invoice",
        "description": "Create a new invoice. The invoice is created in `draft` status by default.",
        "tags": [
          "Invoices"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/InvoiceCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Invoice created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Invoice"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/v1/invoices/{invoiceId}": {
      "get": {
        "operationId": "getInvoice",
        "summary": "Get an invoice",
        "description": "Retrieve a single invoice by ID.",
        "tags": [
          "Invoices"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/InvoiceId"
          },
          {
            "$ref": "#/components/parameters/Fields"
          }
        ],
        "responses": {
          "200": {
            "description": "Invoice details",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Invoice"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "put": {
        "operationId": "updateInvoice",
        "summary": "Full update an invoice",
        "description": "Replace all fields on an existing invoice. All required fields must be provided.",
        "tags": [
          "Invoices"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/InvoiceId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/InvoiceCreate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Invoice updated",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Invoice"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "patch": {
        "operationId": "patchInvoice",
        "summary": "Partial update an invoice",
        "description": "Update only the provided fields on an existing invoice. All fields are optional.",
        "tags": [
          "Invoices"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/InvoiceId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/InvoiceCreate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Invoice updated",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Invoice"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "delete": {
        "operationId": "deleteInvoice",
        "summary": "Delete an invoice",
        "description": "Delete an invoice. Draft invoices are permanently deleted (204).\nNon-draft invoices are soft-deleted (cancelled) to preserve VeriFactu\nSHA-256 hash chain integrity (RD 1007/2023 compliance), returning 200\nwith the cancelled document body.\n",
        "tags": [
          "Invoices"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/InvoiceId"
          }
        ],
        "responses": {
          "200": {
            "description": "Invoice soft-deleted (cancelled). Returned for non-draft invoices.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        },
                        "status": {
                          "type": "string",
                          "example": "cancelled"
                        },
                        "cancelledVia": {
                          "type": "string",
                          "example": "api"
                        }
                      }
                    },
                    "meta": {
                      "type": "object",
                      "properties": {
                        "requestId": {
                          "type": "string"
                        },
                        "timestamp": {
                          "type": "string",
                          "format": "date-time"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "204": {
            "description": "Invoice permanently deleted (draft invoices only)"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/v1/invoices/{invoiceId}/pdf": {
      "get": {
        "operationId": "getInvoicePdf",
        "summary": "Download invoice PDF",
        "description": "Generate and download the invoice as a PDF document.",
        "tags": [
          "Invoices"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/InvoiceId"
          }
        ],
        "responses": {
          "200": {
            "description": "PDF document",
            "content": {
              "application/pdf": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/v1/invoices/{invoiceId}/send": {
      "post": {
        "operationId": "sendInvoice",
        "summary": "Send invoice by email",
        "description": "Send the invoice to a recipient via email. If the invoice is in `draft` status, it will be automatically changed to `sent`.",
        "tags": [
          "Invoices"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/InvoiceId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SendEmailRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Invoice sent",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": true
                    },
                    "messageId": {
                      "type": "string",
                      "description": "Email provider message ID"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "422": {
            "description": "Fiscal profile not configured",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/v1/invoices/{invoiceId}/paid": {
      "post": {
        "operationId": "markInvoicePaid",
        "summary": "Mark invoice as paid",
        "description": "Mark an invoice as paid. Optionally specify the payment date.",
        "tags": [
          "Invoices"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/InvoiceId"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "paidDate": {
                    "type": "string",
                    "format": "date",
                    "description": "Payment date in ISO format. Defaults to today.",
                    "example": "2026-03-09"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Invoice marked as paid",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": true
                    },
                    "status": {
                      "type": "string",
                      "example": "paid"
                    },
                    "paidAt": {
                      "type": "string",
                      "format": "date"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/v1/expenses": {
      "get": {
        "operationId": "listExpenses",
        "summary": "List expenses",
        "description": "Retrieve a paginated list of expenses with optional date range and search filters.",
        "tags": [
          "Expenses"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Offset"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "$ref": "#/components/parameters/From"
          },
          {
            "$ref": "#/components/parameters/To"
          },
          {
            "$ref": "#/components/parameters/Search"
          },
          {
            "$ref": "#/components/parameters/Fields"
          },
          {
            "$ref": "#/components/parameters/FilterVendorId"
          },
          {
            "$ref": "#/components/parameters/FilterCategory"
          }
        ],
        "responses": {
          "200": {
            "description": "A paginated list of expenses",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/PaginatedResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/Expense"
                          }
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "post": {
        "operationId": "createExpense",
        "summary": "Create an expense",
        "description": "Record a new business expense.",
        "tags": [
          "Expenses"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ExpenseCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Expense created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Expense"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/v1/expenses/{expenseId}": {
      "get": {
        "operationId": "getExpense",
        "summary": "Get an expense",
        "description": "Retrieve a single expense by ID.",
        "tags": [
          "Expenses"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/ExpenseId"
          },
          {
            "$ref": "#/components/parameters/Fields"
          }
        ],
        "responses": {
          "200": {
            "description": "Expense details",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Expense"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "put": {
        "operationId": "updateExpense",
        "summary": "Full update an expense",
        "description": "Replace all fields on an existing expense record.",
        "tags": [
          "Expenses"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/ExpenseId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ExpenseCreate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Expense updated",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Expense"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "patch": {
        "operationId": "patchExpense",
        "summary": "Partial update an expense",
        "description": "Update only the provided fields on an existing expense record.",
        "tags": [
          "Expenses"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/ExpenseId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ExpenseCreate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Expense updated",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Expense"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "delete": {
        "operationId": "deleteExpense",
        "summary": "Delete an expense",
        "description": "Permanently delete an expense record.",
        "tags": [
          "Expenses"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/ExpenseId"
          }
        ],
        "responses": {
          "204": {
            "description": "Expense deleted"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/v1/clients": {
      "get": {
        "operationId": "listClients",
        "summary": "List clients",
        "description": "Retrieve a paginated list of clients with optional search.",
        "tags": [
          "Clients"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Offset"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "$ref": "#/components/parameters/From"
          },
          {
            "$ref": "#/components/parameters/To"
          },
          {
            "$ref": "#/components/parameters/Search"
          },
          {
            "$ref": "#/components/parameters/Fields"
          },
          {
            "$ref": "#/components/parameters/FilterStage"
          }
        ],
        "responses": {
          "200": {
            "description": "A paginated list of clients",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/PaginatedResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/Client"
                          }
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "post": {
        "operationId": "createClient",
        "summary": "Create a client",
        "description": "Add a new client to your database.",
        "tags": [
          "Clients"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ClientCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Client created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Client"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/v1/clients/{clientId}": {
      "get": {
        "operationId": "getClient",
        "summary": "Get a client",
        "description": "Retrieve a single client by ID.",
        "tags": [
          "Clients"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/ClientId"
          },
          {
            "$ref": "#/components/parameters/Fields"
          }
        ],
        "responses": {
          "200": {
            "description": "Client details",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Client"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "put": {
        "operationId": "updateClient",
        "summary": "Full update a client",
        "description": "Replace all fields on an existing client.",
        "tags": [
          "Clients"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/ClientId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ClientCreate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Client updated",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Client"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "patch": {
        "operationId": "patchClient",
        "summary": "Partial update a client",
        "description": "Update only the provided fields on an existing client.",
        "tags": [
          "Clients"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/ClientId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ClientCreate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Client updated",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Client"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "delete": {
        "operationId": "deleteClient",
        "summary": "Delete a client",
        "description": "Permanently delete a client from your database.",
        "tags": [
          "Clients"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/ClientId"
          }
        ],
        "responses": {
          "204": {
            "description": "Client deleted"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/v1/clients/{clientId}/contacts": {
      "get": {
        "operationId": "listClientContacts",
        "summary": "List client contacts",
        "description": "Retrieve all contact persons for a client.",
        "tags": [
          "Contacts"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/ClientId"
          }
        ],
        "responses": {
          "200": {
            "description": "List of contacts",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Contact"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "post": {
        "operationId": "createClientContact",
        "summary": "Create a client contact",
        "description": "Add a new contact person to a client.",
        "tags": [
          "Contacts"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/ClientId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ContactCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Contact created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Contact"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/v1/clients/{clientId}/contacts/{contactId}": {
      "get": {
        "operationId": "getClientContact",
        "summary": "Get a client contact",
        "description": "Retrieve a single contact person by ID.",
        "tags": [
          "Contacts"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/ClientId"
          },
          {
            "$ref": "#/components/parameters/ContactId"
          }
        ],
        "responses": {
          "200": {
            "description": "Contact details",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Contact"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "patch": {
        "operationId": "updateClientContact",
        "summary": "Update a client contact",
        "description": "Update fields on an existing contact person.",
        "tags": [
          "Contacts"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/ClientId"
          },
          {
            "$ref": "#/components/parameters/ContactId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ContactCreate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Contact updated",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Contact"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "delete": {
        "operationId": "deleteClientContact",
        "summary": "Delete a client contact",
        "description": "Permanently delete a contact person from a client.",
        "tags": [
          "Contacts"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/ClientId"
          },
          {
            "$ref": "#/components/parameters/ContactId"
          }
        ],
        "responses": {
          "204": {
            "description": "Contact deleted"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/v1/clients/{clientId}/activities": {
      "get": {
        "operationId": "listClientActivities",
        "summary": "List client activities",
        "description": "Retrieve the activity timeline for a client.",
        "tags": [
          "Activities"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/ClientId"
          }
        ],
        "responses": {
          "200": {
            "description": "List of activities",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Activity"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "post": {
        "operationId": "createClientActivity",
        "summary": "Create a client activity",
        "description": "Add a manual activity to the client timeline. Activities are immutable once created.",
        "tags": [
          "Activities"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/ClientId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ActivityCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Activity created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Activity"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/v1/clients/{clientId}/activities/{activityId}": {
      "get": {
        "operationId": "getClientActivity",
        "summary": "Get a client activity",
        "description": "Retrieve a single activity by ID.",
        "tags": [
          "Activities"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/ClientId"
          },
          {
            "$ref": "#/components/parameters/ActivityId"
          }
        ],
        "responses": {
          "200": {
            "description": "Activity details",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Activity"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/v1/clients/{clientId}/notes": {
      "get": {
        "operationId": "listClientNotes",
        "summary": "List client notes",
        "description": "Retrieve all notes for a client.",
        "tags": [
          "Notes"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/ClientId"
          }
        ],
        "responses": {
          "200": {
            "description": "List of notes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Note"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "post": {
        "operationId": "createClientNote",
        "summary": "Create a client note",
        "description": "Add a new note to a client.",
        "tags": [
          "Notes"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/ClientId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/NoteCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Note created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Note"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/v1/clients/{clientId}/notes/{noteId}": {
      "get": {
        "operationId": "getClientNote",
        "summary": "Get a client note",
        "description": "Retrieve a single note by ID.",
        "tags": [
          "Notes"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/ClientId"
          },
          {
            "$ref": "#/components/parameters/NoteId"
          }
        ],
        "responses": {
          "200": {
            "description": "Note details",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Note"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "patch": {
        "operationId": "updateClientNote",
        "summary": "Update a client note",
        "description": "Update the content of an existing note.",
        "tags": [
          "Notes"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/ClientId"
          },
          {
            "$ref": "#/components/parameters/NoteId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/NoteCreate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Note updated",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Note"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "delete": {
        "operationId": "deleteClientNote",
        "summary": "Delete a client note",
        "description": "Permanently delete a note from a client.",
        "tags": [
          "Notes"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/ClientId"
          },
          {
            "$ref": "#/components/parameters/NoteId"
          }
        ],
        "responses": {
          "204": {
            "description": "Note deleted"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/v1/products": {
      "get": {
        "operationId": "listProducts",
        "summary": "List products",
        "description": "Retrieve a paginated list of products and services with optional search.",
        "tags": [
          "Products"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Offset"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "$ref": "#/components/parameters/From"
          },
          {
            "$ref": "#/components/parameters/To"
          },
          {
            "$ref": "#/components/parameters/Search"
          },
          {
            "$ref": "#/components/parameters/Fields"
          },
          {
            "$ref": "#/components/parameters/FilterIsActive"
          }
        ],
        "responses": {
          "200": {
            "description": "A paginated list of products",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/PaginatedResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/Product"
                          }
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "post": {
        "operationId": "createProduct",
        "summary": "Create a product",
        "description": "Add a new product or service to your catalog.",
        "tags": [
          "Products"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ProductCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Product created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Product"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/v1/products/{productId}": {
      "get": {
        "operationId": "getProduct",
        "summary": "Get a product",
        "description": "Retrieve a single product by ID.",
        "tags": [
          "Products"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/ProductId"
          },
          {
            "$ref": "#/components/parameters/Fields"
          }
        ],
        "responses": {
          "200": {
            "description": "Product details",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Product"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "put": {
        "operationId": "updateProduct",
        "summary": "Full update a product",
        "description": "Replace all fields on an existing product or service.",
        "tags": [
          "Products"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/ProductId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ProductCreate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Product updated",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Product"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "patch": {
        "operationId": "patchProduct",
        "summary": "Partial update a product",
        "description": "Update only the provided fields on an existing product or service.",
        "tags": [
          "Products"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/ProductId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ProductCreate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Product updated",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Product"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "delete": {
        "operationId": "deleteProduct",
        "summary": "Delete a product",
        "description": "Permanently delete a product from your catalog.",
        "tags": [
          "Products"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/ProductId"
          }
        ],
        "responses": {
          "204": {
            "description": "Product deleted"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/v1/quotes": {
      "get": {
        "operationId": "listQuotes",
        "summary": "List quotes",
        "description": "Retrieve a paginated list of quotes with optional filters for status, date range, and search.",
        "tags": [
          "Quotes"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Offset"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "name": "status",
            "in": "query",
            "description": "Filter by quote status",
            "schema": {
              "$ref": "#/components/schemas/QuoteStatus"
            }
          },
          {
            "$ref": "#/components/parameters/From"
          },
          {
            "$ref": "#/components/parameters/To"
          },
          {
            "$ref": "#/components/parameters/Search"
          },
          {
            "$ref": "#/components/parameters/Fields"
          },
          {
            "$ref": "#/components/parameters/FilterClientId"
          },
          {
            "$ref": "#/components/parameters/FilterSeriesId"
          }
        ],
        "responses": {
          "200": {
            "description": "A paginated list of quotes",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/PaginatedResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/Quote"
                          }
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "post": {
        "operationId": "createQuote",
        "summary": "Create a quote",
        "description": "Create a new quote. The quote is created in `draft` status by default.",
        "tags": [
          "Quotes"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/QuoteCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Quote created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Quote"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/v1/quotes/{quoteId}": {
      "get": {
        "operationId": "getQuote",
        "summary": "Get a quote",
        "description": "Retrieve a single quote by ID.",
        "tags": [
          "Quotes"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/QuoteId"
          },
          {
            "$ref": "#/components/parameters/Fields"
          }
        ],
        "responses": {
          "200": {
            "description": "Quote details",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Quote"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "put": {
        "operationId": "updateQuote",
        "summary": "Full update a quote",
        "description": "Replace all fields on an existing quote.",
        "tags": [
          "Quotes"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/QuoteId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/QuoteCreate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Quote updated",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Quote"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "patch": {
        "operationId": "patchQuote",
        "summary": "Partial update a quote",
        "description": "Update only the provided fields on an existing quote.",
        "tags": [
          "Quotes"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/QuoteId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/QuoteCreate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Quote updated",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Quote"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "delete": {
        "operationId": "deleteQuote",
        "summary": "Delete a quote",
        "description": "Delete a quote. Draft quotes are permanently deleted (204).\nNon-draft quotes are soft-deleted (cancelled) to preserve VeriFactu\nhash chain integrity, returning 200 with the cancelled document body.\n",
        "tags": [
          "Quotes"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/QuoteId"
          }
        ],
        "responses": {
          "200": {
            "description": "Quote soft-deleted (cancelled). Returned for non-draft quotes.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        },
                        "status": {
                          "type": "string",
                          "example": "cancelled"
                        },
                        "cancelledVia": {
                          "type": "string",
                          "example": "api"
                        }
                      }
                    },
                    "meta": {
                      "type": "object",
                      "properties": {
                        "requestId": {
                          "type": "string"
                        },
                        "timestamp": {
                          "type": "string",
                          "format": "date-time"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "204": {
            "description": "Quote permanently deleted (draft quotes only)"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/v1/quotes/{quoteId}/pdf": {
      "get": {
        "operationId": "getQuotePdf",
        "summary": "Download quote PDF",
        "description": "Generate and download the quote as a PDF document.",
        "tags": [
          "Quotes"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/QuoteId"
          }
        ],
        "responses": {
          "200": {
            "description": "PDF document",
            "content": {
              "application/pdf": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/v1/quotes/{quoteId}/send": {
      "post": {
        "operationId": "sendQuote",
        "summary": "Send quote by email",
        "description": "Send the quote to a recipient via email. If the quote is in `draft` status, it will be automatically changed to `sent`.",
        "tags": [
          "Quotes"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/QuoteId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SendEmailRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Quote sent",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": true
                    },
                    "messageId": {
                      "type": "string",
                      "description": "Email provider message ID"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "422": {
            "description": "Fiscal profile not configured",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/v1/summary": {
      "get": {
        "operationId": "getSummary",
        "summary": "Financial summary",
        "description": "Get an aggregated financial summary including revenue, expenses, profit,\nentity counts, and invoice status breakdown. Supports optional date range filtering.\n",
        "tags": [
          "Summary"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/From"
          },
          {
            "$ref": "#/components/parameters/To"
          }
        ],
        "responses": {
          "200": {
            "description": "Financial summary",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Summary"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/v1/vendors": {
      "get": {
        "operationId": "listVendors",
        "summary": "List vendors",
        "description": "Retrieve a paginated list of vendors.",
        "tags": [
          "Vendors"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Offset"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "$ref": "#/components/parameters/From"
          },
          {
            "$ref": "#/components/parameters/To"
          },
          {
            "$ref": "#/components/parameters/Search"
          },
          {
            "$ref": "#/components/parameters/Fields"
          }
        ],
        "responses": {
          "200": {
            "description": "A paginated list of vendors",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/PaginatedResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/Vendor"
                          }
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "post": {
        "operationId": "createVendor",
        "summary": "Create a vendor",
        "description": "Add a new vendor to your database.",
        "tags": [
          "Vendors"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/VendorCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Vendor created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Vendor"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/v1/vendors/{vendorId}": {
      "get": {
        "operationId": "getVendor",
        "summary": "Get a vendor",
        "description": "Retrieve a single vendor by ID.",
        "tags": [
          "Vendors"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/VendorId"
          },
          {
            "$ref": "#/components/parameters/Fields"
          }
        ],
        "responses": {
          "200": {
            "description": "Vendor details",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Vendor"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "put": {
        "operationId": "updateVendor",
        "summary": "Full update a vendor",
        "description": "Replace all fields on an existing vendor.",
        "tags": [
          "Vendors"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/VendorId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/VendorCreate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Vendor updated",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Vendor"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "patch": {
        "operationId": "patchVendor",
        "summary": "Partial update a vendor",
        "description": "Update only the provided fields on an existing vendor.",
        "tags": [
          "Vendors"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/VendorId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/VendorCreate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Vendor updated",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Vendor"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "delete": {
        "operationId": "deleteVendor",
        "summary": "Delete a vendor",
        "description": "Permanently delete a vendor from your database.",
        "tags": [
          "Vendors"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/VendorId"
          }
        ],
        "responses": {
          "204": {
            "description": "Vendor deleted"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/v1/context": {
      "get": {
        "operationId": "getBusinessContext",
        "summary": "Business context snapshot",
        "description": "Returns a comprehensive business context snapshot in a single call,\noptimized for AI agents and MCP integrations. Includes business info,\ndefaults, plan usage, invoice series, recent activity, top clients,\nand current month financials.\n",
        "tags": [
          "Intelligence"
        ],
        "responses": {
          "200": {
            "description": "Business context data",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BusinessContext"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/v1/monthly": {
      "get": {
        "operationId": "getMonthlySummary",
        "summary": "Monthly P&L",
        "description": "Monthly financial summary with revenue breakdown (tax base, tax, IRPF),\nexpense breakdown (deductible, tax), profit (gross/net), invoice status\ncounts, top clients, expenses by category, and estimated tax liability\n(Modelo 303).\n",
        "tags": [
          "Intelligence"
        ],
        "parameters": [
          {
            "name": "month",
            "in": "query",
            "description": "Month in YYYY-MM format. Defaults to current month.",
            "schema": {
              "type": "string",
              "pattern": "^\\d{4}-\\d{2}$",
              "example": "2026-03"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Monthly financial summary",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MonthlySummary"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/v1/quarterly": {
      "get": {
        "operationId": "getQuarterlySummary",
        "summary": "Quarterly tax figures",
        "description": "Quarterly tax preparation data including Modelo 303 (VAT) and\nModelo 130 (quarterly income payment) pre-filled figures.\nIncludes base imponible, cuotas, and estimated payments.\n",
        "tags": [
          "Intelligence"
        ],
        "parameters": [
          {
            "name": "quarter",
            "in": "query",
            "description": "Quarter in YYYY-Q1 format. Defaults to current quarter.",
            "schema": {
              "type": "string",
              "pattern": "^\\d{4}-Q[1-4]$",
              "example": "2026-Q1"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Quarterly tax summary",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/QuarterlySummary"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/v1/webhooks": {
      "get": {
        "operationId": "listWebhooks",
        "summary": "List webhooks",
        "description": "Retrieve all webhook subscriptions for the authenticated user.",
        "tags": [
          "Webhooks"
        ],
        "responses": {
          "200": {
            "description": "List of webhooks",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Webhook"
                      }
                    },
                    "total": {
                      "type": "integer"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "post": {
        "operationId": "createWebhook",
        "summary": "Create a webhook",
        "description": "Register a new webhook subscription to receive event notifications.",
        "tags": [
          "Webhooks"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Webhook created",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Webhook"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/v1/webhooks/{webhookId}": {
      "get": {
        "operationId": "getWebhook",
        "summary": "Get a webhook",
        "description": "Retrieve a single webhook subscription by ID.",
        "tags": [
          "Webhooks"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/WebhookId"
          }
        ],
        "responses": {
          "200": {
            "description": "Webhook details",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Webhook"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "put": {
        "operationId": "updateWebhook",
        "summary": "Full update a webhook",
        "description": "Replace all fields on an existing webhook subscription.",
        "tags": [
          "Webhooks"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/WebhookId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookUpdate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Webhook updated",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Webhook"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "patch": {
        "operationId": "patchWebhook",
        "summary": "Partial update a webhook",
        "description": "Update only the provided fields on an existing webhook subscription.",
        "tags": [
          "Webhooks"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/WebhookId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookUpdate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Webhook updated",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Webhook"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "delete": {
        "operationId": "deleteWebhook",
        "summary": "Delete a webhook",
        "description": "Permanently delete a webhook subscription.",
        "tags": [
          "Webhooks"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/WebhookId"
          }
        ],
        "responses": {
          "204": {
            "description": "Webhook deleted"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/v1/{resource}/batch": {
      "post": {
        "operationId": "batchCreate",
        "summary": "Batch create resources",
        "description": "Create multiple resources in a single request. The request body must be\nan array of items (max 50). Each item is validated independently.\nReturns 201 if all succeed, 207 if partially successful, 400 if all fail.\n",
        "tags": [
          "Batch"
        ],
        "parameters": [
          {
            "name": "resource",
            "in": "path",
            "required": true,
            "description": "Resource type to batch create",
            "schema": {
              "type": "string",
              "enum": [
                "invoices",
                "expenses",
                "clients",
                "vendors",
                "products",
                "quotes"
              ]
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "array",
                "items": {
                  "type": "object"
                },
                "minItems": 1,
                "maxItems": 50
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "All items created successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BatchResponse"
                }
              }
            }
          },
          "207": {
            "description": "Partial success (some items failed validation)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BatchResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/v1/deposits": {
      "get": {
        "operationId": "listDeposits",
        "summary": "List deposits",
        "description": "Retrieve a paginated list of deposits with optional date range, client, and search filters.",
        "tags": [
          "Deposits"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Offset"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "$ref": "#/components/parameters/From"
          },
          {
            "$ref": "#/components/parameters/To"
          },
          {
            "$ref": "#/components/parameters/Search"
          },
          {
            "$ref": "#/components/parameters/Fields"
          },
          {
            "$ref": "#/components/parameters/FilterClientId"
          }
        ],
        "responses": {
          "200": {
            "description": "A paginated list of deposits",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/PaginatedResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/Deposit"
                          }
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "post": {
        "operationId": "createDeposit",
        "summary": "Create a deposit",
        "description": "Record a new client deposit or prepayment.",
        "tags": [
          "Deposits"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DepositCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Deposit created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Deposit"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/v1/deposits/{depositId}": {
      "get": {
        "operationId": "getDeposit",
        "summary": "Get a deposit",
        "description": "Retrieve a single deposit by ID.",
        "tags": [
          "Deposits"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/DepositId"
          },
          {
            "$ref": "#/components/parameters/Fields"
          }
        ],
        "responses": {
          "200": {
            "description": "Deposit details",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Deposit"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "put": {
        "operationId": "updateDeposit",
        "summary": "Full update a deposit",
        "description": "Replace all fields on an existing deposit.",
        "tags": [
          "Deposits"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/DepositId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DepositCreate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Deposit updated",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Deposit"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "patch": {
        "operationId": "patchDeposit",
        "summary": "Partial update a deposit",
        "description": "Update only the provided fields on an existing deposit.",
        "tags": [
          "Deposits"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/DepositId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DepositCreate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Deposit updated",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Deposit"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "delete": {
        "operationId": "deleteDeposit",
        "summary": "Delete a deposit",
        "description": "Permanently delete a deposit record.",
        "tags": [
          "Deposits"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/DepositId"
          }
        ],
        "responses": {
          "204": {
            "description": "Deposit deleted"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/v1/deposits/{depositId}/apply": {
      "post": {
        "operationId": "applyDeposit",
        "summary": "Apply deposit to an invoice",
        "description": "Apply all or part of a deposit's remaining balance to a specific invoice.\nReturns an error if the requested amount exceeds the remaining balance or\nif the deposit has already been applied to the given invoice.\n",
        "tags": [
          "Deposits"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/DepositId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "invoiceId",
                  "invoiceNumber",
                  "amount"
                ],
                "properties": {
                  "invoiceId": {
                    "type": "string",
                    "description": "ID of the invoice to apply the deposit to",
                    "example": "abc123def456"
                  },
                  "invoiceNumber": {
                    "type": "string",
                    "description": "Invoice number (for audit trail)",
                    "example": "FAC-2026-0042"
                  },
                  "amount": {
                    "type": "number",
                    "description": "Amount to apply (must be positive and not exceed remaining balance)",
                    "example": 500
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Deposit applied successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": true
                    },
                    "depositId": {
                      "type": "string",
                      "example": "dep_abc123"
                    },
                    "appliedAmount": {
                      "type": "number",
                      "example": 500
                    },
                    "remainingBalance": {
                      "type": "number",
                      "example": 250
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "active",
                        "partially_applied",
                        "fully_applied"
                      ],
                      "example": "partially_applied"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/v1/deposits/{depositId}/refund": {
      "post": {
        "operationId": "refundDeposit",
        "summary": "Refund a deposit",
        "description": "Refund all or part of a deposit's remaining balance to the client.\nIf `amount` is omitted, the full remaining balance is refunded.\nReturns an error if the deposit is already fully refunded or if the\nrequested amount exceeds the remaining balance.\n",
        "tags": [
          "Deposits"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/DepositId"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "amount": {
                    "type": "number",
                    "description": "Amount to refund. Omit to refund the full remaining balance.",
                    "example": 250
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Deposit refunded successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": true
                    },
                    "depositId": {
                      "type": "string",
                      "example": "dep_abc123"
                    },
                    "refundedAmount": {
                      "type": "number",
                      "example": 250
                    },
                    "remainingBalance": {
                      "type": "number",
                      "example": 0
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/v1/invoices/{invoiceId}/xml": {
      "get": {
        "operationId": "getInvoiceXml",
        "summary": "Download e-invoice XML",
        "description": "Download the Facturae 3.2.2 XML for an invoice. The XML is generated\nwhen the invoice is saved or sent. Returns 404 if the e-invoice XML\nhas not yet been generated for this invoice.\n",
        "tags": [
          "Invoices"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/InvoiceId"
          }
        ],
        "responses": {
          "200": {
            "description": "E-invoice XML document",
            "content": {
              "application/xml": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/v1/invoices/{invoiceId}/credit-note": {
      "post": {
        "operationId": "createCreditNote",
        "summary": "Create a credit note",
        "description": "Create a rectificative invoice (credit note) for an existing invoice.\nThe original invoice must not be in `draft` or `cancelled` status.\nThe credit note is created with `sent` status and negative line item amounts.\nThe `rectificativa` field is populated according to Spanish Facturae R-type codes.\n",
        "tags": [
          "Invoices"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/InvoiceId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "reason"
                ],
                "properties": {
                  "reason": {
                    "type": "string",
                    "enum": [
                      "refund",
                      "discount",
                      "error",
                      "cancellation",
                      "other"
                    ],
                    "description": "Reason for the credit note",
                    "example": "error"
                  },
                  "reasonDescription": {
                    "type": "string",
                    "maxLength": 500,
                    "description": "Optional free-text description of the reason",
                    "example": "Incorrect unit price on line 2"
                  },
                  "fullCredit": {
                    "type": "boolean",
                    "default": true,
                    "description": "When true, issues a full credit (tipo S — sustitución).\nWhen false, issues a partial correction (tipo I — corrección por diferencias).\n",
                    "example": true
                  },
                  "issueDate": {
                    "type": "string",
                    "format": "date",
                    "description": "Issue date for the credit note. Defaults to today.",
                    "example": "2026-04-07"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Credit note created",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": true
                    },
                    "creditNote": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string",
                          "description": "ID of the newly created credit note invoice",
                          "example": "cn_abc123"
                        },
                        "documentNumber": {
                          "type": "string",
                          "example": "CN-FAC-2026-0042"
                        },
                        "originalInvoiceId": {
                          "type": "string",
                          "example": "abc123def456"
                        },
                        "reason": {
                          "type": "string",
                          "example": "error"
                        },
                        "fullCredit": {
                          "type": "boolean",
                          "example": true
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/v1/invoices/{invoiceId}/late-fee": {
      "post": {
        "operationId": "applyLateFee",
        "summary": "Apply a late payment fee",
        "description": "Calculate and apply a late payment fee to an overdue or sent invoice.\nUses the EU Late Payment Directive default rate of 8% per annum if `amount`\nis not specified. Can only be applied once per invoice.\n",
        "tags": [
          "Invoices"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/InvoiceId"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "amount": {
                    "type": "number",
                    "description": "Fixed fee amount. If omitted, auto-calculated at 8% p.a. on the invoice total.",
                    "example": 42.5
                  },
                  "daysOverdue": {
                    "type": "integer",
                    "description": "Override the number of overdue days used for auto-calculation. Defaults to actual days past due date.",
                    "example": 30
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Late fee applied",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": true
                    },
                    "feeAmount": {
                      "type": "number",
                      "description": "Fee amount applied",
                      "example": 42.5
                    },
                    "invoiceId": {
                      "type": "string",
                      "example": "abc123def456"
                    },
                    "daysOverdue": {
                      "type": "integer",
                      "example": 30
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/v1/expenses/{expenseId}/billable": {
      "post": {
        "operationId": "markExpenseBillable",
        "summary": "Mark expense as billable",
        "description": "Mark an expense as billable to a specific client, optionally with a markup\npercentage. The expense must not already be invoiced. Once billable, the\nexpense can be included in a client invoice.\n",
        "tags": [
          "Expenses"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/ExpenseId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "clientId"
                ],
                "properties": {
                  "clientId": {
                    "type": "string",
                    "description": "ID of the client to bill this expense to",
                    "example": "client_abc123"
                  },
                  "markup": {
                    "type": "number",
                    "minimum": 0,
                    "maximum": 1000,
                    "description": "Markup percentage to apply when invoicing (e.g. 20 = 20% markup)",
                    "example": 20
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Expense marked as billable",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": true
                    },
                    "expenseId": {
                      "type": "string",
                      "example": "exp_abc123"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "delete": {
        "operationId": "unmarkExpenseBillable",
        "summary": "Remove billable flag from expense",
        "description": "Remove the billable flag from an expense. The expense must not already\nbe invoiced — once invoiced, the billable flag cannot be removed.\n",
        "tags": [
          "Expenses"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/ExpenseId"
          }
        ],
        "responses": {
          "200": {
            "description": "Billable flag removed",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": true
                    },
                    "expenseId": {
                      "type": "string",
                      "example": "exp_abc123"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "ApiKeyAuth": {
        "type": "apiKey",
        "in": "header",
        "name": "X-API-Key",
        "description": "API key for authentication. Keys start with `fri_` prefix.\nGenerate keys from Settings > API Keys in the Frihet app.\n"
      }
    },
    "parameters": {
      "Limit": {
        "name": "limit",
        "in": "query",
        "description": "Number of items to return (default 50, max 100)",
        "schema": {
          "type": "integer",
          "minimum": 1,
          "maximum": 100,
          "default": 50
        }
      },
      "Offset": {
        "name": "offset",
        "in": "query",
        "description": "Number of items to skip for pagination (max 10000)",
        "schema": {
          "type": "integer",
          "minimum": 0,
          "maximum": 10000,
          "default": 0
        }
      },
      "From": {
        "name": "from",
        "in": "query",
        "description": "Start date filter in ISO format (YYYY-MM-DD)",
        "schema": {
          "type": "string",
          "format": "date",
          "example": "2026-01-01"
        }
      },
      "To": {
        "name": "to",
        "in": "query",
        "description": "End date filter in ISO format (YYYY-MM-DD)",
        "schema": {
          "type": "string",
          "format": "date",
          "example": "2026-12-31"
        }
      },
      "InvoiceId": {
        "name": "invoiceId",
        "in": "path",
        "required": true,
        "description": "Invoice unique identifier",
        "schema": {
          "type": "string"
        }
      },
      "ExpenseId": {
        "name": "expenseId",
        "in": "path",
        "required": true,
        "description": "Expense unique identifier",
        "schema": {
          "type": "string"
        }
      },
      "ClientId": {
        "name": "clientId",
        "in": "path",
        "required": true,
        "description": "Client unique identifier",
        "schema": {
          "type": "string"
        }
      },
      "ProductId": {
        "name": "productId",
        "in": "path",
        "required": true,
        "description": "Product unique identifier",
        "schema": {
          "type": "string"
        }
      },
      "QuoteId": {
        "name": "quoteId",
        "in": "path",
        "required": true,
        "description": "Quote unique identifier",
        "schema": {
          "type": "string"
        }
      },
      "VendorId": {
        "name": "vendorId",
        "in": "path",
        "required": true,
        "description": "Vendor unique identifier",
        "schema": {
          "type": "string"
        }
      },
      "WebhookId": {
        "name": "webhookId",
        "in": "path",
        "required": true,
        "description": "Webhook unique identifier",
        "schema": {
          "type": "string"
        }
      },
      "ContactId": {
        "name": "contactId",
        "in": "path",
        "required": true,
        "description": "Contact person unique identifier",
        "schema": {
          "type": "string"
        }
      },
      "ActivityId": {
        "name": "activityId",
        "in": "path",
        "required": true,
        "description": "Activity unique identifier",
        "schema": {
          "type": "string"
        }
      },
      "NoteId": {
        "name": "noteId",
        "in": "path",
        "required": true,
        "description": "Note unique identifier",
        "schema": {
          "type": "string"
        }
      },
      "DepositId": {
        "name": "depositId",
        "in": "path",
        "required": true,
        "description": "Deposit unique identifier",
        "schema": {
          "type": "string"
        }
      },
      "Search": {
        "name": "q",
        "in": "query",
        "description": "Full-text search query. Searches across relevant fields per resource type\n(e.g., clientName, documentNumber for invoices; name, email for clients).\nCase-insensitive.\n",
        "schema": {
          "type": "string",
          "example": "acme"
        }
      },
      "Fields": {
        "name": "fields",
        "in": "query",
        "description": "Comma-separated list of fields to include in the response.\nThe `id` field is always included. Example: `fields=id,name,total`\n",
        "schema": {
          "type": "string",
          "example": "id,name,total"
        }
      },
      "Cursor": {
        "name": "cursor",
        "in": "query",
        "description": "Cursor for cursor-based pagination. Use the `nextCursor` value from\na previous response to fetch the next page. When provided, `offset`\nis ignored. The cursor is a base64url-encoded JSON string.\n",
        "schema": {
          "type": "string",
          "example": "eyJpc3N1ZURhdGUiOiIyMDI2LTAzLTIwIiwiX19pZCI6ImFiYzEyMyJ9"
        }
      },
      "FilterClientId": {
        "name": "clientId",
        "in": "query",
        "description": "Filter invoices or quotes by client ID",
        "schema": {
          "type": "string"
        }
      },
      "FilterSeriesId": {
        "name": "seriesId",
        "in": "query",
        "description": "Filter invoices or quotes by invoice series ID",
        "schema": {
          "type": "string"
        }
      },
      "FilterVendorId": {
        "name": "vendorId",
        "in": "query",
        "description": "Filter expenses by vendor ID",
        "schema": {
          "type": "string"
        }
      },
      "FilterCategory": {
        "name": "category",
        "in": "query",
        "description": "Filter expenses by category",
        "schema": {
          "type": "string",
          "example": "office_supplies"
        }
      },
      "FilterIsActive": {
        "name": "isActive",
        "in": "query",
        "description": "Filter products by active status",
        "schema": {
          "type": "boolean",
          "example": true
        }
      },
      "FilterStage": {
        "name": "stage",
        "in": "query",
        "description": "Filter clients by pipeline stage",
        "schema": {
          "type": "string",
          "enum": [
            "lead",
            "contacted",
            "proposal",
            "active",
            "inactive",
            "lost"
          ],
          "example": "active"
        }
      },
      "IdempotencyKey": {
        "name": "Idempotency-Key",
        "in": "header",
        "required": false,
        "description": "Unique key to prevent duplicate resource creation from network retries.\nIf the same key is sent within 24 hours, the original response is returned\nwith an X-Idempotent-Replayed: true header. Max 64 characters. UUID v4 recommended.\n",
        "schema": {
          "type": "string",
          "maxLength": 64,
          "example": "550e8400-e29b-41d4-a716-446655440000"
        }
      }
    },
    "headers": {
      "X-RateLimit-Limit": {
        "description": "Maximum number of requests allowed per window",
        "schema": {
          "type": "integer",
          "example": 100
        }
      },
      "X-RateLimit-Remaining": {
        "description": "Number of requests remaining in the current window",
        "schema": {
          "type": "integer",
          "example": 87
        }
      },
      "X-RateLimit-Reset": {
        "description": "Unix timestamp (seconds) when the rate limit window resets",
        "schema": {
          "type": "integer",
          "example": 1742310060
        }
      },
      "X-API-Version": {
        "description": "Current API version date. Monitor for breaking changes.",
        "schema": {
          "type": "string",
          "example": "2026-03-18"
        }
      },
      "X-Idempotent-Replayed": {
        "description": "Present and set to \"true\" when returning a cached idempotent response",
        "schema": {
          "type": "string",
          "enum": [
            "true"
          ]
        }
      }
    },
    "schemas": {
      "InvoiceStatus": {
        "type": "string",
        "enum": [
          "draft",
          "sent",
          "partial",
          "paid",
          "overdue",
          "cancelled"
        ]
      },
      "QuoteStatus": {
        "type": "string",
        "enum": [
          "draft",
          "sent",
          "accepted",
          "rejected",
          "expired"
        ]
      },
      "LineItem": {
        "type": "object",
        "required": [
          "description",
          "quantity",
          "unitPrice"
        ],
        "properties": {
          "description": {
            "type": "string",
            "description": "Item description",
            "example": "Web development services"
          },
          "quantity": {
            "type": "number",
            "description": "Quantity",
            "example": 10
          },
          "unitPrice": {
            "type": "number",
            "description": "Price per unit",
            "example": 85
          }
        }
      },
      "Address": {
        "type": "object",
        "description": "Structured address. Canonical fields are `province` and `zip`.\nThe aliases `state` and `postalCode` are also accepted for backward compatibility.\n",
        "properties": {
          "street": {
            "type": "string",
            "example": "Calle Gran Via 28"
          },
          "city": {
            "type": "string",
            "example": "Madrid"
          },
          "province": {
            "type": "string",
            "description": "Province or state (canonical field)",
            "example": "Madrid"
          },
          "zip": {
            "type": "string",
            "description": "Postal/ZIP code (canonical field)",
            "example": "28013"
          },
          "country": {
            "type": "string",
            "example": "ES"
          },
          "state": {
            "type": "string",
            "description": "Alias for `province` (backward compatibility)",
            "deprecated": true
          },
          "postalCode": {
            "type": "string",
            "description": "Alias for `zip` (backward compatibility)",
            "deprecated": true
          }
        }
      },
      "InvoiceCreate": {
        "type": "object",
        "required": [
          "clientName",
          "items"
        ],
        "properties": {
          "clientName": {
            "type": "string",
            "description": "Client name",
            "example": "Acme Corp"
          },
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/LineItem"
            },
            "minItems": 1
          },
          "issueDate": {
            "type": "string",
            "format": "date",
            "description": "Issue date in ISO format",
            "example": "2026-03-09"
          },
          "dueDate": {
            "type": "string",
            "format": "date",
            "description": "Due date in ISO format",
            "example": "2026-04-09"
          },
          "status": {
            "$ref": "#/components/schemas/InvoiceStatus"
          },
          "notes": {
            "type": "string",
            "description": "Additional notes",
            "example": "Payment due within 30 days"
          },
          "taxRate": {
            "type": "number",
            "minimum": 0,
            "maximum": 100,
            "description": "Tax rate percentage",
            "example": 21
          },
          "recurring": {
            "$ref": "#/components/schemas/InvoiceRecurringConfig"
          }
        }
      },
      "Invoice": {
        "allOf": [
          {
            "type": "object",
            "properties": {
              "id": {
                "type": "string",
                "description": "Unique identifier",
                "example": "abc123def456"
              },
              "createdAt": {
                "type": "string",
                "format": "date-time",
                "description": "Creation timestamp"
              },
              "updatedAt": {
                "type": "string",
                "format": "date-time",
                "description": "Last update timestamp"
              }
            }
          },
          {
            "$ref": "#/components/schemas/InvoiceCreate"
          },
          {
            "type": "object",
            "properties": {
              "documentNumber": {
                "type": "string",
                "description": "Auto-generated invoice number",
                "example": "FAC-2026-0042"
              },
              "subtotal": {
                "type": "number",
                "description": "Subtotal before tax",
                "example": 850
              },
              "tax": {
                "type": "number",
                "description": "Tax amount",
                "example": 178.5
              },
              "total": {
                "type": "number",
                "description": "Total amount including tax",
                "example": 1028.5
              },
              "currency": {
                "type": "string",
                "description": "Currency code",
                "example": "EUR"
              },
              "verifactuHash": {
                "type": "string",
                "description": "VeriFactu SHA-256 hash (Spanish tax compliance)"
              }
            }
          }
        ]
      },
      "ExpenseCreate": {
        "type": "object",
        "required": [
          "description",
          "amount"
        ],
        "properties": {
          "description": {
            "type": "string",
            "description": "Expense description",
            "example": "Office supplies"
          },
          "amount": {
            "type": "number",
            "description": "Expense amount",
            "example": 45.99
          },
          "date": {
            "type": "string",
            "format": "date",
            "description": "Expense date in ISO format",
            "example": "2026-03-09"
          },
          "category": {
            "type": "string",
            "description": "Expense category",
            "example": "office"
          },
          "vendor": {
            "type": "string",
            "description": "Vendor or supplier name",
            "example": "Office Depot"
          },
          "taxDeductible": {
            "type": "boolean",
            "description": "Whether the expense is tax deductible",
            "example": true
          },
          "recurring": {
            "$ref": "#/components/schemas/ExpenseRecurringConfig"
          }
        }
      },
      "Expense": {
        "allOf": [
          {
            "type": "object",
            "properties": {
              "id": {
                "type": "string",
                "description": "Unique identifier"
              },
              "createdAt": {
                "type": "string",
                "format": "date-time"
              },
              "updatedAt": {
                "type": "string",
                "format": "date-time"
              }
            }
          },
          {
            "$ref": "#/components/schemas/ExpenseCreate"
          }
        ]
      },
      "InvoiceRecurringConfig": {
        "type": "object",
        "required": [
          "enabled",
          "frequency",
          "nextDate"
        ],
        "description": "Recurring invoice configuration. Set on a template invoice to auto-generate copies on schedule.",
        "properties": {
          "enabled": {
            "type": "boolean",
            "description": "Whether recurring generation is active",
            "example": true
          },
          "frequency": {
            "type": "string",
            "enum": [
              "weekly",
              "biweekly",
              "monthly",
              "quarterly",
              "yearly"
            ],
            "description": "How often to generate a new invoice",
            "example": "monthly"
          },
          "nextDate": {
            "type": "string",
            "format": "date",
            "description": "Next scheduled generation date (ISO YYYY-MM-DD)",
            "example": "2026-04-01"
          },
          "endDate": {
            "type": "string",
            "format": "date",
            "description": "Stop generating after this date (optional)",
            "example": "2027-03-31"
          },
          "maxOccurrences": {
            "type": "integer",
            "minimum": 1,
            "description": "Maximum number of invoices to generate (optional)",
            "example": 12
          },
          "autoSend": {
            "type": "boolean",
            "description": "Automatically send generated invoices to the client",
            "default": false,
            "example": false
          },
          "occurrencesGenerated": {
            "type": "integer",
            "readOnly": true,
            "description": "Number of invoices generated so far (server-managed, read-only)",
            "example": 0
          },
          "lastGeneratedId": {
            "type": "string",
            "readOnly": true,
            "description": "ID of the last auto-generated invoice (server-managed, read-only)"
          }
        }
      },
      "ExpenseRecurringConfig": {
        "type": "object",
        "required": [
          "enabled",
          "frequency",
          "nextDate"
        ],
        "description": "Recurring expense configuration. Set on a template expense to auto-generate copies on schedule.",
        "properties": {
          "enabled": {
            "type": "boolean",
            "description": "Whether recurring generation is active",
            "example": true
          },
          "frequency": {
            "type": "string",
            "enum": [
              "weekly",
              "biweekly",
              "monthly",
              "quarterly",
              "yearly"
            ],
            "description": "How often to generate a new expense",
            "example": "monthly"
          },
          "nextDate": {
            "type": "string",
            "format": "date",
            "description": "Next scheduled generation date (ISO YYYY-MM-DD)",
            "example": "2026-04-01"
          },
          "endDate": {
            "type": "string",
            "format": "date",
            "description": "Stop generating after this date (optional)",
            "example": "2027-03-31"
          },
          "maxOccurrences": {
            "type": "integer",
            "minimum": 1,
            "description": "Maximum number of expenses to generate (optional)",
            "example": 12
          },
          "occurrencesGenerated": {
            "type": "integer",
            "readOnly": true,
            "description": "Number of expenses generated so far (server-managed, read-only)",
            "example": 0
          }
        }
      },
      "ClientCreate": {
        "type": "object",
        "required": [
          "name"
        ],
        "properties": {
          "name": {
            "type": "string",
            "description": "Client name (person or company)",
            "example": "Acme Corp"
          },
          "email": {
            "type": "string",
            "format": "email",
            "description": "Contact email",
            "example": "billing@acme.com"
          },
          "phone": {
            "type": "string",
            "description": "Phone number",
            "example": "+34 912 345 678"
          },
          "taxId": {
            "type": "string",
            "description": "Tax identification number (NIF/CIF/VAT)",
            "example": "B12345678"
          },
          "address": {
            "$ref": "#/components/schemas/Address"
          }
        }
      },
      "Client": {
        "allOf": [
          {
            "type": "object",
            "properties": {
              "id": {
                "type": "string",
                "description": "Unique identifier"
              },
              "createdAt": {
                "type": "string",
                "format": "date-time"
              },
              "updatedAt": {
                "type": "string",
                "format": "date-time"
              }
            }
          },
          {
            "$ref": "#/components/schemas/ClientCreate"
          }
        ]
      },
      "ContactCreate": {
        "type": "object",
        "required": [
          "name"
        ],
        "properties": {
          "name": {
            "type": "string",
            "description": "Contact person name",
            "example": "Maria Garcia"
          },
          "email": {
            "type": "string",
            "format": "email",
            "description": "Contact email",
            "example": "maria@acme.es"
          },
          "phone": {
            "type": "string",
            "description": "Phone number",
            "example": "+34 612 345 678"
          },
          "role": {
            "type": "string",
            "description": "Job title or role",
            "example": "CFO"
          },
          "isPrimary": {
            "type": "boolean",
            "description": "Whether this is the primary contact for the client",
            "default": false
          }
        }
      },
      "Contact": {
        "allOf": [
          {
            "type": "object",
            "properties": {
              "id": {
                "type": "string",
                "description": "Unique identifier"
              },
              "createdAt": {
                "type": "string",
                "format": "date-time"
              },
              "updatedAt": {
                "type": "string",
                "format": "date-time"
              }
            }
          },
          {
            "$ref": "#/components/schemas/ContactCreate"
          }
        ]
      },
      "ActivityType": {
        "type": "string",
        "enum": [
          "call",
          "email",
          "meeting",
          "task"
        ],
        "description": "Manual activity types. System types (invoice_created, quote_sent, etc.) are auto-generated."
      },
      "ActivityCreate": {
        "type": "object",
        "required": [
          "type",
          "title"
        ],
        "properties": {
          "type": {
            "$ref": "#/components/schemas/ActivityType"
          },
          "title": {
            "type": "string",
            "description": "Descriptive title for the activity",
            "example": "Follow-up call on Q2 budget"
          },
          "description": {
            "type": "string",
            "description": "Detailed description",
            "example": "Discussed budget terms. Awaiting confirmation."
          },
          "metadata": {
            "type": "object",
            "additionalProperties": true,
            "description": "Free-form additional data"
          }
        }
      },
      "Activity": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Unique identifier"
          },
          "type": {
            "type": "string",
            "description": "Activity type (manual or system-generated)"
          },
          "title": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "metadata": {
            "type": "object",
            "additionalProperties": true
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "NoteCreate": {
        "type": "object",
        "required": [
          "content"
        ],
        "properties": {
          "content": {
            "type": "string",
            "description": "Note content",
            "example": "Client interested in Business plan. Follow up in April."
          }
        }
      },
      "Note": {
        "allOf": [
          {
            "type": "object",
            "properties": {
              "id": {
                "type": "string",
                "description": "Unique identifier"
              },
              "createdAt": {
                "type": "string",
                "format": "date-time"
              },
              "updatedAt": {
                "type": "string",
                "format": "date-time"
              }
            }
          },
          {
            "$ref": "#/components/schemas/NoteCreate"
          }
        ]
      },
      "ProductCreate": {
        "type": "object",
        "required": [
          "name",
          "unitPrice"
        ],
        "properties": {
          "name": {
            "type": "string",
            "description": "Product or service name",
            "example": "Consulting Hour"
          },
          "unitPrice": {
            "type": "number",
            "description": "Unit price",
            "example": 120
          },
          "description": {
            "type": "string",
            "description": "Product description",
            "example": "One hour of strategic consulting"
          },
          "taxRate": {
            "type": "number",
            "minimum": 0,
            "maximum": 100,
            "description": "Default tax rate percentage",
            "example": 21
          }
        }
      },
      "Product": {
        "allOf": [
          {
            "type": "object",
            "properties": {
              "id": {
                "type": "string",
                "description": "Unique identifier"
              },
              "createdAt": {
                "type": "string",
                "format": "date-time"
              },
              "updatedAt": {
                "type": "string",
                "format": "date-time"
              }
            }
          },
          {
            "$ref": "#/components/schemas/ProductCreate"
          }
        ]
      },
      "QuoteCreate": {
        "type": "object",
        "required": [
          "clientName",
          "items"
        ],
        "properties": {
          "clientName": {
            "type": "string",
            "description": "Client name",
            "example": "Acme Corp"
          },
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/LineItem"
            },
            "minItems": 1
          },
          "validUntil": {
            "type": "string",
            "format": "date",
            "description": "Quote expiration date",
            "example": "2026-04-09"
          },
          "status": {
            "$ref": "#/components/schemas/QuoteStatus"
          },
          "notes": {
            "type": "string",
            "description": "Additional notes",
            "example": "Valid for 30 days"
          }
        }
      },
      "Quote": {
        "allOf": [
          {
            "type": "object",
            "properties": {
              "id": {
                "type": "string",
                "description": "Unique identifier"
              },
              "createdAt": {
                "type": "string",
                "format": "date-time"
              },
              "updatedAt": {
                "type": "string",
                "format": "date-time"
              }
            }
          },
          {
            "$ref": "#/components/schemas/QuoteCreate"
          },
          {
            "type": "object",
            "properties": {
              "documentNumber": {
                "type": "string",
                "description": "Auto-generated quote number",
                "example": "PRE-2026-0015"
              },
              "subtotal": {
                "type": "number",
                "description": "Subtotal before tax"
              },
              "tax": {
                "type": "number",
                "description": "Tax amount"
              },
              "total": {
                "type": "number",
                "description": "Total amount including tax"
              }
            }
          }
        ]
      },
      "SendEmailRequest": {
        "type": "object",
        "required": [
          "recipientEmail"
        ],
        "properties": {
          "recipientEmail": {
            "type": "string",
            "format": "email",
            "description": "Recipient email address",
            "example": "client@example.com"
          },
          "recipientName": {
            "type": "string",
            "description": "Recipient name",
            "example": "John Doe"
          },
          "customMessage": {
            "type": "string",
            "description": "Optional custom message to include in the email",
            "example": "Please find attached your invoice."
          },
          "locale": {
            "type": "string",
            "enum": [
              "es",
              "en"
            ],
            "default": "es",
            "description": "Email language"
          }
        }
      },
      "Summary": {
        "type": "object",
        "properties": {
          "period": {
            "type": "object",
            "properties": {
              "from": {
                "type": "string",
                "format": "date",
                "nullable": true
              },
              "to": {
                "type": "string",
                "format": "date",
                "nullable": true
              }
            }
          },
          "revenue": {
            "type": "object",
            "properties": {
              "invoiced": {
                "type": "number",
                "description": "Total invoiced amount",
                "example": 25000
              },
              "paid": {
                "type": "number",
                "description": "Total paid amount",
                "example": 18500
              },
              "pending": {
                "type": "number",
                "description": "Total pending (sent but unpaid)",
                "example": 4500
              },
              "overdue": {
                "type": "number",
                "description": "Total overdue amount",
                "example": 2000
              }
            }
          },
          "expenses": {
            "type": "object",
            "properties": {
              "total": {
                "type": "number",
                "description": "Total expenses",
                "example": 8200
              }
            }
          },
          "profit": {
            "type": "number",
            "description": "Net profit (paid revenue minus expenses)",
            "example": 10300
          },
          "counts": {
            "type": "object",
            "properties": {
              "invoices": {
                "type": "integer",
                "example": 42
              },
              "quotes": {
                "type": "integer",
                "example": 15
              },
              "expenses": {
                "type": "integer",
                "example": 87
              },
              "clients": {
                "type": "integer",
                "example": 23
              },
              "products": {
                "type": "integer",
                "example": 12
              }
            }
          },
          "invoicesByStatus": {
            "type": "object",
            "additionalProperties": {
              "type": "integer"
            },
            "example": {
              "draft": 3,
              "sent": 8,
              "paid": 28,
              "overdue": 3
            }
          },
          "overdue": {
            "type": "object",
            "properties": {
              "count": {
                "type": "integer",
                "example": 3
              },
              "amount": {
                "type": "number",
                "example": 2000
              }
            }
          }
        }
      },
      "PaginatedResponse": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {}
          },
          "total": {
            "type": "integer",
            "description": "Total number of items matching the query"
          },
          "limit": {
            "type": "integer",
            "description": "Number of items per page"
          },
          "offset": {
            "type": "integer",
            "description": "Current offset"
          },
          "nextCursor": {
            "type": "string",
            "description": "Cursor for fetching the next page of results. Only present when there\nare more results available. Pass this value as the `cursor` query parameter\nin the next request. Base64url-encoded.\n",
            "example": "eyJpc3N1ZURhdGUiOiIyMDI2LTAzLTIwIiwiX19pZCI6ImFiYzEyMyJ9"
          }
        }
      },
      "DepositStatus": {
        "type": "string",
        "enum": [
          "active",
          "partially_applied",
          "fully_applied",
          "refunded"
        ]
      },
      "DepositCreate": {
        "type": "object",
        "required": [
          "clientId",
          "clientName",
          "amount",
          "description",
          "receivedDate"
        ],
        "properties": {
          "clientId": {
            "type": "string",
            "description": "ID of the client who made the deposit",
            "example": "client_abc123"
          },
          "clientName": {
            "type": "string",
            "description": "Client name (denormalized for display)",
            "example": "Acme Corp"
          },
          "amount": {
            "type": "number",
            "description": "Deposit amount (must be positive)",
            "example": 750
          },
          "currency": {
            "type": "string",
            "description": "Currency code (ISO 4217)",
            "default": "EUR",
            "example": "EUR"
          },
          "description": {
            "type": "string",
            "description": "Description of the deposit",
            "example": "Prepayment for Q2 project"
          },
          "receivedDate": {
            "type": "string",
            "format": "date",
            "description": "Date the deposit was received (YYYY-MM-DD)",
            "example": "2026-04-01"
          },
          "paymentMethod": {
            "type": "string",
            "description": "Payment method used",
            "example": "bank_transfer"
          },
          "paymentReference": {
            "type": "string",
            "description": "Payment reference or transaction ID",
            "example": "TRF-2026-0042"
          }
        }
      },
      "Deposit": {
        "allOf": [
          {
            "type": "object",
            "properties": {
              "id": {
                "type": "string",
                "description": "Unique identifier",
                "example": "dep_abc123"
              },
              "createdAt": {
                "type": "string",
                "format": "date-time"
              },
              "updatedAt": {
                "type": "string",
                "format": "date-time"
              }
            }
          },
          {
            "$ref": "#/components/schemas/DepositCreate"
          },
          {
            "type": "object",
            "properties": {
              "status": {
                "$ref": "#/components/schemas/DepositStatus"
              },
              "appliedAmount": {
                "type": "number",
                "description": "Total amount already applied to invoices",
                "example": 250
              },
              "remainingBalance": {
                "type": "number",
                "description": "Remaining balance available for application or refund",
                "example": 500
              },
              "refundedAmount": {
                "type": "number",
                "description": "Total amount refunded to the client",
                "example": 0
              },
              "applications": {
                "type": "array",
                "description": "List of invoice applications for this deposit",
                "items": {
                  "type": "object",
                  "properties": {
                    "invoiceId": {
                      "type": "string"
                    },
                    "invoiceNumber": {
                      "type": "string"
                    },
                    "amount": {
                      "type": "number"
                    },
                    "appliedAt": {
                      "type": "string",
                      "format": "date"
                    }
                  }
                }
              }
            }
          }
        ]
      },
      "VendorCreate": {
        "type": "object",
        "required": [
          "name"
        ],
        "properties": {
          "name": {
            "type": "string",
            "description": "Vendor name (person or company)",
            "example": "Office Depot"
          },
          "email": {
            "type": "string",
            "format": "email",
            "description": "Contact email",
            "example": "billing@officedepot.com"
          },
          "phone": {
            "type": "string",
            "description": "Phone number",
            "example": "+34 912 345 678"
          },
          "taxId": {
            "type": "string",
            "description": "Tax identification number (NIF/CIF/VAT)",
            "example": "B87654321"
          },
          "address": {
            "$ref": "#/components/schemas/Address"
          }
        }
      },
      "Vendor": {
        "allOf": [
          {
            "type": "object",
            "properties": {
              "id": {
                "type": "string",
                "description": "Unique identifier"
              },
              "createdAt": {
                "type": "string",
                "format": "date-time"
              },
              "updatedAt": {
                "type": "string",
                "format": "date-time"
              }
            }
          },
          {
            "$ref": "#/components/schemas/VendorCreate"
          }
        ]
      },
      "WebhookCreate": {
        "type": "object",
        "required": [
          "name",
          "url",
          "events"
        ],
        "properties": {
          "name": {
            "type": "string",
            "description": "Webhook name",
            "maxLength": 200,
            "example": "Invoice notifications"
          },
          "url": {
            "type": "string",
            "format": "uri",
            "description": "Endpoint URL to receive webhook events",
            "maxLength": 2000,
            "example": "https://example.com/webhooks/frihet"
          },
          "secret": {
            "type": "string",
            "description": "HMAC secret for verifying webhook signatures",
            "maxLength": 500
          },
          "events": {
            "type": "array",
            "items": {
              "type": "string",
              "maxLength": 100
            },
            "minItems": 1,
            "description": "List of event types to subscribe to",
            "example": [
              "invoice.created",
              "invoice.paid",
              "expense.created"
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "inactive"
            ],
            "default": "active"
          },
          "metadata": {
            "type": "object",
            "additionalProperties": true,
            "description": "Arbitrary metadata to attach to the webhook"
          }
        }
      },
      "WebhookUpdate": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "maxLength": 200
          },
          "url": {
            "type": "string",
            "format": "uri",
            "maxLength": 2000
          },
          "secret": {
            "type": "string",
            "maxLength": 500
          },
          "events": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "minItems": 1
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "inactive",
              "paused"
            ]
          },
          "metadata": {
            "type": "object",
            "additionalProperties": true
          }
        }
      },
      "Webhook": {
        "allOf": [
          {
            "type": "object",
            "properties": {
              "id": {
                "type": "string",
                "description": "Unique identifier"
              },
              "createdAt": {
                "type": "string",
                "format": "date-time"
              },
              "updatedAt": {
                "type": "string",
                "format": "date-time"
              },
              "userId": {
                "type": "string"
              }
            }
          },
          {
            "$ref": "#/components/schemas/WebhookCreate"
          }
        ]
      },
      "BatchResponse": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "index": {
                  "type": "integer",
                  "description": "Index of the item in the original request array"
                },
                "success": {
                  "type": "boolean"
                },
                "data": {
                  "type": "object",
                  "description": "Created resource (only when success is true)"
                },
                "error": {
                  "type": "string",
                  "description": "Error message (only when success is false)"
                },
                "details": {
                  "type": "array",
                  "description": "Validation error details (only on validation failure)",
                  "items": {
                    "type": "object"
                  }
                }
              }
            }
          },
          "summary": {
            "type": "object",
            "properties": {
              "total": {
                "type": "integer",
                "description": "Total items in request",
                "example": 10
              },
              "succeeded": {
                "type": "integer",
                "description": "Number of successfully created items",
                "example": 8
              },
              "failed": {
                "type": "integer",
                "description": "Number of failed items",
                "example": 2
              }
            }
          },
          "meta": {
            "type": "object",
            "properties": {
              "requestId": {
                "type": "string"
              },
              "timestamp": {
                "type": "string",
                "format": "date-time"
              }
            }
          }
        }
      },
      "BusinessContext": {
        "type": "object",
        "description": "Comprehensive business context snapshot for AI agents",
        "properties": {
          "data": {
            "type": "object",
            "properties": {
              "business": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string"
                  },
                  "taxId": {
                    "type": "string"
                  },
                  "fiscalZone": {
                    "type": "string"
                  },
                  "currency": {
                    "type": "string"
                  },
                  "language": {
                    "type": "string"
                  },
                  "country": {
                    "type": "string"
                  }
                }
              },
              "defaults": {
                "type": "object",
                "properties": {
                  "taxRate": {
                    "type": "number"
                  },
                  "irpfRate": {
                    "type": "number"
                  },
                  "dueDays": {
                    "type": "integer"
                  },
                  "currency": {
                    "type": "string"
                  }
                }
              },
              "plan": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "example": "pro"
                  },
                  "invoices": {
                    "type": "object",
                    "properties": {
                      "used": {
                        "type": "integer"
                      },
                      "limit": {
                        "type": "integer"
                      }
                    }
                  },
                  "expenses": {
                    "type": "object",
                    "properties": {
                      "used": {
                        "type": "integer"
                      },
                      "limit": {
                        "type": "integer"
                      }
                    }
                  },
                  "aiMessages": {
                    "type": "object",
                    "properties": {
                      "used": {
                        "type": "integer"
                      },
                      "limit": {
                        "type": "integer"
                      }
                    }
                  }
                }
              },
              "series": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "prefix": {
                      "type": "string"
                    },
                    "current": {
                      "type": "integer"
                    },
                    "year": {
                      "type": "integer"
                    }
                  }
                }
              },
              "recentActivity": {
                "type": "object",
                "properties": {
                  "lastInvoice": {
                    "type": "object",
                    "nullable": true,
                    "properties": {
                      "number": {
                        "type": "string"
                      },
                      "date": {
                        "type": "string"
                      },
                      "client": {
                        "type": "string"
                      }
                    }
                  },
                  "lastExpense": {
                    "type": "object",
                    "nullable": true,
                    "properties": {
                      "date": {
                        "type": "string"
                      },
                      "vendor": {
                        "type": "string"
                      },
                      "amount": {
                        "type": "number"
                      }
                    }
                  },
                  "overdueCount": {
                    "type": "integer"
                  },
                  "overdueAmount": {
                    "type": "number"
                  },
                  "unpaidCount": {
                    "type": "integer"
                  }
                }
              },
              "topClients": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "name": {
                      "type": "string"
                    },
                    "totalRevenue": {
                      "type": "number"
                    },
                    "invoiceCount": {
                      "type": "integer"
                    }
                  }
                }
              },
              "currentMonth": {
                "type": "object",
                "properties": {
                  "revenue": {
                    "type": "number"
                  },
                  "expenses": {
                    "type": "number"
                  },
                  "profit": {
                    "type": "number"
                  },
                  "invoiceCount": {
                    "type": "integer"
                  },
                  "expenseCount": {
                    "type": "integer"
                  }
                }
              }
            }
          },
          "meta": {
            "type": "object",
            "properties": {
              "requestId": {
                "type": "string"
              },
              "timestamp": {
                "type": "string",
                "format": "date-time"
              }
            }
          }
        }
      },
      "MonthlySummary": {
        "type": "object",
        "properties": {
          "data": {
            "type": "object",
            "properties": {
              "period": {
                "type": "string",
                "example": "2026-03"
              },
              "revenue": {
                "type": "object",
                "properties": {
                  "total": {
                    "type": "number"
                  },
                  "taxBase": {
                    "type": "number"
                  },
                  "tax": {
                    "type": "number"
                  },
                  "irpf": {
                    "type": "number"
                  }
                }
              },
              "expenses": {
                "type": "object",
                "properties": {
                  "total": {
                    "type": "number"
                  },
                  "deductible": {
                    "type": "number"
                  },
                  "tax": {
                    "type": "number"
                  }
                }
              },
              "profit": {
                "type": "object",
                "properties": {
                  "gross": {
                    "type": "number"
                  },
                  "net": {
                    "type": "number"
                  }
                }
              },
              "invoices": {
                "type": "object",
                "properties": {
                  "created": {
                    "type": "integer"
                  },
                  "sent": {
                    "type": "integer"
                  },
                  "paid": {
                    "type": "integer"
                  },
                  "overdue": {
                    "type": "integer"
                  }
                }
              },
              "topClients": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "name": {
                      "type": "string"
                    },
                    "totalRevenue": {
                      "type": "number"
                    },
                    "invoiceCount": {
                      "type": "integer"
                    }
                  }
                }
              },
              "byCategory": {
                "type": "object",
                "additionalProperties": {
                  "type": "number"
                },
                "description": "Expense totals grouped by category"
              },
              "taxLiability": {
                "type": "object",
                "properties": {
                  "vatPayable": {
                    "type": "number",
                    "description": "Net VAT payable (output - input)"
                  },
                  "irpfRetained": {
                    "type": "number"
                  },
                  "estimatedModel303": {
                    "type": "number"
                  }
                }
              }
            }
          },
          "meta": {
            "type": "object",
            "properties": {
              "requestId": {
                "type": "string"
              },
              "timestamp": {
                "type": "string",
                "format": "date-time"
              }
            }
          }
        }
      },
      "QuarterlySummary": {
        "type": "object",
        "properties": {
          "data": {
            "type": "object",
            "properties": {
              "period": {
                "type": "string",
                "example": "2026-Q1"
              },
              "months": {
                "type": "array",
                "items": {
                  "type": "string"
                },
                "example": [
                  "2026-01",
                  "2026-02",
                  "2026-03"
                ]
              },
              "modelo303": {
                "type": "object",
                "description": "Pre-filled Modelo 303 (VAT return) figures",
                "properties": {
                  "baseImponible": {
                    "type": "number",
                    "description": "Total tax base"
                  },
                  "cuotaRepercutida": {
                    "type": "number",
                    "description": "Output VAT (charged to clients)"
                  },
                  "baseDeducible": {
                    "type": "number",
                    "description": "Deductible expense base"
                  },
                  "cuotaDeducible": {
                    "type": "number",
                    "description": "Input VAT (paid on deductible expenses)"
                  },
                  "resultado": {
                    "type": "number",
                    "description": "Net VAT (output - input)"
                  }
                }
              },
              "modelo130": {
                "type": "object",
                "description": "Pre-filled Modelo 130 (quarterly income payment) figures",
                "properties": {
                  "ingresos": {
                    "type": "number",
                    "description": "Total income (tax base)"
                  },
                  "gastos": {
                    "type": "number",
                    "description": "Total deductible expenses"
                  },
                  "rendimientoNeto": {
                    "type": "number",
                    "description": "Net income (ingresos - gastos)"
                  },
                  "pagoFraccionado": {
                    "type": "number",
                    "description": "Estimated quarterly payment (20% of net income)"
                  }
                }
              },
              "summary": {
                "type": "object",
                "properties": {
                  "totalRevenue": {
                    "type": "number"
                  },
                  "totalExpenses": {
                    "type": "number"
                  },
                  "invoiceCount": {
                    "type": "integer"
                  },
                  "clientCount": {
                    "type": "integer"
                  }
                }
              }
            }
          },
          "meta": {
            "type": "object",
            "properties": {
              "requestId": {
                "type": "string"
              },
              "timestamp": {
                "type": "string",
                "format": "date-time"
              }
            }
          }
        }
      },
      "Error": {
        "type": "object",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "string",
            "description": "Human-readable error message"
          },
          "details": {
            "type": "array",
            "description": "Validation error details (Zod issues). Only present on 400 validation errors.",
            "items": {
              "type": "object",
              "properties": {
                "code": {
                  "type": "string"
                },
                "message": {
                  "type": "string"
                },
                "path": {
                  "type": "array",
                  "items": {
                    "type": "string"
                  }
                }
              }
            }
          },
          "meta": {
            "type": "object",
            "properties": {
              "requestId": {
                "type": "string",
                "description": "Unique request identifier for tracing"
              }
            }
          }
        }
      }
    },
    "responses": {
      "BadRequest": {
        "description": "Bad request - invalid parameters or request body",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "error": "Validation error",
              "details": [
                {
                  "code": "invalid_type",
                  "message": "Required",
                  "path": [
                    "clientName"
                  ]
                }
              ],
              "meta": {
                "requestId": "550e8400-e29b-41d4-a716-446655440000"
              }
            }
          }
        }
      },
      "Unauthorized": {
        "description": "Authentication required or invalid API key",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "error": "Invalid or expired API key",
              "meta": {
                "requestId": "550e8400-e29b-41d4-a716-446655440000"
              }
            }
          }
        }
      },
      "Forbidden": {
        "description": "Insufficient permissions",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "error": "Insufficient permissions",
              "meta": {
                "requestId": "550e8400-e29b-41d4-a716-446655440000"
              }
            }
          }
        }
      },
      "NotFound": {
        "description": "Resource not found",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "error": "Resource not found",
              "meta": {
                "requestId": "550e8400-e29b-41d4-a716-446655440000"
              }
            }
          }
        }
      },
      "RateLimited": {
        "description": "Rate limit exceeded (100 requests per minute)",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "properties": {
                "error": {
                  "type": "string",
                  "example": "Rate limit exceeded"
                },
                "message": {
                  "type": "string",
                  "example": "Maximum 100 requests per minute"
                },
                "retryAfter": {
                  "type": "integer",
                  "description": "Seconds until rate limit resets",
                  "example": 60
                },
                "meta": {
                  "type": "object",
                  "properties": {
                    "requestId": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        }
      },
      "InternalError": {
        "description": "Internal server error",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "error": "Internal server error",
              "meta": {
                "requestId": "550e8400-e29b-41d4-a716-446655440000"
              }
            }
          }
        }
      }
    }
  }
}