{
  "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)."
    },
    {
      "name": "Reservations",
      "description": "Frihet Stay: Manage vacation rental reservations with guest info, dates, and compliance tracking."
    },
    {
      "name": "Properties",
      "description": "Frihet Stay: Manage rental properties with owner info, capacity, and licensing."
    },
    {
      "name": "Guests",
      "description": "Frihet Stay: Read compliance records for guest check-in (document verification, police reports)."
    },
    {
      "name": "Channels",
      "description": "Frihet Stay: Manage channel connections (iCal feeds) for calendar sync with OTAs."
    },
    {
      "name": "E-Invoicing",
      "description": "EN16931-compliant e-invoicing export and B2G submission endpoints.\nSupports 8 formats (Facturae, XRechnung-CII/UBL, Factur-X, FatturaPA, PEPPOL-BIS-3, UBL, CII).\nFACe (Spain B2G portal) and TicketBAI (Bizkaia BATUZ) submission pipelines.\nTrust Area: COMPLIANCE. Requires owner role or API key with `einvoice:*` scope.\n"
    }
  ],
  "paths": {
    "/v1/gestoria/aging": {
      "post": {
        "operationId": "gestoriaAgingConsolidated",
        "summary": "Consolidated AR aging across client workspaces",
        "description": "For an accountant/gestor, returns accounts-receivable aging consolidated across the given client workspaces. Each workspaceId is authorised per-workspace: the caller must be an active accountant or owner member of that workspace, otherwise it is silently rejected and listed in rejectedWorkspaceIds (no data returned for it).\n",
        "tags": [
          "Gestoria"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "workspaceIds"
                ],
                "properties": {
                  "workspaceIds": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "minItems": 1,
                    "maxItems": 200,
                    "description": "Client workspace UIDs the caller manages."
                  },
                  "asOf": {
                    "type": "string",
                    "format": "date",
                    "description": "Reference date (YYYY-MM-DD). Defaults to today."
                  },
                  "bustCache": {
                    "type": "boolean",
                    "description": "Honoured only by the callable CF; REST always computes fresh."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Consolidated aging report",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "workspaces": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "workspaceId": {
                                "type": "string"
                              },
                              "ownerName": {
                                "type": "string"
                              },
                              "buckets": {
                                "type": "object",
                                "properties": {
                                  "current": {
                                    "type": "number"
                                  },
                                  "days1_30": {
                                    "type": "number"
                                  },
                                  "days31_60": {
                                    "type": "number"
                                  },
                                  "days61_90": {
                                    "type": "number"
                                  },
                                  "days90plus": {
                                    "type": "number"
                                  }
                                }
                              },
                              "grandTotal": {
                                "type": "number"
                              },
                              "totalOverdue": {
                                "type": "number"
                              },
                              "asOf": {
                                "type": "string"
                              },
                              "currency": {
                                "type": "string"
                              },
                              "topDebtors": {
                                "type": "array",
                                "items": {
                                  "type": "object",
                                  "properties": {
                                    "clientId": {
                                      "type": "string"
                                    },
                                    "clientName": {
                                      "type": "string"
                                    },
                                    "totalOutstanding": {
                                      "type": "number"
                                    },
                                    "daysOldestInvoice": {
                                      "type": "number"
                                    },
                                    "invoiceCount": {
                                      "type": "number"
                                    }
                                  }
                                }
                              }
                            }
                          }
                        },
                        "rejectedWorkspaceIds": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "description": "Workspaces the caller is not an authorised member of."
                        },
                        "consolidatedBuckets": {
                          "type": "object",
                          "properties": {
                            "current": {
                              "type": "number"
                            },
                            "days1_30": {
                              "type": "number"
                            },
                            "days31_60": {
                              "type": "number"
                            },
                            "days61_90": {
                              "type": "number"
                            },
                            "days90plus": {
                              "type": "number"
                            }
                          }
                        },
                        "consolidatedTotal": {
                          "type": "number"
                        },
                        "consolidatedOverdue": {
                          "type": "number"
                        },
                        "asOf": {
                          "type": "string"
                        },
                        "generatedAt": {
                          "type": "string",
                          "format": "date-time"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      }
    },
    "/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.\n\nIf `taxId` is provided and another client in your workspace already has the\nsame taxId (normalized: case-insensitive, ignoring separators like dots and\nhyphens), the request is rejected with `409 CLIENT_TAXID_EXISTS` and the\nexisting client's id is returned in `existingClientId`.\n",
        "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"
          },
          "409": {
            "description": "A client with this taxId already exists in your workspace.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "CLIENT_TAXID_EXISTS"
                    },
                    "message": {
                      "type": "string",
                      "example": "Client with this taxId already exists"
                    },
                    "existingClientId": {
                      "type": "string",
                      "description": "Document id of the existing client with the same taxId."
                    },
                    "taxId": {
                      "type": "string",
                      "description": "GDPR-masked form of the conflicting taxId (e.g. \"43******K\")."
                    }
                  }
                }
              }
            }
          },
          "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. Returns `409 CLIENT_TAXID_EXISTS`\nif the new `taxId` is already in use by another client in your workspace.\n",
        "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"
          },
          "409": {
            "description": "Another client with this taxId already exists in your workspace.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "CLIENT_TAXID_EXISTS"
                    },
                    "existingClientId": {
                      "type": "string"
                    },
                    "taxId": {
                      "type": "string",
                      "description": "GDPR-masked form of the conflicting taxId."
                    }
                  }
                }
              }
            }
          },
          "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. Returns\n`409 CLIENT_TAXID_EXISTS` if the new `taxId` is already in use by\nanother client in your workspace.\n",
        "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"
          },
          "409": {
            "description": "Another client with this taxId already exists in your workspace.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "CLIENT_TAXID_EXISTS"
                    },
                    "existingClientId": {
                      "type": "string"
                    },
                    "taxId": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "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"
          }
        }
      }
    },
    "/v1/reservations": {
      "get": {
        "operationId": "listReservations",
        "summary": "List reservations",
        "description": "Retrieve a paginated list of Stay reservations with optional filters.",
        "tags": [
          "Reservations"
        ],
        "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"
          },
          {
            "name": "status",
            "in": "query",
            "schema": {
              "$ref": "#/components/schemas/ReservationStatus"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A paginated list of reservations",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/PaginatedResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/Reservation"
                          }
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "post": {
        "operationId": "createReservation",
        "summary": "Create a reservation",
        "tags": [
          "Reservations"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ReservationCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Reservation created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Reservation"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/reservations/{reservationId}": {
      "get": {
        "operationId": "getReservation",
        "summary": "Get a reservation",
        "tags": [
          "Reservations"
        ],
        "parameters": [
          {
            "name": "reservationId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/Fields"
          }
        ],
        "responses": {
          "200": {
            "description": "Reservation details",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Reservation"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      },
      "patch": {
        "operationId": "updateReservation",
        "summary": "Update a reservation",
        "tags": [
          "Reservations"
        ],
        "parameters": [
          {
            "name": "reservationId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ReservationCreate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Reservation updated",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Reservation"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/v1/properties": {
      "get": {
        "operationId": "listProperties",
        "summary": "List properties",
        "description": "Retrieve a paginated list of Stay properties.",
        "tags": [
          "Properties"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Offset"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "$ref": "#/components/parameters/Search"
          },
          {
            "$ref": "#/components/parameters/Fields"
          },
          {
            "name": "status",
            "in": "query",
            "schema": {
              "$ref": "#/components/schemas/PropertyStatus"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A paginated list of properties",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/PaginatedResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/Property"
                          }
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "post": {
        "operationId": "createProperty",
        "summary": "Create a property",
        "tags": [
          "Properties"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PropertyCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Property created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Property"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      }
    },
    "/v1/properties/{propertyId}": {
      "get": {
        "operationId": "getProperty",
        "summary": "Get a property",
        "tags": [
          "Properties"
        ],
        "parameters": [
          {
            "name": "propertyId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/Fields"
          }
        ],
        "responses": {
          "200": {
            "description": "Property details",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Property"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      },
      "patch": {
        "operationId": "updateProperty",
        "summary": "Update a property",
        "tags": [
          "Properties"
        ],
        "parameters": [
          {
            "name": "propertyId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PropertyCreate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Property updated",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Property"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/v1/guests": {
      "get": {
        "operationId": "listGuests",
        "summary": "List guest compliance records",
        "description": "Retrieve compliance records for guest check-ins (document verification status).",
        "tags": [
          "Guests"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Offset"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "$ref": "#/components/parameters/Search"
          },
          {
            "$ref": "#/components/parameters/Fields"
          }
        ],
        "responses": {
          "200": {
            "description": "A paginated list of guest compliance records",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/PaginatedResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/Guest"
                          }
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/guests/{guestId}": {
      "get": {
        "operationId": "getGuest",
        "summary": "Get a guest compliance record",
        "tags": [
          "Guests"
        ],
        "parameters": [
          {
            "name": "guestId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/Fields"
          }
        ],
        "responses": {
          "200": {
            "description": "Guest compliance record",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Guest"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/v1/channels": {
      "get": {
        "operationId": "listChannels",
        "summary": "List channels",
        "description": "Retrieve channel connections (iCal feeds) for calendar sync.",
        "tags": [
          "Channels"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Offset"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "$ref": "#/components/parameters/Fields"
          },
          {
            "name": "status",
            "in": "query",
            "schema": {
              "$ref": "#/components/schemas/ChannelStatus"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A paginated list of channels",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/PaginatedResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/Channel"
                          }
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "post": {
        "operationId": "createChannel",
        "summary": "Create a channel (add iCal feed)",
        "tags": [
          "Channels"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ChannelCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Channel created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Channel"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      }
    },
    "/v1/channels/{channelId}": {
      "delete": {
        "operationId": "deleteChannel",
        "summary": "Remove a channel",
        "tags": [
          "Channels"
        ],
        "parameters": [
          {
            "name": "channelId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Channel deleted"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/v1/channels/{channelId}/sync": {
      "post": {
        "operationId": "syncChannel",
        "summary": "Trigger channel sync",
        "description": "Triggers a sync of the iCal feed for this channel.",
        "tags": [
          "Channels"
        ],
        "parameters": [
          {
            "name": "channelId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Sync triggered",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "success": {
                          "type": "boolean"
                        },
                        "message": {
                          "type": "string"
                        },
                        "channelId": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/webhooks/resend-inbound": {
      "post": {
        "operationId": "resendInbound",
        "summary": "Resend inbound email webhook",
        "description": "Receives inbound emails forwarded to `receipts@<workspace-slug>.frihet.io` via Resend.\nVerifies the Svix webhook signature, extracts PDF/image attachments, and queues\neach one in `receipt_queue/{workspaceUid}/items/{id}` for downstream OCR processing.\n\nThis endpoint is called by Resend's inbound routing — not by API consumers.\nSignature verification uses HMAC-SHA256 with the `RESEND_INBOUND_WEBHOOK_SECRET`\nenvironment variable. Header format follows Svix:\n`svix-id`, `svix-timestamp`, `svix-signature`.\n\n**Supported attachment MIME types:** `application/pdf`, `image/jpeg`, `image/png`,\n`image/webp`, `image/heic`, `image/heif`, `image/tiff`.\n",
        "tags": [
          "Webhooks"
        ],
        "security": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ResendInboundPayload"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Email processed. Returns count of queued attachments.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "queued": {
                      "type": "integer",
                      "description": "Number of attachments queued for OCR",
                      "example": 2
                    },
                    "skipped": {
                      "type": "integer",
                      "description": "Number of attachments skipped (unsupported type or no content)",
                      "example": 0
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid destination address format",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid Svix signature headers",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Workspace slug not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/v1/invoices/{invoiceId}/einvoice/export": {
      "post": {
        "operationId": "exportEInvoice",
        "summary": "Export e-invoice XML",
        "description": "Generate and return an e-invoice XML document for the invoice in one of 8 supported formats.\nOptionally sign with XAdES-EPES (Facturae only). Conforms to EN16931 semantic model.\n\nSupported formats: Facturae 3.2.2, XRechnung-CII, XRechnung-UBL, Factur-X (EN16931),\nFatturaPA 1.2.2, PEPPOL-BIS-3, UBL 2.1, CII D16B.\n\n**Trust Area: COMPLIANCE** — Requires owner role or API key with `einvoice:*` scope.\n",
        "tags": [
          "E-Invoicing"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/InvoiceId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "format"
                ],
                "additionalProperties": false,
                "properties": {
                  "format": {
                    "type": "string",
                    "enum": [
                      "Facturae",
                      "XRechnung-CII",
                      "XRechnung-UBL",
                      "Factur-X",
                      "FatturaPA",
                      "PEPPOL-BIS-3",
                      "UBL",
                      "CII"
                    ],
                    "description": "Target e-invoice format.\n- Facturae: Spanish B2G (Agencia Tributaria, FACe)\n- XRechnung-CII/UBL: German B2G (PEPPOL/ZRE/OZG-RE)\n- Factur-X: French standard (PDF/A-3 XML component)\n- FatturaPA: Italian SDI clearance\n- PEPPOL-BIS-3: Pan-European PEPPOL network\n- UBL/CII: Generic cross-border EU\n",
                    "example": "Facturae"
                  },
                  "signed": {
                    "type": "boolean",
                    "default": false,
                    "description": "Sign the XML with XAdES-EPES. Only supported for `format: Facturae`.\nRequires a valid PKCS#12 certificate uploaded in Settings > Compliance.\n"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "E-invoice XML generated successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "xml": {
                          "type": "string",
                          "description": "E-invoice XML content (UTF-8)"
                        },
                        "contentType": {
                          "type": "string",
                          "example": "application/xml"
                        },
                        "filename": {
                          "type": "string",
                          "example": "F2026-001_Facturae.xml"
                        },
                        "signed": {
                          "type": "boolean",
                          "description": "Whether the XML was signed with XAdES-EPES"
                        },
                        "format": {
                          "type": "string",
                          "example": "Facturae"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid format, signing not supported for this format, or body validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "422": {
            "description": "XML generation failed or certificate not configured",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/v1/invoices/{invoiceId}/face/submit": {
      "post": {
        "operationId": "submitFaceInvoice",
        "summary": "Submit invoice to FACe B2G portal",
        "description": "Submit a signed Facturae XML to Spain's FACe B2G portal (face.gob.es).\n\nPipeline: load invoice → generate Facturae XML → sign with XAdES-EPES → submit to FACe.\nResult is persisted to `invoices/{id}/face/submission` subdoc.\n\n**Idempotent**: if the invoice was already accepted (registered), returns the prior result\nwith `idempotent: true` — does not resubmit.\n\n**Trust Area: COMPLIANCE** — Requires owner role or API key with `einvoice:*` scope.\nRequires a PKCS#12 certificate for sandbox/production modes.\n",
        "tags": [
          "E-Invoicing"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/InvoiceId"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": false,
                "properties": {
                  "mode": {
                    "type": "string",
                    "enum": [
                      "mock",
                      "sandbox",
                      "production"
                    ],
                    "description": "FACe submission mode. Defaults to `ES_FACE_MODE` env var (default `mock`)."
                  },
                  "correo": {
                    "type": "string",
                    "format": "email",
                    "description": "Recipient notification email (required by FACe protocol). Defaults to fiscal billing email."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Invoice submitted to FACe",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "status": {
                          "type": "string",
                          "example": "submitted"
                        },
                        "numeroRegistro": {
                          "type": "string",
                          "description": "FACe registration number (never fabricated)",
                          "example": "REG/2026/000042"
                        },
                        "codigo": {
                          "type": "string",
                          "description": "FACe result code",
                          "example": "0"
                        },
                        "descripcion": {
                          "type": "string",
                          "description": "FACe result description",
                          "example": "Registrada"
                        },
                        "idempotent": {
                          "type": "boolean",
                          "description": "Present and true when returning a prior accepted submission"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "422": {
            "description": "FACe rejection, certificate missing, or XML generation error",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    },
                    "errors": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "codigo": {
                            "type": "string"
                          },
                          "descripcion": {
                            "type": "string"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/v1/invoices/{invoiceId}/face/status": {
      "get": {
        "operationId": "getFaceInvoiceStatus",
        "summary": "Get FACe submission status",
        "description": "Query the current tramitación status of a previously submitted FACe invoice.\nReads the saved `numeroRegistro` from Firestore and calls FACe `consultarFactura`.\n\n**Trust Area: COMPLIANCE** — Requires owner role or API key with `einvoice:*` scope.\n",
        "tags": [
          "E-Invoicing"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/InvoiceId"
          }
        ],
        "responses": {
          "200": {
            "description": "FACe tramitación status",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "numeroRegistro": {
                          "type": "string",
                          "description": "FACe registration number (read from Firestore, never fabricated)"
                        },
                        "estadoTramitacion": {
                          "type": "string",
                          "nullable": true,
                          "description": "FACe tramitación code (e.g. '1200' = Registrada, '1300' = En tramitación)"
                        },
                        "codigo": {
                          "type": "string",
                          "nullable": true
                        },
                        "descripcion": {
                          "type": "string",
                          "nullable": true
                        },
                        "motivo": {
                          "type": "string",
                          "nullable": true
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "No FACe submission found for this invoice",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Certificate required or FACe transport error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/v1/invoices/{invoiceId}/ticketbai/submit": {
      "post": {
        "operationId": "submitTicketBaiInvoice",
        "summary": "Submit invoice to TicketBAI (Bizkaia BATUZ)",
        "description": "Submit a signed TicketBAI XML to the Bizkaia BATUZ tax authority.\n\nPipeline: fetch BYOC cert → compute hash chain → build TicketBAI XML →\nsign with XAdES-BES → submit to BATUZ → generate QR code.\nResult persisted to `invoices/{id}/tbai/submission` subdoc.\n\n**Idempotent**: if the invoice was already accepted, returns the prior result\nwith `idempotent: true` — does not resubmit.\n\n**Trust Area: COMPLIANCE** — Requires owner role or API key with `einvoice:*` scope.\nRequires a TicketBAI BYOC certificate uploaded in Settings > Integrations > TicketBAI.\n",
        "tags": [
          "E-Invoicing"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/InvoiceId"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": false,
                "properties": {
                  "sandbox": {
                    "type": "boolean",
                    "description": "Override to sandbox mode (default from user integration config)."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "TicketBAI submission accepted",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "accepted": {
                          "type": "boolean",
                          "example": true
                        },
                        "csv": {
                          "type": "string",
                          "description": "CSV de verificación (never fabricated)",
                          "example": "TBAI-48-120226-000001-2H"
                        },
                        "tbaiIdentifier": {
                          "type": "string",
                          "description": "TicketBAI identifier string",
                          "example": "TBAI-B-000001"
                        },
                        "qrUrl": {
                          "type": "string",
                          "description": "QR code URL for invoice printing"
                        },
                        "idempotent": {
                          "type": "boolean",
                          "description": "Present and true when returning a prior accepted submission"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "422": {
            "description": "TicketBAI rejection, certificate missing, or chain broken",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    },
                    "errors": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/v1/invoices/{invoiceId}/ticketbai/status": {
      "get": {
        "operationId": "getTicketBaiInvoiceStatus",
        "summary": "Get TicketBAI submission status",
        "description": "Read the TicketBAI submission record for a previously submitted invoice.\nReturns accepted/rejected status, CSV, identifier, and QR URL from Firestore.\n\n**Trust Area: COMPLIANCE** — Requires owner role or API key with `einvoice:*` scope.\n",
        "tags": [
          "E-Invoicing"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/InvoiceId"
          }
        ],
        "responses": {
          "200": {
            "description": "TicketBAI submission status",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "accepted": {
                          "type": "boolean"
                        },
                        "csv": {
                          "type": "string",
                          "description": "CSV de verificación (read from Firestore, never fabricated)"
                        },
                        "tbaiIdentifier": {
                          "type": "string"
                        },
                        "estado": {
                          "type": "string",
                          "description": "accepted | rejected"
                        },
                        "qrUrl": {
                          "type": "string",
                          "nullable": true
                        },
                        "submittedAt": {
                          "type": "string",
                          "format": "date-time",
                          "nullable": true
                        },
                        "errors": {
                          "type": "array",
                          "nullable": true,
                          "items": {
                            "type": "string"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "No TicketBAI submission found for this invoice",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/v1/kitchen/tickets": {
      "get": {
        "operationId": "listKitchenTickets",
        "summary": "List tickets",
        "tags": [
          "Kitchen"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Offset"
          },
          {
            "$ref": "#/components/parameters/Fields"
          }
        ],
        "responses": {
          "200": {
            "description": "Paginated list of tickets",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PaginatedResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "post": {
        "operationId": "createKitchenTickets",
        "summary": "Create tickets",
        "tags": [
          "Kitchen"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Tickets created"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/kitchen/tickets/{id}": {
      "get": {
        "operationId": "getKitchenTickets",
        "summary": "Get tickets by ID",
        "tags": [
          "Kitchen"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Tickets details"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "patch": {
        "operationId": "updateKitchenTickets",
        "summary": "Update tickets",
        "tags": [
          "Kitchen"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Tickets updated"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "delete": {
        "operationId": "deleteKitchenTickets",
        "summary": "Delete tickets",
        "tags": [
          "Kitchen"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "responses": {
          "204": {
            "description": "Tickets deleted"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/kitchen/ticketItems": {
      "get": {
        "operationId": "listKitchenTicketItems",
        "summary": "List ticketItems",
        "tags": [
          "Kitchen"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Offset"
          },
          {
            "$ref": "#/components/parameters/Fields"
          }
        ],
        "responses": {
          "200": {
            "description": "Paginated list of ticketItems",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PaginatedResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "post": {
        "operationId": "createKitchenTicketItems",
        "summary": "Create ticketItems",
        "tags": [
          "Kitchen"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "TicketItems created"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/kitchen/ticketItems/{id}": {
      "get": {
        "operationId": "getKitchenTicketItems",
        "summary": "Get ticketItems by ID",
        "tags": [
          "Kitchen"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "TicketItems details"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "patch": {
        "operationId": "updateKitchenTicketItems",
        "summary": "Update ticketItems",
        "tags": [
          "Kitchen"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "TicketItems updated"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "delete": {
        "operationId": "deleteKitchenTicketItems",
        "summary": "Delete ticketItems",
        "tags": [
          "Kitchen"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "responses": {
          "204": {
            "description": "TicketItems deleted"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/kitchen/menuItems": {
      "get": {
        "operationId": "listKitchenMenuItems",
        "summary": "List menuItems",
        "tags": [
          "Kitchen"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Offset"
          },
          {
            "$ref": "#/components/parameters/Fields"
          }
        ],
        "responses": {
          "200": {
            "description": "Paginated list of menuItems",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PaginatedResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "post": {
        "operationId": "createKitchenMenuItems",
        "summary": "Create menuItems",
        "tags": [
          "Kitchen"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "MenuItems created"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/kitchen/menuItems/{id}": {
      "get": {
        "operationId": "getKitchenMenuItems",
        "summary": "Get menuItems by ID",
        "tags": [
          "Kitchen"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "MenuItems details"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "patch": {
        "operationId": "updateKitchenMenuItems",
        "summary": "Update menuItems",
        "tags": [
          "Kitchen"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "MenuItems updated"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "delete": {
        "operationId": "deleteKitchenMenuItems",
        "summary": "Delete menuItems",
        "tags": [
          "Kitchen"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "responses": {
          "204": {
            "description": "MenuItems deleted"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/kitchen/stations": {
      "get": {
        "operationId": "listKitchenStations",
        "summary": "List stations",
        "tags": [
          "Kitchen"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Offset"
          },
          {
            "$ref": "#/components/parameters/Fields"
          }
        ],
        "responses": {
          "200": {
            "description": "Paginated list of stations",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PaginatedResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "post": {
        "operationId": "createKitchenStations",
        "summary": "Create stations",
        "tags": [
          "Kitchen"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Stations created"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/kitchen/stations/{id}": {
      "get": {
        "operationId": "getKitchenStations",
        "summary": "Get stations by ID",
        "tags": [
          "Kitchen"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Stations details"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "patch": {
        "operationId": "updateKitchenStations",
        "summary": "Update stations",
        "tags": [
          "Kitchen"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Stations updated"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "delete": {
        "operationId": "deleteKitchenStations",
        "summary": "Delete stations",
        "tags": [
          "Kitchen"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "responses": {
          "204": {
            "description": "Stations deleted"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/pos/sales": {
      "get": {
        "operationId": "listPosSales",
        "summary": "List sales",
        "tags": [
          "Pos"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Offset"
          },
          {
            "$ref": "#/components/parameters/Fields"
          }
        ],
        "responses": {
          "200": {
            "description": "Paginated list of sales",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PaginatedResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "post": {
        "operationId": "createPosSales",
        "summary": "Create sales",
        "tags": [
          "Pos"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Sales created"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/pos/sales/{id}": {
      "get": {
        "operationId": "getPosSales",
        "summary": "Get sales by ID",
        "tags": [
          "Pos"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Sales details"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "patch": {
        "operationId": "updatePosSales",
        "summary": "Update sales",
        "tags": [
          "Pos"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Sales updated"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "delete": {
        "operationId": "deletePosSales",
        "summary": "Delete sales",
        "tags": [
          "Pos"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "responses": {
          "204": {
            "description": "Sales deleted"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/pos/products": {
      "get": {
        "operationId": "listPosProducts",
        "summary": "List products",
        "tags": [
          "Pos"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Offset"
          },
          {
            "$ref": "#/components/parameters/Fields"
          }
        ],
        "responses": {
          "200": {
            "description": "Paginated list of products",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PaginatedResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "post": {
        "operationId": "createPosProducts",
        "summary": "Create products",
        "tags": [
          "Pos"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Products created"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/pos/products/{id}": {
      "get": {
        "operationId": "getPosProducts",
        "summary": "Get products by ID",
        "tags": [
          "Pos"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Products details"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "patch": {
        "operationId": "updatePosProducts",
        "summary": "Update products",
        "tags": [
          "Pos"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Products updated"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "delete": {
        "operationId": "deletePosProducts",
        "summary": "Delete products",
        "tags": [
          "Pos"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "responses": {
          "204": {
            "description": "Products deleted"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/pos/terminals": {
      "get": {
        "operationId": "listPosTerminals",
        "summary": "List terminals",
        "tags": [
          "Pos"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Offset"
          },
          {
            "$ref": "#/components/parameters/Fields"
          }
        ],
        "responses": {
          "200": {
            "description": "Paginated list of terminals",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PaginatedResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "post": {
        "operationId": "createPosTerminals",
        "summary": "Create terminals",
        "tags": [
          "Pos"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Terminals created"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/pos/terminals/{id}": {
      "get": {
        "operationId": "getPosTerminals",
        "summary": "Get terminals by ID",
        "tags": [
          "Pos"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Terminals details"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "patch": {
        "operationId": "updatePosTerminals",
        "summary": "Update terminals",
        "tags": [
          "Pos"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Terminals updated"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "delete": {
        "operationId": "deletePosTerminals",
        "summary": "Delete terminals",
        "tags": [
          "Pos"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "responses": {
          "204": {
            "description": "Terminals deleted"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/pos/cash_sessions": {
      "get": {
        "operationId": "listPosCashSessions",
        "summary": "List cash sessions",
        "tags": [
          "Pos"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Offset"
          },
          {
            "$ref": "#/components/parameters/Fields"
          }
        ],
        "responses": {
          "200": {
            "description": "Paginated list of cash sessions",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PaginatedResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "post": {
        "operationId": "createPosCashSessions",
        "summary": "Create cash sessions",
        "tags": [
          "Pos"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Cash sessions created"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/pos/cash_sessions/{id}": {
      "get": {
        "operationId": "getPosCashSessions",
        "summary": "Get cash sessions by ID",
        "tags": [
          "Pos"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Cash sessions details"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "patch": {
        "operationId": "updatePosCashSessions",
        "summary": "Update cash sessions",
        "tags": [
          "Pos"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Cash sessions updated"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "delete": {
        "operationId": "deletePosCashSessions",
        "summary": "Delete cash sessions",
        "tags": [
          "Pos"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "responses": {
          "204": {
            "description": "Cash sessions deleted"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/stay/properties": {
      "get": {
        "operationId": "listStayProperties",
        "summary": "List properties",
        "tags": [
          "Stay"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Offset"
          },
          {
            "$ref": "#/components/parameters/Fields"
          }
        ],
        "responses": {
          "200": {
            "description": "Paginated list of properties",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PaginatedResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "post": {
        "operationId": "createStayProperties",
        "summary": "Create properties",
        "tags": [
          "Stay"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Properties created"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/stay/properties/{id}": {
      "get": {
        "operationId": "getStayProperties",
        "summary": "Get properties by ID",
        "tags": [
          "Stay"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Properties details"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "patch": {
        "operationId": "updateStayProperties",
        "summary": "Update properties",
        "tags": [
          "Stay"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Properties updated"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "delete": {
        "operationId": "deleteStayProperties",
        "summary": "Delete properties",
        "tags": [
          "Stay"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "responses": {
          "204": {
            "description": "Properties deleted"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/stay/reservations": {
      "get": {
        "operationId": "listStayReservations",
        "summary": "List reservations",
        "tags": [
          "Stay"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Offset"
          },
          {
            "$ref": "#/components/parameters/Fields"
          }
        ],
        "responses": {
          "200": {
            "description": "Paginated list of reservations",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PaginatedResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "post": {
        "operationId": "createStayReservations",
        "summary": "Create reservations",
        "tags": [
          "Stay"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Reservations created"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/stay/reservations/{id}": {
      "get": {
        "operationId": "getStayReservations",
        "summary": "Get reservations by ID",
        "tags": [
          "Stay"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Reservations details"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "patch": {
        "operationId": "updateStayReservations",
        "summary": "Update reservations",
        "tags": [
          "Stay"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Reservations updated"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "delete": {
        "operationId": "deleteStayReservations",
        "summary": "Delete reservations",
        "tags": [
          "Stay"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "responses": {
          "204": {
            "description": "Reservations deleted"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/stay/expenses": {
      "get": {
        "operationId": "listStayExpenses",
        "summary": "List expenses",
        "tags": [
          "Stay"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Offset"
          },
          {
            "$ref": "#/components/parameters/Fields"
          }
        ],
        "responses": {
          "200": {
            "description": "Paginated list of expenses",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PaginatedResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "post": {
        "operationId": "createStayExpenses",
        "summary": "Create expenses",
        "tags": [
          "Stay"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Expenses created"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/stay/expenses/{id}": {
      "get": {
        "operationId": "getStayExpenses",
        "summary": "Get expenses by ID",
        "tags": [
          "Stay"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Expenses details"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "patch": {
        "operationId": "updateStayExpenses",
        "summary": "Update expenses",
        "tags": [
          "Stay"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Expenses updated"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "delete": {
        "operationId": "deleteStayExpenses",
        "summary": "Delete expenses",
        "tags": [
          "Stay"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "responses": {
          "204": {
            "description": "Expenses deleted"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/stay/cleaning_tasks": {
      "get": {
        "operationId": "listStayCleaningTasks",
        "summary": "List cleaning tasks",
        "tags": [
          "Stay"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Offset"
          },
          {
            "$ref": "#/components/parameters/Fields"
          }
        ],
        "responses": {
          "200": {
            "description": "Paginated list of cleaning tasks",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PaginatedResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "post": {
        "operationId": "createStayCleaningTasks",
        "summary": "Create cleaning tasks",
        "tags": [
          "Stay"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Cleaning tasks created"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/stay/cleaning_tasks/{id}": {
      "get": {
        "operationId": "getStayCleaningTasks",
        "summary": "Get cleaning tasks by ID",
        "tags": [
          "Stay"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Cleaning tasks details"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "patch": {
        "operationId": "updateStayCleaningTasks",
        "summary": "Update cleaning tasks",
        "tags": [
          "Stay"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Cleaning tasks updated"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "delete": {
        "operationId": "deleteStayCleaningTasks",
        "summary": "Delete cleaning tasks",
        "tags": [
          "Stay"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "responses": {
          "204": {
            "description": "Cleaning tasks deleted"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/stay/settlements": {
      "get": {
        "operationId": "listStaySettlements",
        "summary": "List settlements",
        "tags": [
          "Stay"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Offset"
          },
          {
            "$ref": "#/components/parameters/Fields"
          }
        ],
        "responses": {
          "200": {
            "description": "Paginated list of settlements",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PaginatedResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "post": {
        "operationId": "createStaySettlements",
        "summary": "Create settlements",
        "tags": [
          "Stay"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Settlements created"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/stay/settlements/{id}": {
      "get": {
        "operationId": "getStaySettlements",
        "summary": "Get settlements by ID",
        "tags": [
          "Stay"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Settlements details"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "patch": {
        "operationId": "updateStaySettlements",
        "summary": "Update settlements",
        "tags": [
          "Stay"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Settlements updated"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "delete": {
        "operationId": "deleteStaySettlements",
        "summary": "Delete settlements",
        "tags": [
          "Stay"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "responses": {
          "204": {
            "description": "Settlements deleted"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/stay/compliance": {
      "get": {
        "operationId": "listStayCompliance",
        "summary": "List compliance",
        "tags": [
          "Stay"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Offset"
          },
          {
            "$ref": "#/components/parameters/Fields"
          }
        ],
        "responses": {
          "200": {
            "description": "Paginated list of compliance",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PaginatedResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "post": {
        "operationId": "createStayCompliance",
        "summary": "Create compliance",
        "tags": [
          "Stay"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Compliance created"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/stay/compliance/{id}": {
      "get": {
        "operationId": "getStayCompliance",
        "summary": "Get compliance by ID",
        "tags": [
          "Stay"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Compliance details"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "patch": {
        "operationId": "updateStayCompliance",
        "summary": "Update compliance",
        "tags": [
          "Stay"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Compliance updated"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "delete": {
        "operationId": "deleteStayCompliance",
        "summary": "Delete compliance",
        "tags": [
          "Stay"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "responses": {
          "204": {
            "description": "Compliance deleted"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    }
  },
  "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": {
      "ResendInboundPayload": {
        "type": "object",
        "description": "Payload sent by Resend for inbound email routing.",
        "properties": {
          "to": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Recipient email addresses. Should include receipts@<slug>.frihet.io",
            "example": [
              "receipts@myworkspace.frihet.io"
            ]
          },
          "from": {
            "type": "string",
            "description": "Sender email address",
            "example": "vendor@example.com"
          },
          "subject": {
            "type": "string",
            "description": "Email subject line",
            "example": "Invoice #1234 from Acme Corp"
          },
          "text": {
            "type": "string",
            "description": "Plain text body"
          },
          "html": {
            "type": "string",
            "description": "HTML body"
          },
          "attachments": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "filename": {
                  "type": "string",
                  "description": "Original filename of the attachment",
                  "example": "invoice.pdf"
                },
                "content": {
                  "type": "string",
                  "description": "Base64-encoded file content"
                },
                "content_type": {
                  "type": "string",
                  "description": "MIME type of the attachment",
                  "example": "application/pdf"
                }
              }
            }
          }
        }
      },
      "ReceiptQueueItem": {
        "type": "object",
        "description": "A receipt or invoice queued for OCR processing from an inbound email.",
        "properties": {
          "id": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "queued",
              "processing",
              "done",
              "failed"
            ]
          },
          "sourceEmail": {
            "type": "string",
            "description": "Email address that sent the attachment"
          },
          "originalFilename": {
            "type": "string"
          },
          "mimeType": {
            "type": "string"
          },
          "subject": {
            "type": "string"
          },
          "workspaceUid": {
            "type": "string"
          },
          "receivedAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          },
          "storagePath": {
            "type": "string",
            "description": "Firebase Storage path after upload (available when status=done)",
            "nullable": true
          },
          "expenseId": {
            "type": "string",
            "description": "Created expense ID after OCR completes (available when status=done)",
            "nullable": true
          },
          "error": {
            "type": "string",
            "description": "Error message when status=failed",
            "nullable": true
          }
        }
      },
      "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": {
          "clientId": {
            "type": "string",
            "description": "Client document ID. When provided, the API auto-snapshots\n`clientTaxId`, `clientAddress`, `clientLocation`, `clientName`,\nand `clientEmail` from the referenced client at create time\n(immutable post-create — VeriFactu RD 1007/2023). Caller-provided\nvalues for those fields override the snapshot.\n",
            "example": "client_abc123"
          },
          "clientName": {
            "type": "string",
            "description": "Client name (snapshot field — frozen at create)",
            "example": "Acme Corp"
          },
          "clientTaxId": {
            "type": "string",
            "description": "Client tax ID / NIF / VAT (snapshot field — frozen at create).\nAuto-populated from clientId reference if not provided.\n",
            "example": "B12345678"
          },
          "clientAddress": {
            "type": "string",
            "description": "Client billing address — single-line or structured. Snapshot\nfield, frozen at create.\n",
            "example": "Calle Mayor 12, 38001 Santa Cruz de Tenerife"
          },
          "clientLocation": {
            "type": "string",
            "enum": [
              "peninsula",
              "canarias",
              "ceuta_melilla",
              "eu",
              "world"
            ],
            "description": "Fiscal zone — drives tax label rendering on PDF + tax math\n(IVA/IGIC/IPSI/Reverse charge/Exempt). Snapshot field, frozen\nat create. Auto-populated from clientId reference if absent.\n",
            "example": "canarias"
          },
          "clientEmail": {
            "type": "string",
            "format": "email",
            "description": "Client email (snapshot field — frozen at create)."
          },
          "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. Combined with `clientLocation` to produce\nthe label (IGIC for canarias, IPSI for ceuta_melilla, etc.).\n",
            "example": 21
          },
          "irpfRate": {
            "type": "number",
            "minimum": 0,
            "maximum": 100,
            "description": "IRPF withholding rate percentage (Spain).",
            "example": 15
          },
          "discountRate": {
            "type": "number",
            "minimum": 0,
            "maximum": 100,
            "description": "Invoice-level discount percentage.",
            "example": 10
          },
          "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"
          },
          "truncated": {
            "type": "boolean",
            "description": "Only present (and `true`) when the underlying search query\nsaturated the internal 500-document cap. `total` therefore reports\nthe size of the first 500 matches, not the full match count.\nNarrow the search query (taxId / fiscal id, exact email) to ensure\nyou see every result.\n",
            "example": true
          }
        }
      },
      "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. Write-only: echoed once in the create response, never returned by read endpoints (see hasSecret).",
            "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",
            "description": "HMAC secret for verifying webhook signatures. Write-only: never returned by read endpoints (see hasSecret).",
            "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"
              },
              "hasSecret": {
                "type": "boolean",
                "description": "True if an HMAC secret is configured. The secret value itself is never returned by read endpoints."
              }
            }
          },
          {
            "$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"
              }
            }
          }
        }
      },
      "ReservationStatus": {
        "type": "string",
        "enum": [
          "Pending",
          "Confirmed",
          "Checked In",
          "Checked Out",
          "Cancelled"
        ]
      },
      "PropertyStatus": {
        "type": "string",
        "enum": [
          "Active",
          "Maintenance",
          "Inactive"
        ]
      },
      "ChannelStatus": {
        "type": "string",
        "enum": [
          "active",
          "paused",
          "error"
        ]
      },
      "ReservationCreate": {
        "type": "object",
        "required": [
          "guestName",
          "propertyId",
          "checkIn",
          "checkOut"
        ],
        "properties": {
          "guestName": {
            "type": "string",
            "description": "Guest full name",
            "example": "Maria Lopez"
          },
          "guestEmail": {
            "type": "string",
            "format": "email",
            "example": "maria@example.com"
          },
          "propertyId": {
            "type": "string",
            "description": "ID of the property"
          },
          "checkIn": {
            "type": "string",
            "format": "date",
            "description": "Check-in date (ISO 8601)",
            "example": "2026-05-01"
          },
          "checkOut": {
            "type": "string",
            "format": "date",
            "description": "Check-out date (ISO 8601)",
            "example": "2026-05-05"
          },
          "status": {
            "$ref": "#/components/schemas/ReservationStatus"
          },
          "amount": {
            "type": "number",
            "description": "Total amount in EUR",
            "example": 450
          },
          "channel": {
            "type": "string",
            "enum": [
              "Direct",
              "Airbnb",
              "Booking.com",
              "Vrbo"
            ],
            "example": "Airbnb"
          },
          "confirmationCode": {
            "type": "string",
            "example": "HM4X7K"
          },
          "complianceStatus": {
            "type": "string",
            "enum": [
              "Not Started",
              "In Progress",
              "Completed",
              "Failed"
            ]
          },
          "nights": {
            "type": "integer",
            "minimum": 0
          },
          "notes": {
            "type": "string"
          }
        }
      },
      "Reservation": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "guestName": {
            "type": "string"
          },
          "guestEmail": {
            "type": "string",
            "nullable": true
          },
          "propertyId": {
            "type": "string"
          },
          "checkIn": {
            "type": "string",
            "format": "date-time"
          },
          "checkOut": {
            "type": "string",
            "format": "date-time"
          },
          "status": {
            "$ref": "#/components/schemas/ReservationStatus"
          },
          "amount": {
            "type": "number"
          },
          "channel": {
            "type": "string"
          },
          "confirmationCode": {
            "type": "string",
            "nullable": true
          },
          "complianceStatus": {
            "type": "string"
          },
          "nights": {
            "type": "integer"
          },
          "notes": {
            "type": "string",
            "nullable": true
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "PropertyCreate": {
        "type": "object",
        "required": [
          "name"
        ],
        "properties": {
          "name": {
            "type": "string",
            "description": "Property name",
            "example": "Sunset Villa"
          },
          "type": {
            "type": "string",
            "enum": [
              "Apartment",
              "Villa",
              "Studio",
              "House",
              "Room"
            ],
            "example": "Villa"
          },
          "address": {
            "type": "string",
            "example": "Calle Sol 12, Santa Cruz"
          },
          "status": {
            "$ref": "#/components/schemas/PropertyStatus"
          },
          "ownerName": {
            "type": "string",
            "example": "Carlos Martinez"
          },
          "ownerEmail": {
            "type": "string",
            "format": "email"
          },
          "commissionRate": {
            "type": "number",
            "minimum": 0,
            "maximum": 100,
            "description": "Commission percentage (0-100)",
            "example": 15
          },
          "licenseNumber": {
            "type": "string",
            "description": "Tourism license number",
            "example": "VV-38-001234"
          },
          "maxGuests": {
            "type": "integer",
            "minimum": 1,
            "example": 6
          }
        }
      },
      "Property": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "type": {
            "type": "string"
          },
          "address": {
            "type": "string"
          },
          "status": {
            "$ref": "#/components/schemas/PropertyStatus"
          },
          "ownerName": {
            "type": "string"
          },
          "ownerEmail": {
            "type": "string",
            "nullable": true
          },
          "commissionRate": {
            "type": "number"
          },
          "licenseNumber": {
            "type": "string",
            "nullable": true
          },
          "maxGuests": {
            "type": "integer"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "Guest": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "guestName": {
            "type": "string"
          },
          "documentType": {
            "type": "string",
            "nullable": true,
            "enum": [
              "DNI",
              "Passport",
              "NIE"
            ]
          },
          "documentNumber": {
            "type": "string",
            "nullable": true,
            "description": "Redacted for privacy"
          },
          "nationality": {
            "type": "string",
            "nullable": true
          },
          "reservationId": {
            "type": "string"
          },
          "documentVerified": {
            "type": "boolean"
          },
          "signatureCaptured": {
            "type": "boolean"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "ChannelCreate": {
        "type": "object",
        "required": [
          "propertyId",
          "name"
        ],
        "properties": {
          "propertyId": {
            "type": "string",
            "description": "ID of the property this channel belongs to"
          },
          "name": {
            "type": "string",
            "description": "Channel name (e.g., \"Airbnb\", \"Booking.com\")",
            "example": "Airbnb"
          },
          "type": {
            "type": "string",
            "enum": [
              "ical_import",
              "ical_export",
              "api"
            ],
            "default": "ical_import"
          },
          "feedUrl": {
            "type": "string",
            "format": "uri",
            "description": "iCal feed URL for import",
            "example": "https://www.airbnb.com/calendar/ical/12345.ics"
          },
          "status": {
            "$ref": "#/components/schemas/ChannelStatus"
          }
        }
      },
      "Channel": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "propertyId": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "type": {
            "type": "string"
          },
          "feedUrl": {
            "type": "string",
            "nullable": true
          },
          "status": {
            "type": "string"
          },
          "lastSync": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "lastSyncEvents": {
            "type": "integer"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      }
    },
    "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"
              }
            }
          }
        }
      }
    }
  }
}