{
  "openapi": "3.0.0",
  "paths": {
    "/.well-known/portal-sso/{slug}/jwks.json": {
      "get": {
        "description": "The `jwks_uri` a partner registers at their OpenID Provider so it can verify our `private_key_jwt` client assertions. Returns an RFC 7517 JWK Set of the tenant's current signing key plus — during a rotation grace window — the immediately-previous key, each keyed by `kid`. Public key material only; no authentication required. An unknown slug or a tenant with no signing key returns an empty key set (never a 404). Cached for 5 minutes; OPs re-fetch on an unknown `kid`.",
        "operationId": "PublicPortalSsoJwksController_getJwks",
        "parameters": [
          {
            "name": "slug",
            "required": true,
            "in": "path",
            "description": "The tenant's public portal slug.",
            "schema": {
              "example": "acme",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicPortalSsoJwks"
                }
              }
            }
          }
        },
        "summary": "Published RP signing keys (JWKS) for a tenant's private_key_jwt SSO",
        "tags": [
          "Portal SSO"
        ]
      }
    },
    "/v1/accounts": {
      "get": {
        "description": "\nRetrieves your company's chart of accounts, sorted by `publicAccountId`\nand then by `accountNumber`. Pass an account's `id` as `accountId` when\ncreating journal entries or draft journal entries, or to filter the\njournal-entry list.\n\nResults are cached for 5 seconds.\n\n## Required Scope\n\n- `accounts-read`\n    ",
        "operationId": "PublicAccountsController_getAccounts_v1",
        "parameters": [],
        "responses": {
          "200": {
            "description": "List of accounts for the company",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/AccountResponse"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 400
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Bad Request"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 401
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions - API key missing required scopes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 403
                    },
                    "code": {
                      "type": "string",
                      "example": "INSUFFICIENT_PERMISSIONS"
                    },
                    "details": {
                      "type": "object",
                      "properties": {
                        "reason": {
                          "type": "string",
                          "example": "api_key_missing_required_scope"
                        },
                        "requiredScopes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "example": [
                            "usage:write"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "OAuth2ClientCredentials": []
          }
        ],
        "summary": "List accounts",
        "tags": [
          "Accounts"
        ]
      }
    },
    "/v1/api-key": {
      "get": {
        "description": "\nReturns metadata about the API key used to authenticate the request: its\nexpiry, IP whitelist, granted scopes, and rate limit tiers. Useful for\nverifying what a key can do before calling other endpoints.\n\nKey details are cached for 5 seconds. The endpoint requires API-key\nauthentication specifically — calling it with an OAuth access token responds\n`403` with code `INSUFFICIENT_PERMISSIONS` and reason\n`endpoint_requires_api_key_auth`.\n\n## Required Scope\n\nNo specific scope is required — any valid API key for your company can call\nthis endpoint.\n    ",
        "operationId": "PublicApiKeyController_getApiKeyInfo_v1",
        "parameters": [],
        "responses": {
          "200": {
            "description": "API key information",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiKeyInfoResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 400
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Bad Request"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 401
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions - API key missing required scopes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 403
                    },
                    "code": {
                      "type": "string",
                      "example": "INSUFFICIENT_PERMISSIONS"
                    },
                    "details": {
                      "type": "object",
                      "properties": {
                        "reason": {
                          "type": "string",
                          "example": "api_key_missing_required_scope"
                        },
                        "requiredScopes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "example": [
                            "usage:write"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "OAuth2ClientCredentials": []
          }
        ],
        "summary": "Get current API key",
        "tags": [
          "API Key"
        ]
      }
    },
    "/v1/company": {
      "get": {
        "description": "\nRetrieves the master data of the company your API key belongs to.\n\nThe company is resolved from the API key itself — there is no company\nparameter, and a key can never read another company's data.\n\n## Use Cases\n\n- **Connectivity check**: The simplest authenticated call — verify your key\n  works and confirm which company it is bound to before doing anything else.\n- **Document headers**: Pull the legal name, VAT number, and address for\n  rendering your own documents or syncing into another system.\n- **Localization**: Use `preferredLanguage` and `countryCode` to localize\n  communication generated on behalf of the company.\n\n## Response Structure\n\n- **id**: Unique identifier for the company (UUID)\n- **name**: Legal/display company name\n- **email** / **billingEmail**: Primary and billing contact addresses\n- **vat**: VAT registration number (CVR in Denmark)\n- **address**, **city**, **postalCode**, **countryCode**: Registered address\n  (`countryCode` is ISO 3166-1 alpha-2, e.g. `DK`)\n- **phone**: Phone number\n- **preferredLanguage**: Language code used for company communication (e.g. `da`, `en`)\n- **contactPersonFirstName** / **contactPersonLastName**: Primary contact person\n\nFields without a value are returned as `null`.\n\n## Required Scope\n\n- `company-read`\n\n## Performance\n\nResults are cached for 5 seconds, so bursts of calls do not hit the database\non every request.\n\n## Example Response\n\n```json\n{\n  \"id\": \"550e8400-e29b-41d4-a716-446655440000\",\n  \"name\": \"Acme Corporation\",\n  \"email\": \"contact@acme.com\",\n  \"vat\": 12345678,\n  \"billingEmail\": \"billing@acme.com\",\n  \"address\": \"123 Main Street\",\n  \"city\": \"Copenhagen\",\n  \"postalCode\": \"2100\",\n  \"countryCode\": \"DK\",\n  \"phone\": \"+45 12 34 56 78\",\n  \"preferredLanguage\": \"da\",\n  \"contactPersonFirstName\": \"John\",\n  \"contactPersonLastName\": \"Doe\"\n}\n```\n    ",
        "operationId": "PublicCompanyController_getCompany_v1",
        "parameters": [],
        "responses": {
          "200": {
            "description": "Company information",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CompanyResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 400
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Bad Request"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 401
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions - API key missing required scopes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 403
                    },
                    "code": {
                      "type": "string",
                      "example": "INSUFFICIENT_PERMISSIONS"
                    },
                    "details": {
                      "type": "object",
                      "properties": {
                        "reason": {
                          "type": "string",
                          "example": "api_key_missing_required_scope"
                        },
                        "requiredScopes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "example": [
                            "usage:write"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "OAuth2ClientCredentials": []
          }
        ],
        "summary": "Get company details",
        "tags": [
          "Company"
        ]
      }
    },
    "/v1/credit-notes": {
      "post": {
        "description": "Creates a credit note. Pass `invoiceNumber` to credit an existing invoice; the referenced invoice is then marked credited.",
        "operationId": "PublicCreditNotesController_create_v1",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PublicCreateCreditNote"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Credit note created successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicCreditNote"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 400
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Bad Request"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 401
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions - API key missing required scopes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 403
                    },
                    "code": {
                      "type": "string",
                      "example": "INSUFFICIENT_PERMISSIONS"
                    },
                    "details": {
                      "type": "object",
                      "properties": {
                        "reason": {
                          "type": "string",
                          "example": "api_key_missing_required_scope"
                        },
                        "requiredScopes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "example": [
                            "usage:write"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "OAuth2ClientCredentials": []
          }
        ],
        "summary": "Create a credit note",
        "tags": [
          "Credit Notes"
        ]
      },
      "get": {
        "description": "Returns a paginated list of credit notes for your company, optionally filtered by status and customer.",
        "operationId": "PublicCreditNotesController_list_v1",
        "parameters": [
          {
            "name": "page",
            "required": false,
            "in": "query",
            "description": "Page number (1-indexed)",
            "schema": {
              "minimum": 1,
              "default": 1,
              "example": 1,
              "type": "number"
            }
          },
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "description": "Number of items per page",
            "schema": {
              "minimum": 1,
              "maximum": 100,
              "default": 25,
              "example": 25,
              "type": "number"
            }
          },
          {
            "name": "search",
            "required": false,
            "in": "query",
            "description": "Free-text search (credit note number, description)",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "status",
            "required": false,
            "in": "query",
            "description": "Filter credit notes by status",
            "schema": {
              "type": "string",
              "enum": [
                "draft",
                "scheduled",
                "sending",
                "sent"
              ]
            }
          },
          {
            "name": "customerId",
            "required": false,
            "in": "query",
            "description": "Filter credit notes for a specific customer",
            "schema": {
              "example": "0197A943-2325-7829-B835-B6C71A293065",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Paginated list of credit notes",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicListCreditNotesResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 400
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Bad Request"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 401
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions - API key missing required scopes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 403
                    },
                    "code": {
                      "type": "string",
                      "example": "INSUFFICIENT_PERMISSIONS"
                    },
                    "details": {
                      "type": "object",
                      "properties": {
                        "reason": {
                          "type": "string",
                          "example": "api_key_missing_required_scope"
                        },
                        "requiredScopes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "example": [
                            "usage:write"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "OAuth2ClientCredentials": []
          }
        ],
        "summary": "List credit notes",
        "tags": [
          "Credit Notes"
        ]
      }
    },
    "/v1/credit-notes/{id}": {
      "get": {
        "description": "\nRetrieves a single credit note by its unique identifier. Returns `404`\nwhen the credit note does not exist in your company. For the rendered\ndocument, use the PDF endpoint.\n\n## Required Scope\n\n- `invoices-read`\n    ",
        "operationId": "PublicCreditNotesController_getOne_v1",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "description": "Credit Note ID",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The credit note",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicCreditNote"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 400
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Bad Request"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 401
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions - API key missing required scopes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 403
                    },
                    "code": {
                      "type": "string",
                      "example": "INSUFFICIENT_PERMISSIONS"
                    },
                    "details": {
                      "type": "object",
                      "properties": {
                        "reason": {
                          "type": "string",
                          "example": "api_key_missing_required_scope"
                        },
                        "requiredScopes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "example": [
                            "usage:write"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "OAuth2ClientCredentials": []
          }
        ],
        "summary": "Get a credit note by ID",
        "tags": [
          "Credit Notes"
        ]
      }
    },
    "/v1/credit-notes/{id}/delivery-status": {
      "get": {
        "description": "Returns an aggregate send summary plus a per-attempt delivery log for the credit note.",
        "operationId": "PublicCreditNotesController_getDeliveryStatus_v1",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "description": "Credit Note ID",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Delivery status",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicDeliveryStatusResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 400
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Bad Request"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 401
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions - API key missing required scopes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 403
                    },
                    "code": {
                      "type": "string",
                      "example": "INSUFFICIENT_PERMISSIONS"
                    },
                    "details": {
                      "type": "object",
                      "properties": {
                        "reason": {
                          "type": "string",
                          "example": "api_key_missing_required_scope"
                        },
                        "requiredScopes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "example": [
                            "usage:write"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "OAuth2ClientCredentials": []
          }
        ],
        "summary": "Get the delivery status of a credit note",
        "tags": [
          "Credit Notes"
        ]
      }
    },
    "/v1/credit-notes/{id}/pdf": {
      "get": {
        "description": "Streams the rendered credit note PDF. Pass `draft=true` to render a draft watermark version (generated on the fly).",
        "operationId": "PublicCreditNotesController_downloadPdf_v1",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "description": "Credit Note ID",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "draft",
            "required": false,
            "in": "query",
            "description": "Render a draft watermark version",
            "schema": {
              "type": "boolean"
            }
          }
        ],
        "responses": {
          "400": {
            "description": "Bad Request",
            "content": {
              "application/pdf": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 400
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Bad Request"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/pdf": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 401
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions - API key missing required scopes",
            "content": {
              "application/pdf": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 403
                    },
                    "code": {
                      "type": "string",
                      "example": "INSUFFICIENT_PERMISSIONS"
                    },
                    "details": {
                      "type": "object",
                      "properties": {
                        "reason": {
                          "type": "string",
                          "example": "api_key_missing_required_scope"
                        },
                        "requiredScopes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "example": [
                            "usage:write"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "OAuth2ClientCredentials": []
          }
        ],
        "summary": "Download the credit note PDF",
        "tags": [
          "Credit Notes"
        ]
      }
    },
    "/v1/credit-notes/{id}/send": {
      "post": {
        "description": "Sends the credit note over the chosen delivery channel (Email, Sproom e-invoicing, or Manual).",
        "operationId": "PublicCreditNotesController_send_v1",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "description": "Credit Note ID",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PublicSendCreditNote"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Credit note send accepted",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicSendInvoiceResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 400
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Bad Request"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 401
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions - API key missing required scopes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 403
                    },
                    "code": {
                      "type": "string",
                      "example": "INSUFFICIENT_PERMISSIONS"
                    },
                    "details": {
                      "type": "object",
                      "properties": {
                        "reason": {
                          "type": "string",
                          "example": "api_key_missing_required_scope"
                        },
                        "requiredScopes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "example": [
                            "usage:write"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "OAuth2ClientCredentials": []
          }
        ],
        "summary": "Send a credit note to the customer",
        "tags": [
          "Credit Notes"
        ]
      }
    },
    "/v1/customers": {
      "get": {
        "description": "\nRetrieves all customers for your company, sorted by customer number.\n\nPass `?customerNumber=` for an exact-match lookup of a single customer by\nits human-readable number (useful when you only know the number shown on an\ninvoice, not the UUID).\n\nThe unfiltered list is cached for 5 seconds; filtered lookups always read\nfresh data, so a just-created or just-updated customer is immediately\nvisible via its customer number.\n\n## Required Scope\n\n- `customers-read`\n    ",
        "operationId": "PublicCustomersController_getCustomers_v1",
        "parameters": [
          {
            "name": "customerNumber",
            "required": false,
            "in": "query",
            "description": "Optional exact-match filter on customerNumber. Tenant scoping is enforced regardless of the filter.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "externalSystemId",
            "required": false,
            "in": "query",
            "description": "Optional exact-match filter on externalSystemId. The value is unique per company, so at most one customer can match.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "metadata",
            "required": false,
            "in": "query",
            "style": "deepObject",
            "explode": true,
            "schema": {
              "type": "object",
              "additionalProperties": {
                "type": "string"
              }
            },
            "description": "Exact-match metadata filters in the form metadata[key]=value. Multiple pairs combine with AND semantics — a record matches only if it carries every given key with exactly the given value. At most 10 pairs per request."
          }
        ],
        "responses": {
          "200": {
            "description": "List of customers for the company matching the given filters",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/CustomerResponse"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 400
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Bad Request"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 401
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions - API key missing required scopes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 403
                    },
                    "code": {
                      "type": "string",
                      "example": "INSUFFICIENT_PERMISSIONS"
                    },
                    "details": {
                      "type": "object",
                      "properties": {
                        "reason": {
                          "type": "string",
                          "example": "api_key_missing_required_scope"
                        },
                        "requiredScopes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "example": [
                            "usage:write"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "OAuth2ClientCredentials": []
          }
        ],
        "summary": "List customers",
        "tags": [
          "Customers"
        ]
      },
      "post": {
        "description": "\nCreates a customer in your company. The response contains the new `id` and\nthe auto-assigned `customerNumber` — fetch the full record via\n`GET /v1/customers/{customerId}` if you need it.\n\n- `customerType` defaults to `BUSINESS` when omitted.\n- `externalSystemId` lets you store your own system's identifier for\n  deduplication. It must be unique within your company — reusing one returns\n  `409 EXTERNAL_SYSTEM_ID_ALREADY_EXISTS`. Empty or whitespace-only values\n  are treated as unset.\n\n## Required Scope\n\n- `customers-write`\n    ",
        "operationId": "PublicCustomersController_createCustomer_v1",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateCustomerRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Customer created successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreateCustomerResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 400
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Bad Request"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 401
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions - API key missing required scopes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 403
                    },
                    "code": {
                      "type": "string",
                      "example": "INSUFFICIENT_PERMISSIONS"
                    },
                    "details": {
                      "type": "object",
                      "properties": {
                        "reason": {
                          "type": "string",
                          "example": "api_key_missing_required_scope"
                        },
                        "requiredScopes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "example": [
                            "usage:write"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "OAuth2ClientCredentials": []
          }
        ],
        "summary": "Create a customer",
        "tags": [
          "Customers"
        ]
      }
    },
    "/v1/customers/{customerId}": {
      "get": {
        "description": "\nRetrieves a customer by its unique identifier. Returns `404` when the\ncustomer does not exist (or belongs to another company).\n\n## Required Scope\n\n- `customers-read`\n    ",
        "operationId": "PublicCustomersController_getCustomer_v1",
        "parameters": [
          {
            "name": "customerId",
            "required": true,
            "in": "path",
            "description": "Customer ID",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Customer details",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CustomerResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 400
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Bad Request"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 401
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions - API key missing required scopes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 403
                    },
                    "code": {
                      "type": "string",
                      "example": "INSUFFICIENT_PERMISSIONS"
                    },
                    "details": {
                      "type": "object",
                      "properties": {
                        "reason": {
                          "type": "string",
                          "example": "api_key_missing_required_scope"
                        },
                        "requiredScopes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "example": [
                            "usage:write"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "OAuth2ClientCredentials": []
          }
        ],
        "summary": "Get a single customer",
        "tags": [
          "Customers"
        ]
      },
      "patch": {
        "description": "\nPartially updates a customer — only the fields you send are changed; send\n`null` to clear a clearable field. Returns the full updated customer.\n\n`externalSystemId` follows the same rules as on create: unique within your\ncompany (`409 EXTERNAL_SYSTEM_ID_ALREADY_EXISTS` on conflict), empty values\ntreated as unset.\n\n## Required Scope\n\n- `customers-write`\n    ",
        "operationId": "PublicCustomersController_updateCustomer_v1",
        "parameters": [
          {
            "name": "customerId",
            "required": true,
            "in": "path",
            "description": "Customer ID",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateCustomerRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Customer updated successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CustomerResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 400
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Bad Request"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 401
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions - API key missing required scopes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 403
                    },
                    "code": {
                      "type": "string",
                      "example": "INSUFFICIENT_PERMISSIONS"
                    },
                    "details": {
                      "type": "object",
                      "properties": {
                        "reason": {
                          "type": "string",
                          "example": "api_key_missing_required_scope"
                        },
                        "requiredScopes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "example": [
                            "usage:write"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "OAuth2ClientCredentials": []
          }
        ],
        "summary": "Update a customer",
        "tags": [
          "Customers"
        ]
      }
    },
    "/v1/customers/{customerId}/contacts": {
      "get": {
        "description": "\nRetrieves the contact persons registered on a customer. The customer's\ndefault contact is returned first, then the rest alphabetically.\n\n## Required Scope\n\n- `customers-read`\n    ",
        "operationId": "PublicCustomersController_getCustomerContacts_v1",
        "parameters": [
          {
            "name": "customerId",
            "required": true,
            "in": "path",
            "description": "Customer ID",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "List of contacts for a customer",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/CustomerContactResponse"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 400
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Bad Request"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 401
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions - API key missing required scopes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 403
                    },
                    "code": {
                      "type": "string",
                      "example": "INSUFFICIENT_PERMISSIONS"
                    },
                    "details": {
                      "type": "object",
                      "properties": {
                        "reason": {
                          "type": "string",
                          "example": "api_key_missing_required_scope"
                        },
                        "requiredScopes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "example": [
                            "usage:write"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "OAuth2ClientCredentials": []
          }
        ],
        "summary": "List a customer's contacts",
        "tags": [
          "Customers"
        ]
      }
    },
    "/v1/customers/{customerId}/departments": {
      "get": {
        "description": "\nRetrieves the departments of a customer — sub-units with their own address,\nEAN number (for e-invoicing), and purchase-order number, typically used to\nroute invoices within larger organizations.\n\nThe default department is returned first, then the rest alphabetically.\n\n## Required Scope\n\n- `customers-read`\n    ",
        "operationId": "PublicCustomersController_getCustomerDepartments_v1",
        "parameters": [
          {
            "name": "customerId",
            "required": true,
            "in": "path",
            "description": "Customer ID",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "List of departments for a customer",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/CustomerDepartmentResponse"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 400
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Bad Request"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 401
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions - API key missing required scopes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 403
                    },
                    "code": {
                      "type": "string",
                      "example": "INSUFFICIENT_PERMISSIONS"
                    },
                    "details": {
                      "type": "object",
                      "properties": {
                        "reason": {
                          "type": "string",
                          "example": "api_key_missing_required_scope"
                        },
                        "requiredScopes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "example": [
                            "usage:write"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "OAuth2ClientCredentials": []
          }
        ],
        "summary": "List a customer's departments",
        "tags": [
          "Customers"
        ]
      }
    },
    "/v1/customers/{customerId}/payment-methods": {
      "get": {
        "description": "\nRetrieves the payment methods saved on a customer (e.g. cards stored via a\ncard-save link). Pass `?provider=` to narrow to a single payment provider.\n\n## Required Scope\n\n- `payment-methods-read`\n    ",
        "operationId": "PublicPaymentMethodsController_list_v1",
        "parameters": [
          {
            "name": "customerId",
            "required": true,
            "in": "path",
            "description": "The customer ID",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "provider",
            "required": false,
            "in": "query",
            "description": "Filter by payment provider",
            "schema": {
              "enum": [
                "ONPAY",
                "STRIPE"
              ],
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "List of payment methods",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/PaymentMethodResponse"
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "OAuth2ClientCredentials": []
          }
        ],
        "summary": "List saved payment methods for a customer",
        "tags": [
          "Payment Methods"
        ]
      }
    },
    "/v1/customers/{customerId}/payment-methods/{paymentMethodId}/apply-to-subscriptions": {
      "post": {
        "description": "Assigns the specified payment method to all active, trial, and scheduled subscriptions. Overwrites existing card assignments. Excludes PARENT_PAYS subscriptions.",
        "operationId": "PublicPaymentMethodsController_applyToSubscriptions_v1",
        "parameters": [
          {
            "name": "customerId",
            "required": true,
            "in": "path",
            "description": "The customer ID",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "paymentMethodId",
            "required": true,
            "in": "path",
            "description": "The payment method ID to apply",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ApplyPaymentMethodToSubscriptionsDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Card applied to subscriptions"
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "OAuth2ClientCredentials": []
          }
        ],
        "summary": "Apply a payment method to all active subscriptions for a customer",
        "tags": [
          "Payment Methods"
        ]
      }
    },
    "/v1/customers/{customerId}/payment-methods/{paymentMethodId}/cancel": {
      "delete": {
        "description": "Cancels the card subscription on OnPay and marks it as cancelled. This cannot be undone.",
        "operationId": "PublicPaymentMethodsController_cancelCard_v1",
        "parameters": [
          {
            "name": "customerId",
            "required": true,
            "in": "path",
            "description": "The customer ID",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "paymentMethodId",
            "required": true,
            "in": "path",
            "description": "The payment method ID to cancel",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Card cancelled"
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "OAuth2ClientCredentials": []
          }
        ],
        "summary": "Cancel a saved card on the payment provider",
        "tags": [
          "Payment Methods"
        ]
      }
    },
    "/v1/customers/{customerId}/payment-methods/{paymentMethodId}/unassign": {
      "delete": {
        "description": "Removes the link between the customer and the card. The card stays active on the provider and can be reassigned to another customer.",
        "operationId": "PublicPaymentMethodsController_unassign_v1",
        "parameters": [
          {
            "name": "customerId",
            "required": true,
            "in": "path",
            "description": "The customer ID",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "paymentMethodId",
            "required": true,
            "in": "path",
            "description": "The payment method ID to unassign",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Payment method unassigned"
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "OAuth2ClientCredentials": []
          }
        ],
        "summary": "Unassign a payment method from a customer",
        "tags": [
          "Payment Methods"
        ]
      }
    },
    "/v1/customers/{customerId}/payment-methods/card-save-link": {
      "post": {
        "description": "Creates a payment window URL where the customer can enter their card details. The card is saved as a subscription for future charges. Send this URL to your customer.",
        "operationId": "PublicPaymentMethodsController_createCardSaveLink_v1",
        "parameters": [
          {
            "name": "customerId",
            "required": true,
            "in": "path",
            "description": "The customer ID",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateCardSaveLinkRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Payment link created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PaymentLinkResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "OAuth2ClientCredentials": []
          }
        ],
        "summary": "Generate a link for the customer to save a card for future payments",
        "tags": [
          "Payment Methods"
        ]
      }
    },
    "/v1/customers/{customerId}/payment-methods/default/{paymentMethodId}": {
      "put": {
        "description": "Marks this card as the default for the customer. The default card is pre-selected when assigning new subscriptions — it does not retroactively change existing subscriptions. Use the apply-to-subscriptions endpoint to update existing subscriptions.",
        "operationId": "PublicPaymentMethodsController_setDefault_v1",
        "parameters": [
          {
            "name": "customerId",
            "required": true,
            "in": "path",
            "description": "The customer ID",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "paymentMethodId",
            "required": true,
            "in": "path",
            "description": "The payment method ID to set as default",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Default updated"
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "OAuth2ClientCredentials": []
          }
        ],
        "summary": "Set a saved payment method as the customer default",
        "tags": [
          "Payment Methods"
        ]
      }
    },
    "/v1/customers/groups": {
      "get": {
        "description": "\nRetrieves all customer groups for your company, sorted by group number.\nGroups carry a discount percentage and the ledger account customers in the\ngroup post to — assign a customer to a group via the `customerGroupId` field\nwhen creating or updating the customer.\n\nResults are cached for 5 seconds.\n\n## Required Scope\n\n- `customers-read`\n    ",
        "operationId": "PublicCustomersController_getCustomerGroups_v1",
        "parameters": [
          {
            "name": "metadata",
            "required": false,
            "in": "query",
            "style": "deepObject",
            "explode": true,
            "schema": {
              "type": "object",
              "additionalProperties": {
                "type": "string"
              }
            },
            "description": "Exact-match metadata filters in the form metadata[key]=value. Multiple pairs combine with AND semantics — a record matches only if it carries every given key with exactly the given value. At most 10 pairs per request."
          }
        ],
        "responses": {
          "200": {
            "description": "List of customer groups for the company matching the given filters",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/CustomerGroupResponse"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 400
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Bad Request"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 401
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions - API key missing required scopes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 403
                    },
                    "code": {
                      "type": "string",
                      "example": "INSUFFICIENT_PERMISSIONS"
                    },
                    "details": {
                      "type": "object",
                      "properties": {
                        "reason": {
                          "type": "string",
                          "example": "api_key_missing_required_scope"
                        },
                        "requiredScopes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "example": [
                            "usage:write"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "OAuth2ClientCredentials": []
          }
        ],
        "summary": "List customer groups",
        "tags": [
          "Customers"
        ]
      }
    },
    "/v1/dimensions": {
      "get": {
        "description": "\nRetrieves all dimension categories and their values for your company.\n\n## Response Structure\n\nEach dimension includes:\n- **id**: Unique identifier for the dimension category\n- **name**: Display name (e.g., \"Department\", \"Project\")\n- **isUnique**: Whether only one value can be assigned per journal entry\n- **values**: Tree of dimension values with hierarchical structure\n\n## Value Hierarchy\n\nValues are returned as a nested tree structure:\n- Root values have `parentId: null`\n- Nested values reference their parent via `parentId`\n- `children` array contains nested values\n\n## Performance\n\nResults are cached for 5 seconds to improve performance. Changes via POST/PUT/DELETE\nendpoints automatically invalidate the cache.\n\n## Example Response\n\n```json\n[\n  {\n    \"id\": \"550e8400-e29b-41d4-a716-446655440000\",\n    \"name\": \"Department\",\n    \"isUnique\": true,\n    \"values\": [\n      {\n        \"id\": \"...\",\n        \"name\": \"Sales\",\n        \"parentId\": null,\n        \"children\": [\n          { \"id\": \"...\", \"name\": \"Sales Europe\", \"parentId\": \"...\", \"children\": [] }\n        ]\n      }\n    ]\n  }\n]\n```\n    ",
        "operationId": "PublicDimensionsController_getDimensions_v1",
        "parameters": [],
        "responses": {
          "200": {
            "description": "List of dimensions with their values",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Dimension"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 400
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Bad Request"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 401
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions - API key missing required scopes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 403
                    },
                    "code": {
                      "type": "string",
                      "example": "INSUFFICIENT_PERMISSIONS"
                    },
                    "details": {
                      "type": "object",
                      "properties": {
                        "reason": {
                          "type": "string",
                          "example": "api_key_missing_required_scope"
                        },
                        "requiredScopes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "example": [
                            "usage:write"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "OAuth2ClientCredentials": []
          }
        ],
        "summary": "List all dimensions",
        "tags": [
          "Dimensions"
        ]
      },
      "post": {
        "description": "\nCreates a new dimension category (e.g., \"Department\", \"Project\", \"Cost Center\").\n\n## Request Body\n\n| Field | Type | Required | Description |\n|-------|------|----------|-------------|\n| name | string | Yes | Display name (2-100 characters, must be unique) |\n| isUnique | boolean | Yes | Whether only one value can be assigned per journal entry |\n\n## Uniqueness Flag\n\nChoose the `isUnique` setting based on your use case:\n\n- **`isUnique: true`** - Mutually exclusive categories\n  - Example: \"Department\" - a transaction belongs to exactly one department\n  - Journal entry validation will reject multiple values from this category\n\n- **`isUnique: false`** - Additive tags\n  - Example: \"Tags\" - a transaction can have multiple descriptive tags\n  - Multiple values can be freely assigned\n\n**Note**: You can change this setting later, but changing from `false` to `true` will fail\nif any journal entries already have multiple values assigned from this category.\n\n## Example\n\n```json\n{\n  \"name\": \"Cost Center\",\n  \"isUnique\": true\n}\n```\n    ",
        "operationId": "PublicDimensionsController_createDimension_v1",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateDimensionRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Dimension category created successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DimensionResponse"
                }
              }
            }
          },
          "400": {
            "description": "Validation error or duplicate name. Error code: JOURNAL_TAG_CATEGORY_NAME_ALREADY_EXISTS"
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 401
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions - API key missing required scopes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 403
                    },
                    "code": {
                      "type": "string",
                      "example": "INSUFFICIENT_PERMISSIONS"
                    },
                    "details": {
                      "type": "object",
                      "properties": {
                        "reason": {
                          "type": "string",
                          "example": "api_key_missing_required_scope"
                        },
                        "requiredScopes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "example": [
                            "usage:write"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "OAuth2ClientCredentials": []
          }
        ],
        "summary": "Create a new dimension category",
        "tags": [
          "Dimensions"
        ]
      }
    },
    "/v1/dimensions/{id}": {
      "get": {
        "description": "\nRetrieves a specific dimension category and all its values.\n\nUseful when you need to refresh data for a single dimension after making changes,\nwithout fetching all dimensions.\n    ",
        "operationId": "PublicDimensionsController_getDimension_v1",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "description": "The unique identifier of the dimension category",
            "schema": {
              "example": "550e8400-e29b-41d4-a716-446655440000",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The dimension with its values",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Dimension"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 400
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Bad Request"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 401
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions - API key missing required scopes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 403
                    },
                    "code": {
                      "type": "string",
                      "example": "INSUFFICIENT_PERMISSIONS"
                    },
                    "details": {
                      "type": "object",
                      "properties": {
                        "reason": {
                          "type": "string",
                          "example": "api_key_missing_required_scope"
                        },
                        "requiredScopes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "example": [
                            "usage:write"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Dimension not found. Error code: JOURNAL_TAG_CATEGORY_NOT_FOUND"
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "OAuth2ClientCredentials": []
          }
        ],
        "summary": "Get a single dimension by ID",
        "tags": [
          "Dimensions"
        ]
      },
      "put": {
        "description": "\nUpdates an existing dimension category. All fields are optional - only provide fields you want to change.\n\n## Updating the Name\n\nProvide a new `name` to rename the dimension category. The new name must be unique\nwithin your company.\n\n## Changing the Uniqueness Constraint\n\n**From `false` to `true`:**\n- Will fail if any journal entries currently have multiple values from this category\n- Before making this change, ensure all journal entries have at most one value assigned\n- Error code if failed: JOURNAL_TAG_CATEGORY_UNIQUENESS_CONFLICT\n\n**From `true` to `false`:**\n- Always succeeds\n- Existing journal entries are unaffected\n- Future journal entries can have multiple values\n\n## Request Body\n\n| Field | Type | Required | Description |\n|-------|------|----------|-------------|\n| name | string | No | New display name (2-100 characters, must be unique) |\n| isUnique | boolean | No | New uniqueness constraint |\n\n## Example\n\n```json\n{\n  \"name\": \"Business Unit\"\n}\n```\n    ",
        "operationId": "PublicDimensionsController_updateDimension_v1",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "description": "The unique identifier of the dimension category to update",
            "schema": {
              "example": "550e8400-e29b-41d4-a716-446655440000",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateDimensionRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Dimension category updated successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DimensionResponse"
                }
              }
            }
          },
          "400": {
            "description": "Validation error, duplicate name, or uniqueness conflict. Error codes: JOURNAL_TAG_CATEGORY_NAME_ALREADY_EXISTS, JOURNAL_TAG_CATEGORY_UNIQUENESS_CONFLICT"
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 401
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions - API key missing required scopes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 403
                    },
                    "code": {
                      "type": "string",
                      "example": "INSUFFICIENT_PERMISSIONS"
                    },
                    "details": {
                      "type": "object",
                      "properties": {
                        "reason": {
                          "type": "string",
                          "example": "api_key_missing_required_scope"
                        },
                        "requiredScopes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "example": [
                            "usage:write"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Dimension not found. Error code: JOURNAL_TAG_CATEGORY_NOT_FOUND"
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "OAuth2ClientCredentials": []
          }
        ],
        "summary": "Update a dimension category",
        "tags": [
          "Dimensions"
        ]
      },
      "delete": {
        "description": "\nDeletes a dimension category. The category must be empty (have no values) before deletion.\n\n## Prerequisites\n\nBefore deleting a dimension category:\n1. Delete all dimension values within the category\n2. For hierarchical values, delete children before parents\n\n## Cascade Behavior\n\n- Dimension values are **NOT** automatically deleted\n- You must explicitly delete all values first\n- This prevents accidental data loss\n\n## Error Handling\n\n- If the category has values, returns error code: JOURNAL_TAG_CATEGORY_HAS_TAGS\n- If the category doesn't exist, returns error code: JOURNAL_TAG_CATEGORY_NOT_FOUND\n    ",
        "operationId": "PublicDimensionsController_deleteDimension_v1",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "description": "The unique identifier of the dimension category to delete",
            "schema": {
              "example": "550e8400-e29b-41d4-a716-446655440000",
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Dimension category deleted successfully"
          },
          "400": {
            "description": "Category has values and cannot be deleted. Error code: JOURNAL_TAG_CATEGORY_HAS_TAGS"
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 401
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions - API key missing required scopes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 403
                    },
                    "code": {
                      "type": "string",
                      "example": "INSUFFICIENT_PERMISSIONS"
                    },
                    "details": {
                      "type": "object",
                      "properties": {
                        "reason": {
                          "type": "string",
                          "example": "api_key_missing_required_scope"
                        },
                        "requiredScopes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "example": [
                            "usage:write"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Dimension not found. Error code: JOURNAL_TAG_CATEGORY_NOT_FOUND"
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "OAuth2ClientCredentials": []
          }
        ],
        "summary": "Delete a dimension category",
        "tags": [
          "Dimensions"
        ]
      }
    },
    "/v1/dimensions/values": {
      "post": {
        "description": "\nCreates a new dimension value within an existing dimension category.\n\n## Request Body\n\n| Field | Type | Required | Description |\n|-------|------|----------|-------------|\n| dimensionId | string (UUID) | Yes | The dimension category ID this value belongs to |\n| name | string | Yes | Display name (2-120 characters, must be unique within category) |\n| parentId | string (UUID) | No | Parent value ID for hierarchical structures |\n\n## Creating Hierarchical Values\n\nDimension values can be nested to create hierarchies like \"Europe > Denmark > Copenhagen\":\n\n1. Create \"Europe\" without a parentId (root level)\n2. Create \"Denmark\" with parentId = Europe's ID\n3. Create \"Copenhagen\" with parentId = Denmark's ID\n\n**Rules:**\n- Parent must exist within the same dimension category\n- No circular references allowed\n\n## Example - Root Value\n\n```json\n{\n  \"dimensionId\": \"550e8400-e29b-41d4-a716-446655440000\",\n  \"name\": \"Europe\"\n}\n```\n\n## Example - Nested Value\n\n```json\n{\n  \"dimensionId\": \"550e8400-e29b-41d4-a716-446655440000\",\n  \"name\": \"Denmark\",\n  \"parentId\": \"550e8400-e29b-41d4-a716-446655440001\"\n}\n```\n    ",
        "operationId": "PublicDimensionsController_createDimensionValue_v1",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateDimensionValueRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Dimension value created successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DimensionValueResponse"
                }
              }
            }
          },
          "400": {
            "description": "Validation error, duplicate name, or invalid parent. Error codes: JOURNAL_TAG_CATEGORY_NOT_FOUND, JOURNAL_TAG_NAME_ALREADY_EXISTS, JOURNAL_TAG_PARENT_INVALID"
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 401
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions - API key missing required scopes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 403
                    },
                    "code": {
                      "type": "string",
                      "example": "INSUFFICIENT_PERMISSIONS"
                    },
                    "details": {
                      "type": "object",
                      "properties": {
                        "reason": {
                          "type": "string",
                          "example": "api_key_missing_required_scope"
                        },
                        "requiredScopes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "example": [
                            "usage:write"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "OAuth2ClientCredentials": []
          }
        ],
        "summary": "Create a new dimension value",
        "tags": [
          "Dimensions"
        ]
      }
    },
    "/v1/dimensions/values/{id}": {
      "put": {
        "description": "\nUpdates an existing dimension value. All fields are optional - only provide fields you want to change.\n\n## Updating the Name\n\nProvide a new `name` to rename the value. The new name must be unique within the\ndimension category.\n\n## Changing the Parent (Moving in Hierarchy)\n\nSet `parentId` to move the value within the hierarchy:\n\n- **Move to root level**: Set `parentId: null`\n- **Move under another value**: Set `parentId` to the new parent's ID\n\n**Rules:**\n- New parent must exist within the same dimension category\n- Cannot create circular references (A cannot be parent of B if B is already an ancestor of A)\n- Moving a value also moves all its children\n\n## Request Body\n\n| Field | Type | Required | Description |\n|-------|------|----------|-------------|\n| name | string | No | New display name (2-120 characters, must be unique within category) |\n| parentId | string (UUID) or null | No | New parent value ID, or null for root level |\n\n## Example - Rename\n\n```json\n{\n  \"name\": \"Northern Europe\"\n}\n```\n\n## Example - Move to Root\n\n```json\n{\n  \"parentId\": null\n}\n```\n    ",
        "operationId": "PublicDimensionsController_updateDimensionValue_v1",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "description": "The unique identifier of the dimension value to update",
            "schema": {
              "example": "550e8400-e29b-41d4-a716-446655440000",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateDimensionValueRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Dimension value updated successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DimensionValueResponse"
                }
              }
            }
          },
          "400": {
            "description": "Validation error, duplicate name, or invalid parent. Error codes: JOURNAL_TAG_NAME_ALREADY_EXISTS, JOURNAL_TAG_PARENT_INVALID"
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 401
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions - API key missing required scopes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 403
                    },
                    "code": {
                      "type": "string",
                      "example": "INSUFFICIENT_PERMISSIONS"
                    },
                    "details": {
                      "type": "object",
                      "properties": {
                        "reason": {
                          "type": "string",
                          "example": "api_key_missing_required_scope"
                        },
                        "requiredScopes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "example": [
                            "usage:write"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Dimension value not found. Error code: JOURNAL_TAG_NOT_FOUND"
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "OAuth2ClientCredentials": []
          }
        ],
        "summary": "Update a dimension value",
        "tags": [
          "Dimensions"
        ]
      },
      "delete": {
        "description": "\nDeletes a dimension value. The value must have no children before deletion.\n\n## Prerequisites\n\nBefore deleting a dimension value:\n1. Delete all child values first (if hierarchical)\n2. Consider the impact on reporting - historical journal entries keep their assignments\n\n## Cascade Behavior\n\n- Child values are **NOT** automatically deleted\n- You must explicitly delete children first (bottom-up deletion)\n- Journal entry assignments are automatically removed when the value is deleted\n\n## Deletion Order for Hierarchies\n\nFor a hierarchy like \"Europe > Denmark > Copenhagen\":\n1. Delete \"Copenhagen\" first\n2. Then delete \"Denmark\"\n3. Finally delete \"Europe\"\n\n## Error Handling\n\n- If the value has children, returns error code: JOURNAL_TAG_HAS_CHILDREN\n- If the value doesn't exist, returns error code: JOURNAL_TAG_NOT_FOUND\n    ",
        "operationId": "PublicDimensionsController_deleteDimensionValue_v1",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "description": "The unique identifier of the dimension value to delete",
            "schema": {
              "example": "550e8400-e29b-41d4-a716-446655440000",
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Dimension value deleted successfully"
          },
          "400": {
            "description": "Value has children and cannot be deleted. Error code: JOURNAL_TAG_HAS_CHILDREN"
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 401
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions - API key missing required scopes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 403
                    },
                    "code": {
                      "type": "string",
                      "example": "INSUFFICIENT_PERMISSIONS"
                    },
                    "details": {
                      "type": "object",
                      "properties": {
                        "reason": {
                          "type": "string",
                          "example": "api_key_missing_required_scope"
                        },
                        "requiredScopes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "example": [
                            "usage:write"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Dimension value not found. Error code: JOURNAL_TAG_NOT_FOUND"
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "OAuth2ClientCredentials": []
          }
        ],
        "summary": "Delete a dimension value",
        "tags": [
          "Dimensions"
        ]
      }
    },
    "/v1/document-templates": {
      "get": {
        "description": "\nRetrieves a paginated list of your company's document templates for the\npublicly exposed document types — invoice, credit note, quote, and order\nconfirmation.\n\nPass `?type=` to filter by document type, or `?search=` to prefix-match\non template name.\n\n## Required Scope\n\n- `document-templates-read`\n    ",
        "operationId": "PublicDocumentTemplatesController_list_v1",
        "parameters": [
          {
            "name": "page",
            "required": false,
            "in": "query",
            "description": "Page number (1-indexed)",
            "schema": {
              "minimum": 1,
              "default": 1,
              "type": "number"
            }
          },
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "description": "Maximum number of items per page",
            "schema": {
              "minimum": 1,
              "maximum": 100,
              "default": 25,
              "type": "number"
            }
          },
          {
            "name": "search",
            "required": false,
            "in": "query",
            "description": "Prefix search on template name",
            "schema": {
              "example": "Premium",
              "type": "string"
            }
          },
          {
            "name": "documentType",
            "required": false,
            "in": "query",
            "description": "Filter by document type",
            "schema": {
              "type": "string",
              "enum": [
                "invoice-template",
                "credit-note-template",
                "quote-template",
                "order-confirmation-template"
              ]
            }
          },
          {
            "name": "sortBy",
            "required": false,
            "in": "query",
            "description": "Field to sort by",
            "schema": {
              "default": "createdAt",
              "type": "string",
              "enum": [
                "name",
                "documentType",
                "createdAt"
              ]
            }
          },
          {
            "name": "sortOrder",
            "required": false,
            "in": "query",
            "description": "Sort direction",
            "schema": {
              "default": "DESC",
              "type": "string",
              "enum": [
                "ASC",
                "DESC"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Paginated list of document templates for the company",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ListDocumentTemplatesResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 400
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Bad Request"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 401
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions - API key missing required scopes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 403
                    },
                    "code": {
                      "type": "string",
                      "example": "INSUFFICIENT_PERMISSIONS"
                    },
                    "details": {
                      "type": "object",
                      "properties": {
                        "reason": {
                          "type": "string",
                          "example": "api_key_missing_required_scope"
                        },
                        "requiredScopes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "example": [
                            "usage:write"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "OAuth2ClientCredentials": []
          }
        ],
        "summary": "List document templates",
        "tags": [
          "Document Templates"
        ]
      }
    },
    "/v1/draft-journal-batches": {
      "post": {
        "deprecated": true,
        "description": "Creates multiple draft journal entries in a single transaction. All entries are committed together — if any entry fails, the entire batch is rolled back.\n\nDEPRECATED — sunset on 2026-11-08 (RFC 8594; every response carries `Deprecation`/`Sunset`/`Link` headers). Migrate to `POST /api/v2/draft-journal-batches`.",
        "operationId": "PublicDraftJournalBatchesController_createDraftJournalEntryBatch_v1",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateDraftJournalEntryBatchRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Batch of draft journal entries created successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreateDraftJournalEntryBatchResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 400
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Bad Request"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 401
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions - API key missing required scopes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 403
                    },
                    "code": {
                      "type": "string",
                      "example": "INSUFFICIENT_PERMISSIONS"
                    },
                    "details": {
                      "type": "object",
                      "properties": {
                        "reason": {
                          "type": "string",
                          "example": "api_key_missing_required_scope"
                        },
                        "requiredScopes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "example": [
                            "usage:write"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "OAuth2ClientCredentials": []
          }
        ],
        "summary": "Create multiple draft journal entries in batch",
        "tags": [
          "Draft Journal Entries"
        ]
      }
    },
    "/v1/draft-journal-entries": {
      "post": {
        "deprecated": true,
        "description": "Creates a draft journal entry that can be reviewed before being booked as a real posted journal entry. Accepts the same fields as the regular journal entry endpoint. The posting period is not validated at creation time.\n\nDEPRECATED — sunset on 2026-11-08 (RFC 8594; every response carries `Deprecation`/`Sunset`/`Link` headers). Migrate to the v2 draft endpoints under `/api/v2/draft-journal-entries`.",
        "operationId": "PublicDraftJournalEntriesController_createDraftJournalEntry_v1",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateDraftJournalEntryRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Draft journal entry created successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DraftJournalEntryResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 400
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Bad Request"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 401
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions - API key missing required scopes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 403
                    },
                    "code": {
                      "type": "string",
                      "example": "INSUFFICIENT_PERMISSIONS"
                    },
                    "details": {
                      "type": "object",
                      "properties": {
                        "reason": {
                          "type": "string",
                          "example": "api_key_missing_required_scope"
                        },
                        "requiredScopes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "example": [
                            "usage:write"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "OAuth2ClientCredentials": []
          }
        ],
        "summary": "Create a draft journal entry",
        "tags": [
          "Draft Journal Entries"
        ]
      },
      "get": {
        "deprecated": true,
        "description": "Retrieves a paginated list of draft journal entries created via the public API, with optional filtering.\n\nDEPRECATED — sunset on 2026-11-08 (RFC 8594; every response carries `Deprecation`/`Sunset`/`Link` headers). Migrate to the v2 draft endpoints under `/api/v2/draft-journal-entries`.",
        "operationId": "PublicDraftJournalEntriesController_listDraftJournalEntries_v1",
        "parameters": [
          {
            "name": "page",
            "required": false,
            "in": "query",
            "description": "Page number (1-indexed)",
            "schema": {
              "minimum": 1,
              "default": 1,
              "type": "number"
            }
          },
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "description": "Maximum items per page",
            "schema": {
              "minimum": 1,
              "maximum": 100,
              "default": 25,
              "type": "number"
            }
          },
          {
            "name": "fromDate",
            "required": false,
            "in": "query",
            "description": "Only include drafts on or after this date (YYYY-MM-DD)",
            "schema": {
              "example": "2026-01-01",
              "type": "string"
            }
          },
          {
            "name": "toDate",
            "required": false,
            "in": "query",
            "description": "Only include drafts on or before this date (YYYY-MM-DD)",
            "schema": {
              "example": "2026-01-31",
              "type": "string"
            }
          },
          {
            "name": "accountId",
            "required": false,
            "in": "query",
            "description": "Filter by account ID (matches any draft line on this account)",
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          },
          {
            "name": "customerId",
            "required": false,
            "in": "query",
            "description": "Filter by customer ID",
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          },
          {
            "name": "vendorId",
            "required": false,
            "in": "query",
            "description": "Filter by vendor ID",
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          },
          {
            "name": "journalType",
            "required": false,
            "in": "query",
            "description": "Filter by journal type",
            "schema": {
              "type": "string",
              "enum": [
                "JOURNAL_ENTRY",
                "SUPPLIER_INVOICE",
                "SUPPLIER_PAYMENT",
                "CUSTOMER_INVOICE",
                "CUSTOMER_PAYMENT",
                "CUSTOMER_REMINDER",
                "CURRENCY_REVALUATION",
                "VAT_SETTLEMENT",
                "YEAR_END_CLOSING"
              ]
            }
          },
          {
            "name": "minAmount",
            "required": false,
            "in": "query",
            "description": "Only include drafts with an amount greater than or equal to this value (inclusive).",
            "schema": {
              "example": 100,
              "type": "number"
            }
          },
          {
            "name": "maxAmount",
            "required": false,
            "in": "query",
            "description": "Only include drafts with an amount less than or equal to this value (inclusive).",
            "schema": {
              "example": 10000,
              "type": "number"
            }
          },
          {
            "name": "externalSystemId",
            "required": false,
            "in": "query",
            "description": "Exact-match filter on your own system's id. Not unique — several drafts may share one id, so expect zero or more results.",
            "schema": {
              "maxLength": 255,
              "example": "erp-7f3a2c91",
              "type": "string"
            }
          },
          {
            "name": "search",
            "required": false,
            "in": "query",
            "description": "Free-text search in description and reference fields",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Draft journal entries retrieved successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ListDraftJournalEntriesResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 400
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Bad Request"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 401
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions - API key missing required scopes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 403
                    },
                    "code": {
                      "type": "string",
                      "example": "INSUFFICIENT_PERMISSIONS"
                    },
                    "details": {
                      "type": "object",
                      "properties": {
                        "reason": {
                          "type": "string",
                          "example": "api_key_missing_required_scope"
                        },
                        "requiredScopes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "example": [
                            "usage:write"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "OAuth2ClientCredentials": []
          }
        ],
        "summary": "List draft journal entries",
        "tags": [
          "Draft Journal Entries"
        ]
      }
    },
    "/v1/draft-journal-entries/{id}": {
      "get": {
        "deprecated": true,
        "description": "Retrieves a draft journal entry by ID.\n\nDEPRECATED — sunset on 2026-11-08 (RFC 8594; every response carries `Deprecation`/`Sunset`/`Link` headers). Migrate to the v2 draft endpoints under `/api/v2/draft-journal-entries`.",
        "operationId": "PublicDraftJournalEntriesController_getDraftJournalEntry_v1",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "description": "Draft journal entry ID (UUID)",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Draft journal entry retrieved successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DraftJournalEntryResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 400
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Bad Request"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 401
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions - API key missing required scopes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 403
                    },
                    "code": {
                      "type": "string",
                      "example": "INSUFFICIENT_PERMISSIONS"
                    },
                    "details": {
                      "type": "object",
                      "properties": {
                        "reason": {
                          "type": "string",
                          "example": "api_key_missing_required_scope"
                        },
                        "requiredScopes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "example": [
                            "usage:write"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "OAuth2ClientCredentials": []
          }
        ],
        "summary": "Get a single draft journal entry",
        "tags": [
          "Draft Journal Entries"
        ]
      },
      "delete": {
        "deprecated": true,
        "description": "Deletes a draft journal entry. Any attached documents are released back to the inbox (status reset to NEW).\n\nDEPRECATED — sunset on 2026-11-08 (RFC 8594; every response carries `Deprecation`/`Sunset`/`Link` headers). Migrate to the v2 draft endpoints under `/api/v2/draft-journal-entries`.",
        "operationId": "PublicDraftJournalEntriesController_deleteDraftJournalEntry_v1",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "description": "Draft journal entry ID (UUID)",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Draft deleted successfully"
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 400
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Bad Request"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 401
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions - API key missing required scopes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 403
                    },
                    "code": {
                      "type": "string",
                      "example": "INSUFFICIENT_PERMISSIONS"
                    },
                    "details": {
                      "type": "object",
                      "properties": {
                        "reason": {
                          "type": "string",
                          "example": "api_key_missing_required_scope"
                        },
                        "requiredScopes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "example": [
                            "usage:write"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "OAuth2ClientCredentials": []
          }
        ],
        "summary": "Delete a draft journal entry",
        "tags": [
          "Draft Journal Entries"
        ]
      }
    },
    "/v1/draft-journal-entries/{id}/book": {
      "post": {
        "deprecated": true,
        "description": "Converts a draft journal entry into a real posted journal entry. Validates the posting period and balance, then permanently deletes the draft.\n\nDEPRECATED — sunset on 2026-11-08 (RFC 8594; every response carries `Deprecation`/`Sunset`/`Link` headers). Migrate to the v2 draft endpoints under `/api/v2/draft-journal-entries`.",
        "operationId": "PublicDraftJournalEntriesController_bookDraftJournalEntry_v1",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "description": "Draft journal entry ID (UUID)",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "201": {
            "description": "Draft booked successfully — returns the created journal entry",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JournalEntryResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 400
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Bad Request"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 401
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions - API key missing required scopes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 403
                    },
                    "code": {
                      "type": "string",
                      "example": "INSUFFICIENT_PERMISSIONS"
                    },
                    "details": {
                      "type": "object",
                      "properties": {
                        "reason": {
                          "type": "string",
                          "example": "api_key_missing_required_scope"
                        },
                        "requiredScopes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "example": [
                            "usage:write"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "OAuth2ClientCredentials": []
          }
        ],
        "summary": "Book a draft journal entry",
        "tags": [
          "Draft Journal Entries"
        ]
      }
    },
    "/v1/invoices": {
      "post": {
        "description": "Creates a draft invoice. The invoice number is allocated at booking time (when sent), so a draft has no number yet.",
        "operationId": "PublicInvoicesController_create_v1",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PublicCreateInvoice"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Invoice created successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicInvoice"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 400
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Bad Request"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 401
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions - API key missing required scopes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 403
                    },
                    "code": {
                      "type": "string",
                      "example": "INSUFFICIENT_PERMISSIONS"
                    },
                    "details": {
                      "type": "object",
                      "properties": {
                        "reason": {
                          "type": "string",
                          "example": "api_key_missing_required_scope"
                        },
                        "requiredScopes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "example": [
                            "usage:write"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "OAuth2ClientCredentials": []
          }
        ],
        "summary": "Create a draft invoice",
        "tags": [
          "Invoices"
        ]
      },
      "get": {
        "description": "Returns a paginated list of invoices for your company, optionally filtered by status and customer.",
        "operationId": "PublicInvoicesController_list_v1",
        "parameters": [
          {
            "name": "page",
            "required": false,
            "in": "query",
            "description": "Page number (1-indexed)",
            "schema": {
              "minimum": 1,
              "default": 1,
              "example": 1,
              "type": "number"
            }
          },
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "description": "Number of items per page",
            "schema": {
              "minimum": 1,
              "maximum": 100,
              "default": 25,
              "example": 25,
              "type": "number"
            }
          },
          {
            "name": "search",
            "required": false,
            "in": "query",
            "description": "Free-text search (invoice number, description)",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "status",
            "required": false,
            "in": "query",
            "description": "Filter invoices by status",
            "schema": {
              "type": "string",
              "enum": [
                "draft",
                "scheduled",
                "sending",
                "sent",
                "paid",
                "partially_paid",
                "cancelled",
                "uncollectible",
                "credited"
              ]
            }
          },
          {
            "name": "customerId",
            "required": false,
            "in": "query",
            "description": "Filter invoices for a specific customer",
            "schema": {
              "example": "0197A943-2325-7829-B835-B6C71A293065",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Paginated list of invoices",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicListInvoicesResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 400
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Bad Request"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 401
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions - API key missing required scopes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 403
                    },
                    "code": {
                      "type": "string",
                      "example": "INSUFFICIENT_PERMISSIONS"
                    },
                    "details": {
                      "type": "object",
                      "properties": {
                        "reason": {
                          "type": "string",
                          "example": "api_key_missing_required_scope"
                        },
                        "requiredScopes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "example": [
                            "usage:write"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "OAuth2ClientCredentials": []
          }
        ],
        "summary": "List invoices",
        "tags": [
          "Invoices"
        ]
      }
    },
    "/v1/invoices/{id}": {
      "get": {
        "description": "\nRetrieves a single invoice by its unique identifier. Returns `404` when the\ninvoice does not exist in your company. For the rendered document, use the\nPDF endpoint.\n\n## Required Scope\n\n- `invoices-read`\n    ",
        "operationId": "PublicInvoicesController_getOne_v1",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "description": "Invoice ID",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The invoice",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicInvoice"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 400
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Bad Request"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 401
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions - API key missing required scopes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 403
                    },
                    "code": {
                      "type": "string",
                      "example": "INSUFFICIENT_PERMISSIONS"
                    },
                    "details": {
                      "type": "object",
                      "properties": {
                        "reason": {
                          "type": "string",
                          "example": "api_key_missing_required_scope"
                        },
                        "requiredScopes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "example": [
                            "usage:write"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "OAuth2ClientCredentials": []
          }
        ],
        "summary": "Get an invoice by ID",
        "tags": [
          "Invoices"
        ]
      }
    },
    "/v1/invoices/{id}/delivery-status": {
      "get": {
        "description": "Returns an aggregate send summary plus a per-attempt delivery log for the invoice.",
        "operationId": "PublicInvoicesController_getDeliveryStatus_v1",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "description": "Invoice ID",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Delivery status",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicDeliveryStatusResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 400
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Bad Request"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 401
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions - API key missing required scopes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 403
                    },
                    "code": {
                      "type": "string",
                      "example": "INSUFFICIENT_PERMISSIONS"
                    },
                    "details": {
                      "type": "object",
                      "properties": {
                        "reason": {
                          "type": "string",
                          "example": "api_key_missing_required_scope"
                        },
                        "requiredScopes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "example": [
                            "usage:write"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "OAuth2ClientCredentials": []
          }
        ],
        "summary": "Get the delivery status of an invoice",
        "tags": [
          "Invoices"
        ]
      }
    },
    "/v1/invoices/{id}/pdf": {
      "get": {
        "description": "Streams the rendered invoice PDF. Pass `draft=true` to render a draft watermark version (generated on the fly).",
        "operationId": "PublicInvoicesController_downloadPdf_v1",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "description": "Invoice ID",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "draft",
            "required": false,
            "in": "query",
            "description": "Render a draft watermark version",
            "schema": {
              "type": "boolean"
            }
          }
        ],
        "responses": {
          "400": {
            "description": "Bad Request",
            "content": {
              "application/pdf": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 400
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Bad Request"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/pdf": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 401
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions - API key missing required scopes",
            "content": {
              "application/pdf": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 403
                    },
                    "code": {
                      "type": "string",
                      "example": "INSUFFICIENT_PERMISSIONS"
                    },
                    "details": {
                      "type": "object",
                      "properties": {
                        "reason": {
                          "type": "string",
                          "example": "api_key_missing_required_scope"
                        },
                        "requiredScopes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "example": [
                            "usage:write"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "OAuth2ClientCredentials": []
          }
        ],
        "summary": "Download the invoice PDF",
        "tags": [
          "Invoices"
        ]
      }
    },
    "/v1/invoices/{id}/send": {
      "post": {
        "description": "Sends the invoice over the chosen delivery channel (Email, Sproom e-invoicing, or Manual). Sending books the invoice and allocates its number.",
        "operationId": "PublicInvoicesController_send_v1",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "description": "Invoice ID",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PublicSendInvoice"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Invoice send accepted",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicSendInvoiceResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 400
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Bad Request"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 401
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions - API key missing required scopes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 403
                    },
                    "code": {
                      "type": "string",
                      "example": "INSUFFICIENT_PERMISSIONS"
                    },
                    "details": {
                      "type": "object",
                      "properties": {
                        "reason": {
                          "type": "string",
                          "example": "api_key_missing_required_scope"
                        },
                        "requiredScopes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "example": [
                            "usage:write"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "OAuth2ClientCredentials": []
          }
        ],
        "summary": "Send an invoice to the customer",
        "tags": [
          "Invoices"
        ]
      }
    },
    "/v1/journal-batches": {
      "post": {
        "deprecated": true,
        "description": "DEPRECATED. Migrate to `POST /api/v2/journal-entries` and call it once per entry; v2 auto-appends the AR/AP leg on the customer/vendor group default and rejects drift with typed error codes. The batch behavior of this endpoint will be re-introduced on v2 once the gated app fully cuts over from v1. \n\nOriginal behavior: creates multiple journal entries in a single transaction. All entries are committed together — if any entry fails, the entire batch is rolled back. Supports journal entries, invoices, and payments with optional customer and dimension references.",
        "operationId": "PublicJournalBatchesController_createJournalEntryBatch_v1",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateJournalEntryBatchRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Batch of journal entries created successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreateJournalEntryBatchResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 400
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Bad Request"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 401
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions - API key missing required scopes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 403
                    },
                    "code": {
                      "type": "string",
                      "example": "INSUFFICIENT_PERMISSIONS"
                    },
                    "details": {
                      "type": "object",
                      "properties": {
                        "reason": {
                          "type": "string",
                          "example": "api_key_missing_required_scope"
                        },
                        "requiredScopes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "example": [
                            "usage:write"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "OAuth2ClientCredentials": []
          }
        ],
        "summary": "Create multiple journal entries in batch (DEPRECATED — migrate to v2)",
        "tags": [
          "Journal Entries"
        ]
      }
    },
    "/v1/journal-categories": {
      "get": {
        "description": "\nRetrieves the journal categories of your company. A category groups journal\nentries and restricts which entry types may be posted into it — pass its id\nas `journalCategoryId` when creating journal entries or drafts.\n\nThe default category is returned first, then the rest in creation order.\nResults are cached for 5 seconds.\n\n## Required Scope\n\n- `journal-categories-read`\n    ",
        "operationId": "PublicJournalCategoriesController_getJournalCategories_v1",
        "parameters": [],
        "responses": {
          "200": {
            "description": "List of available journal categories for the company",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/JournalCategoryResponse"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 400
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Bad Request"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 401
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions - API key missing required scopes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 403
                    },
                    "code": {
                      "type": "string",
                      "example": "INSUFFICIENT_PERMISSIONS"
                    },
                    "details": {
                      "type": "object",
                      "properties": {
                        "reason": {
                          "type": "string",
                          "example": "api_key_missing_required_scope"
                        },
                        "requiredScopes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "example": [
                            "usage:write"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "OAuth2ClientCredentials": []
          }
        ],
        "summary": "List journal categories",
        "tags": [
          "Journal Categories"
        ]
      }
    },
    "/v1/journal-entries": {
      "post": {
        "deprecated": true,
        "description": "DEPRECATED. Use `POST /api/v2/journal-entries` instead. The v2 endpoint auto-appends the AR/AP leg on the customer/vendor group default account, eliminating the most common booking error (drift between the posted account and the configured group default). v1 stays available for legacy integrators but skips the anchor-account guard, so any drift it accepts will need to be reconciled later. \n\nOriginal behavior: creates a single journal entry with the specified accounts and amount. Supports journal entries, invoices, and payments with optional customer and dimension references.",
        "operationId": "PublicJournalEntriesController_createJournalEntry_v1",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateJournalEntryRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Journal entry created successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JournalEntryResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 400
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Bad Request"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 401
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions - API key missing required scopes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 403
                    },
                    "code": {
                      "type": "string",
                      "example": "INSUFFICIENT_PERMISSIONS"
                    },
                    "details": {
                      "type": "object",
                      "properties": {
                        "reason": {
                          "type": "string",
                          "example": "api_key_missing_required_scope"
                        },
                        "requiredScopes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "example": [
                            "usage:write"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "OAuth2ClientCredentials": []
          }
        ],
        "summary": "Create a single journal entry (DEPRECATED — use POST /api/v2/journal-entries)",
        "tags": [
          "Journal Entries"
        ]
      },
      "get": {
        "description": "Retrieves a paginated list of journal entries with optional filtering by date, account, customer, external system id, and search text.",
        "operationId": "PublicJournalEntriesController_listJournalEntries_v1",
        "parameters": [
          {
            "name": "page",
            "required": false,
            "in": "query",
            "description": "Page number (1-indexed)",
            "schema": {
              "minimum": 1,
              "default": 1,
              "type": "number"
            }
          },
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "description": "Maximum number of items per page",
            "schema": {
              "minimum": 1,
              "maximum": 100,
              "default": 25,
              "type": "number"
            }
          },
          {
            "name": "fromDate",
            "required": false,
            "in": "query",
            "description": "Only include entries with a posting date on or after this date (ISO 8601). Filters je.date (bogføringsdato).",
            "schema": {
              "example": "2026-01-01",
              "type": "string"
            }
          },
          {
            "name": "toDate",
            "required": false,
            "in": "query",
            "description": "Only include entries with a posting date on or before this date (ISO 8601). Filters je.date (bogføringsdato).",
            "schema": {
              "example": "2026-01-31",
              "type": "string"
            }
          },
          {
            "name": "documentDateFrom",
            "required": false,
            "in": "query",
            "description": "Only include entries with a document date on or after this date (ISO 8601). Filters je.documentDate.",
            "schema": {
              "example": "2026-01-01",
              "type": "string"
            }
          },
          {
            "name": "documentDateTo",
            "required": false,
            "in": "query",
            "description": "Only include entries with a document date on or before this date (ISO 8601). Filters je.documentDate.",
            "schema": {
              "example": "2026-01-31",
              "type": "string"
            }
          },
          {
            "name": "accountId",
            "required": false,
            "in": "query",
            "description": "Filter by account ID",
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          },
          {
            "name": "customerId",
            "required": false,
            "in": "query",
            "description": "Filter by customer ID",
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          },
          {
            "name": "vendorId",
            "required": false,
            "in": "query",
            "description": "Filter by vendor ID",
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          },
          {
            "name": "journalType",
            "required": false,
            "in": "query",
            "description": "Filter by journal type",
            "schema": {
              "type": "string",
              "enum": [
                "JOURNAL_ENTRY",
                "SUPPLIER_INVOICE",
                "SUPPLIER_PAYMENT",
                "CUSTOMER_INVOICE",
                "CUSTOMER_PAYMENT",
                "CUSTOMER_REMINDER",
                "CURRENCY_REVALUATION",
                "VAT_SETTLEMENT",
                "YEAR_END_CLOSING"
              ]
            }
          },
          {
            "name": "externalSystemId",
            "required": false,
            "in": "query",
            "description": "Exact-match filter on your own system's id (set via PATCH /journal-entries/:id or carried on the entry). Not unique — several entries may share one id, so expect zero or more results.",
            "schema": {
              "maxLength": 255,
              "example": "erp-7f3a2c91",
              "type": "string"
            }
          },
          {
            "name": "minAmount",
            "required": false,
            "in": "query",
            "description": "Only include entries with an amount greater than or equal to this value (inclusive).",
            "schema": {
              "example": 100,
              "type": "number"
            }
          },
          {
            "name": "maxAmount",
            "required": false,
            "in": "query",
            "description": "Only include entries with an amount less than or equal to this value (inclusive).",
            "schema": {
              "example": 10000,
              "type": "number"
            }
          },
          {
            "name": "search",
            "required": false,
            "in": "query",
            "description": "Free-text search in description and reference fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "sortBy",
            "required": false,
            "in": "query",
            "description": "Sort field",
            "schema": {
              "default": "date",
              "example": "date",
              "type": "string",
              "enum": [
                "date",
                "documentDate",
                "amount",
                "createdAt"
              ]
            }
          },
          {
            "name": "sortOrder",
            "required": false,
            "in": "query",
            "description": "Sort direction",
            "schema": {
              "default": "DESC",
              "example": "DESC",
              "type": "string",
              "enum": [
                "ASC",
                "DESC"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Journal entries retrieved successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ListJournalEntriesResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 400
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Bad Request"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 401
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions - API key missing required scopes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 403
                    },
                    "code": {
                      "type": "string",
                      "example": "INSUFFICIENT_PERMISSIONS"
                    },
                    "details": {
                      "type": "object",
                      "properties": {
                        "reason": {
                          "type": "string",
                          "example": "api_key_missing_required_scope"
                        },
                        "requiredScopes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "example": [
                            "usage:write"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "OAuth2ClientCredentials": []
          }
        ],
        "summary": "List journal entries",
        "tags": [
          "Journal Entries"
        ]
      }
    },
    "/v1/journal-entries/{id}": {
      "patch": {
        "description": "Partial update of a posted journal entry. Provide at least one of `reference`, `externalSystemId`.\n\n`reference` corrects the reference on a CUSTOMER_INVOICE / CUSTOMER_PAYMENT / SUPPLIER_INVOICE /\nSUPPLIER_PAYMENT entry and re-runs payment ↔ invoice matching. Use this when an entry was booked\nwith a wrong reference and therefore never matched.\n\n`externalSystemId` stores your own system's id for the entry. It is metadata: settable on any\njournal type regardless of match state, and never affects matching. It is not unique — several\nentries may share one id; filter `GET /journal-entries?externalSystemId=...` to list them.\n\n**Reference corrections apply to unmatched journal entries only.** A payment that settles an invoice\ncarries amounts derived against that invoice (currency and original exchange rate), and which\ninvoice a payment settled is part of the books — neither can be edited in place. Documents with\nsettlement activity are rejected with `409 JOURNAL_ENTRY_REFERENCE_UPDATE_ALREADY_MATCHED`.\n\n**Matched to the wrong journal entry?** Reverse the entry with `POST /api/v1/journal-entries/reverse`\nand re-book it with the correct reference via `POST /api/v2/journal-entries`. The reversal keeps\nthe audit trail intact, and the re-booked entry derives its settlement amounts against the\ncorrect invoice.\n\nPayments: the journal entry must be UNMATCHED (not linked to an invoice). After the update the corrected\nreference is looked up against the counterparty's invoices — on a hit the payment is linked and the\ninvoice status recomputed (OPEN → PARTIALLY_PAID / PAID). On a miss the payment stays unmatched and\ncan be corrected again.\n\nInvoices: the invoice must have no settlement activity (no applied payments or linked credit notes).\nThe invoice number is updated and any payments already waiting on the corrected number are matched\nin the same transaction. A 409 is returned when the invoice is already settled against, or when\nanother invoice for the same counterparty already uses the new number.\n\nReference corrections on reversed entries and other journal types are rejected with 400.",
        "operationId": "PublicJournalEntriesController_updateJournalEntry_v1",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "description": "Journal entry ID",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateJournalEntryRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Journal entry updated.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UpdateJournalEntryResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 400
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Bad Request"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 401
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions - API key missing required scopes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 403
                    },
                    "code": {
                      "type": "string",
                      "example": "INSUFFICIENT_PERMISSIONS"
                    },
                    "details": {
                      "type": "object",
                      "properties": {
                        "reason": {
                          "type": "string",
                          "example": "api_key_missing_required_scope"
                        },
                        "requiredScopes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "example": [
                            "usage:write"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "OAuth2ClientCredentials": []
          }
        ],
        "summary": "Update a journal entry — correct the reference and/or set your external system id",
        "tags": [
          "Journal Entries"
        ]
      },
      "get": {
        "description": "Retrieves a journal entry by its ID.",
        "operationId": "PublicJournalEntriesController_getJournalEntry_v1",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "description": "Journal entry ID (UUID)",
            "schema": {
              "example": "550e8400-e29b-41d4-a716-446655440000",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Journal entry retrieved successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JournalEntryResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 400
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Bad Request"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 401
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions - API key missing required scopes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 403
                    },
                    "code": {
                      "type": "string",
                      "example": "INSUFFICIENT_PERMISSIONS"
                    },
                    "details": {
                      "type": "object",
                      "properties": {
                        "reason": {
                          "type": "string",
                          "example": "api_key_missing_required_scope"
                        },
                        "requiredScopes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "example": [
                            "usage:write"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "OAuth2ClientCredentials": []
          }
        ],
        "summary": "Get a single journal entry",
        "tags": [
          "Journal Entries"
        ]
      }
    },
    "/v1/journal-entries/{id}/attachments": {
      "get": {
        "description": "Retrieves all attachments/documents associated with a journal entry.",
        "operationId": "PublicJournalEntriesController_getJournalEntryAttachments_v1",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "description": "Journal entry ID (UUID)",
            "schema": {
              "example": "550e8400-e29b-41d4-a716-446655440000",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Attachments retrieved successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JournalEntryAttachmentsListResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 400
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Bad Request"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 401
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions - API key missing required scopes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 403
                    },
                    "code": {
                      "type": "string",
                      "example": "INSUFFICIENT_PERMISSIONS"
                    },
                    "details": {
                      "type": "object",
                      "properties": {
                        "reason": {
                          "type": "string",
                          "example": "api_key_missing_required_scope"
                        },
                        "requiredScopes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "example": [
                            "usage:write"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "OAuth2ClientCredentials": []
          }
        ],
        "summary": "Get attachments for a journal entry",
        "tags": [
          "Journal Entries"
        ]
      }
    },
    "/v1/journal-entries/batch-reverse": {
      "post": {
        "description": "Atomically reverses 1–100 posted journal entries in a single transaction.\nThe original entries are left untouched; both originals and reversals remain visible\nin ledger / aging / balance reports so the audit trail is preserved.\n\nDate handling: when `reversalDate` is omitted, each reversal is dated to its own\noriginal entry so the original/reversal pair lands in the same posting period. When\n`reversalDate` is supplied it applies to every reversal in the batch.\n\nThe posting period for every reversal date must be open. Duplicate IDs in the request\nare de-duplicated. If any reversal fails (closed period, ineligible source entry, etc.)\nthe whole batch rolls back and no reversals are persisted.",
        "operationId": "PublicJournalEntriesController_batchReverseJournalEntries_v1",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/BatchReverseJournalEntriesRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Reversals posted successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BatchReverseJournalEntriesResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 400
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Bad Request"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 401
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions - API key missing required scopes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 403
                    },
                    "code": {
                      "type": "string",
                      "example": "INSUFFICIENT_PERMISSIONS"
                    },
                    "details": {
                      "type": "object",
                      "properties": {
                        "reason": {
                          "type": "string",
                          "example": "api_key_missing_required_scope"
                        },
                        "requiredScopes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "example": [
                            "usage:write"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "OAuth2ClientCredentials": []
          }
        ],
        "summary": "Reverse posted journal entries in batch",
        "tags": [
          "Journal Entries"
        ]
      }
    },
    "/v1/journal-entries/reverse": {
      "post": {
        "description": "Reverses a single posted journal entry. Mirrors the gated app's \"Reverse only,\npost immediately\" correction option — a new POSTED journal entry is created with the\noriginal's Dr/Cr lines flipped. The original entry is left untouched; both entries\nremain visible in ledger / aging / balance reports so the audit trail is preserved.\n\nDate handling: when `reversalDate` is omitted, the reversal is dated to the original\nentry so the pair lands in the same posting period. The posting period for the\nresolved date must be open.\n\nEligibility: the source entry must be POSTED and not already part of a correction\nchain that disallows further reversal. The endpoint rejects ineligible entries with 400.",
        "operationId": "PublicJournalEntriesController_reverseJournalEntry_v1",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ReverseJournalEntryRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Reversal posted successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ReverseJournalEntryResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 400
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Bad Request"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 401
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions - API key missing required scopes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 403
                    },
                    "code": {
                      "type": "string",
                      "example": "INSUFFICIENT_PERMISSIONS"
                    },
                    "details": {
                      "type": "object",
                      "properties": {
                        "reason": {
                          "type": "string",
                          "example": "api_key_missing_required_scope"
                        },
                        "requiredScopes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "example": [
                            "usage:write"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "OAuth2ClientCredentials": []
          }
        ],
        "summary": "Reverse a posted journal entry",
        "tags": [
          "Journal Entries"
        ]
      }
    },
    "/v1/mcp/developer": {
      "post": {
        "tags": [
          "MCP"
        ],
        "summary": "LedgerBee Developer MCP Server",
        "description": "Anonymous MCP endpoint for AI agents — no account required (any bearer token is accepted and grants nothing). Serves only the `read_development_docs` tool, which lists links to the LedgerBee developer docs (https://docs.ledgerbee.com). The tenant-scoped servers (`POST /v1/mcp`, `POST /v1/mcp/c/{appCompanyId}`) require an OAuth grant with MCP scopes — see the MCP guide.",
        "operationId": "postV1McpDeveloper",
        "x-mcp-server": {
          "name": "ledgerbee-developer-mcp",
          "tools": [
            {
              "name": "read_development_docs",
              "description": "List links to the LedgerBee developer documentation"
            }
          ]
        },
        "responses": {
          "200": {
            "description": "MCP JSON-RPC response"
          }
        }
      }
    },
    "/v1/meters/{meterId}/subscriptions": {
      "get": {
        "description": "\nLooks up a meter by its UUID and returns the subscriptions (with their\nproducts) that can report usage to it — i.e. subscriptions holding a product\nwhose price is linked to this meter. Paused subscriptions are excluded.\n\nReturns an empty `subscriptions` array when no product price uses the meter.\nResponds `404` with code `METER_NOT_FOUND` if the meter does not exist in\nyour company, and `403` with code `LICENSE.REQUIRED` if your company lacks\nthe Metered Products or Subscription license.\n\n## Required Scope\n\n- `meter-report`\n    ",
        "operationId": "PublicMeterController_getMeterSubscriptionsById_v1",
        "parameters": [
          {
            "name": "meterId",
            "required": true,
            "in": "path",
            "description": "The unique identifier of the meter",
            "schema": {
              "example": "550e8400-e29b-41d4-a716-446655440000",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Subscriptions and products that can report usage to this meter",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MeterSubscriptionsResponseDTO"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 400
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Bad Request"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 401
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions - API key missing required scopes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 403
                    },
                    "code": {
                      "type": "string",
                      "example": "INSUFFICIENT_PERMISSIONS"
                    },
                    "details": {
                      "type": "object",
                      "properties": {
                        "reason": {
                          "type": "string",
                          "example": "api_key_missing_required_scope"
                        },
                        "requiredScopes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "example": [
                            "usage:write"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "OAuth2ClientCredentials": []
          }
        ],
        "summary": "List meter subscriptions by ID",
        "tags": [
          "Meters"
        ]
      }
    },
    "/v1/meters/report": {
      "post": {
        "tags": [
          "Meters"
        ],
        "summary": "Report usage",
        "description": "\nReports a usage event to a meter for metered subscription billing. Ingestion\nis asynchronous: a successful report returns `202` with `status: queued`\nand a `requestId` — the event is not yet visible the moment the call\nreturns.\n\nThe `Idempotency-Key` header is required (`400` when missing). Replaying a\nrequest with the same key returns `200` with `status: duplicate` and the\nevent is not ingested twice, so retries are always safe.\n\nUse the meter-subscriptions endpoints to discover which subscriptions and\nproducts can report usage to a given meter.\n\n## Required Scope\n\n- `meter-report`\n      ",
        "operationId": "post_v1_meters_report",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-idempotency-key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Idempotency key to deduplicate submissions"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UsageReportRequestDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Duplicate request detected",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "status": {
                      "type": "string",
                      "example": "duplicate"
                    },
                    "idempotencyKey": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "202": {
            "description": "Queued for ingestion",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "status": {
                      "type": "string",
                      "example": "queued"
                    },
                    "requestId": {
                      "type": "string"
                    },
                    "idempotencyKey": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "message"
                  ],
                  "properties": {
                    "message": {
                      "type": "string",
                      "example": "Meter not found"
                    },
                    "code": {
                      "type": "string",
                      "example": "METER_NOT_FOUND"
                    },
                    "details": {
                      "type": "object",
                      "additionalProperties": true
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "message"
                  ],
                  "properties": {
                    "message": {
                      "type": "string",
                      "example": "Meter not found"
                    },
                    "code": {
                      "type": "string",
                      "example": "METER_NOT_FOUND"
                    },
                    "details": {
                      "type": "object",
                      "additionalProperties": true
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions - API key missing required scopes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "message"
                  ],
                  "properties": {
                    "message": {
                      "type": "string",
                      "example": "Meter not found"
                    },
                    "code": {
                      "type": "string",
                      "example": "METER_NOT_FOUND"
                    },
                    "details": {
                      "type": "object",
                      "additionalProperties": true
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Resource not found",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "message"
                  ],
                  "properties": {
                    "message": {
                      "type": "string",
                      "example": "Meter not found"
                    },
                    "code": {
                      "type": "string",
                      "example": "METER_NOT_FOUND"
                    },
                    "details": {
                      "type": "object",
                      "additionalProperties": true
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "Conflict or invalid state for request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "message"
                  ],
                  "properties": {
                    "message": {
                      "type": "string",
                      "example": "Meter not found"
                    },
                    "code": {
                      "type": "string",
                      "example": "METER_NOT_FOUND"
                    },
                    "details": {
                      "type": "object",
                      "additionalProperties": true
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "message"
                  ],
                  "properties": {
                    "message": {
                      "type": "string",
                      "example": "Meter not found"
                    },
                    "code": {
                      "type": "string",
                      "example": "METER_NOT_FOUND"
                    },
                    "details": {
                      "type": "object",
                      "additionalProperties": true
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/meters/subscriptions": {
      "get": {
        "description": "\nLooks up a meter by its name (`?meterName=`) and returns the subscriptions\n(with their products) that can report usage to it — useful when your\nintegration knows the meter's name (e.g. `api_calls`) but not its UUID.\nPaused subscriptions are excluded.\n\nReturns an empty `subscriptions` array when no product price uses the meter.\nResponds `400` with code `METER_IDENTIFIER_REQUIRED` when `meterName` is\nmissing, `404` with code `METER_NOT_FOUND` if no meter has that name in\nyour company, and `403` with code `LICENSE.REQUIRED` if your company lacks\nthe Metered Products or Subscription license.\n\n## Required Scope\n\n- `meter-report`\n    ",
        "operationId": "PublicMeterController_getMeterSubscriptionsByName_v1",
        "parameters": [
          {
            "name": "meterName",
            "required": true,
            "in": "query",
            "description": "The name of the meter to look up",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Subscriptions and products that can report usage to this meter (lookup by name)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MeterSubscriptionsResponseDTO"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 400
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Bad Request"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 401
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions - API key missing required scopes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 403
                    },
                    "code": {
                      "type": "string",
                      "example": "INSUFFICIENT_PERMISSIONS"
                    },
                    "details": {
                      "type": "object",
                      "properties": {
                        "reason": {
                          "type": "string",
                          "example": "api_key_missing_required_scope"
                        },
                        "requiredScopes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "example": [
                            "usage:write"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "OAuth2ClientCredentials": []
          }
        ],
        "summary": "List meter subscriptions by name",
        "tags": [
          "Meters"
        ]
      }
    },
    "/v1/order-confirmations": {
      "get": {
        "description": "\nReturns a paginated list of order confirmations.\n\n## Filters\n\n| Parameter | Description |\n|-----------|-------------|\n| status | Display status: `draft`, `sent`, `converted`. Derived statuses are resolved server-side. |\n| customerId | Filter to one customer. |\n| page / limit | Pagination (defaults: page 1, limit 25, max limit 100). |\n| sortBy / sortOrder | Sort field (e.g. `date`, `documentNumber`, `amount`, `status`) and direction. Defaults to newest first. |\n    ",
        "operationId": "PublicOrderConfirmationsController_list_v1",
        "parameters": [
          {
            "name": "page",
            "required": false,
            "in": "query",
            "description": "Page number (1-indexed)",
            "schema": {
              "minimum": 1,
              "default": 1,
              "example": 1,
              "type": "number"
            }
          },
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "description": "Items per page",
            "schema": {
              "minimum": 1,
              "maximum": 100,
              "default": 25,
              "example": 25,
              "type": "number"
            }
          },
          {
            "name": "status",
            "required": false,
            "in": "query",
            "description": "Filter by display status (draft/sent/converted). Derived statuses are resolved server-side.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "customerId",
            "required": false,
            "in": "query",
            "description": "Filter by customer id",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "sortBy",
            "required": false,
            "in": "query",
            "description": "Sort field",
            "schema": {
              "example": "date",
              "type": "string"
            }
          },
          {
            "name": "sortOrder",
            "required": false,
            "in": "query",
            "description": "Sort order",
            "schema": {
              "type": "string",
              "enum": [
                "ASC",
                "DESC"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Paginated list of order confirmations",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicListOrderConfirmationsResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 400
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Bad Request"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 401
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions - API key missing required scopes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 403
                    },
                    "code": {
                      "type": "string",
                      "example": "INSUFFICIENT_PERMISSIONS"
                    },
                    "details": {
                      "type": "object",
                      "properties": {
                        "reason": {
                          "type": "string",
                          "example": "api_key_missing_required_scope"
                        },
                        "requiredScopes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "example": [
                            "usage:write"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "OAuth2ClientCredentials": []
          }
        ],
        "summary": "List order confirmations",
        "tags": [
          "Order Confirmations"
        ]
      },
      "post": {
        "description": "\nCreates a draft order confirmation.\n\n- The document number is **not** allocated here — it is assigned on send.\n- Totals (subtotal/vat/amount) are computed from the line items.\n    ",
        "operationId": "PublicOrderConfirmationsController_create_v1",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PublicCreateOrderConfirmation"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Order confirmation created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicOrderConfirmation"
                }
              }
            }
          },
          "400": {
            "description": "Validation error"
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 401
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions - API key missing required scopes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 403
                    },
                    "code": {
                      "type": "string",
                      "example": "INSUFFICIENT_PERMISSIONS"
                    },
                    "details": {
                      "type": "object",
                      "properties": {
                        "reason": {
                          "type": "string",
                          "example": "api_key_missing_required_scope"
                        },
                        "requiredScopes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "example": [
                            "usage:write"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "OAuth2ClientCredentials": []
          }
        ],
        "summary": "Create a draft order confirmation",
        "tags": [
          "Order Confirmations"
        ]
      }
    },
    "/v1/order-confirmations/{id}": {
      "get": {
        "description": "Returns a single order confirmation, including its line items.",
        "operationId": "PublicOrderConfirmationsController_findOne_v1",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "description": "The order confirmation id",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The order confirmation",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicOrderConfirmation"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 400
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Bad Request"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 401
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions - API key missing required scopes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 403
                    },
                    "code": {
                      "type": "string",
                      "example": "INSUFFICIENT_PERMISSIONS"
                    },
                    "details": {
                      "type": "object",
                      "properties": {
                        "reason": {
                          "type": "string",
                          "example": "api_key_missing_required_scope"
                        },
                        "requiredScopes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "example": [
                            "usage:write"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Order confirmation not found"
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "OAuth2ClientCredentials": []
          }
        ],
        "summary": "Get an order confirmation by id",
        "tags": [
          "Order Confirmations"
        ]
      },
      "patch": {
        "description": "\nReplaces the editable fields and line items of a draft document.\n\nLine items are replaced wholesale — send the full intended set. A converted\ndocument is read-only (`SALES_DOCUMENT_LOCKED_CONVERTED`).\n    ",
        "operationId": "PublicOrderConfirmationsController_update_v1",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "description": "The order confirmation id",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PublicUpdateOrderConfirmation"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Order confirmation updated",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicOrderConfirmation"
                }
              }
            }
          },
          "400": {
            "description": "Validation error, or document already converted (SALES_DOCUMENT_LOCKED_CONVERTED)."
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 401
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions - API key missing required scopes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 403
                    },
                    "code": {
                      "type": "string",
                      "example": "INSUFFICIENT_PERMISSIONS"
                    },
                    "details": {
                      "type": "object",
                      "properties": {
                        "reason": {
                          "type": "string",
                          "example": "api_key_missing_required_scope"
                        },
                        "requiredScopes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "example": [
                            "usage:write"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Order confirmation not found"
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "OAuth2ClientCredentials": []
          }
        ],
        "summary": "Update a draft order confirmation",
        "tags": [
          "Order Confirmations"
        ]
      }
    },
    "/v1/order-confirmations/{id}/convert": {
      "post": {
        "description": "\nConverts the order confirmation into an **invoice** (`target: \"invoice\"`).\n\nBy default the source document's fields and line items are copied verbatim. To\nreview and adjust the target before finalizing, supply an optional `document`\npayload — its fields override the copied values.\n\nA document converts only once. Re-converting fails with\n`SALES_DOCUMENT_ALREADY_CONVERTED_TO_INVOICE`.\n\nThe response identifies the produced invoice via `targetType` (\"invoice\") and\n`targetId`.\n    ",
        "operationId": "PublicOrderConfirmationsController_convert_v1",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "description": "The order confirmation id to convert",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PublicConvertOrderConfirmation"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Conversion result",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicConvertOrderConfirmationResult"
                }
              }
            }
          },
          "400": {
            "description": "Error codes: SALES_DOCUMENT_ALREADY_CONVERTED_TO_INVOICE."
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 401
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions - API key missing required scopes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 403
                    },
                    "code": {
                      "type": "string",
                      "example": "INSUFFICIENT_PERMISSIONS"
                    },
                    "details": {
                      "type": "object",
                      "properties": {
                        "reason": {
                          "type": "string",
                          "example": "api_key_missing_required_scope"
                        },
                        "requiredScopes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "example": [
                            "usage:write"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Order confirmation not found"
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "OAuth2ClientCredentials": []
          }
        ],
        "summary": "Convert an order confirmation into an invoice",
        "tags": [
          "Order Confirmations"
        ]
      }
    },
    "/v1/order-confirmations/{id}/pdf": {
      "get": {
        "description": "\nRenders and streams the document as a PDF (`application/pdf`).\n\nPass `?draft=true` to render an unfinalized \"draft\" watermark preview before\nthe document is sent.\n    ",
        "operationId": "PublicOrderConfirmationsController_getPdf_v1",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "description": "The order confirmation id",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "draft",
            "required": false,
            "in": "query",
            "description": "Render a draft-watermarked preview when \"true\".",
            "schema": {
              "type": "boolean"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "PDF binary stream"
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/pdf": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 400
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Bad Request"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/pdf": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 401
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions - API key missing required scopes",
            "content": {
              "application/pdf": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 403
                    },
                    "code": {
                      "type": "string",
                      "example": "INSUFFICIENT_PERMISSIONS"
                    },
                    "details": {
                      "type": "object",
                      "properties": {
                        "reason": {
                          "type": "string",
                          "example": "api_key_missing_required_scope"
                        },
                        "requiredScopes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "example": [
                            "usage:write"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Order confirmation not found"
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "OAuth2ClientCredentials": []
          }
        ],
        "summary": "Download an order confirmation as PDF",
        "tags": [
          "Order Confirmations"
        ]
      }
    },
    "/v1/order-confirmations/{id}/send": {
      "post": {
        "description": "\nSends the document. This allocates the document number (if not already set),\nrenders the PDF, optionally emails it, and marks the document **sent**.\n\n## Delivery\n\n- `deliveryType: \"Manual\"` (default) — allocates the number and marks sent\n  without emailing. Use this when you will deliver the PDF yourself\n  (download it via `GET /:id/pdf`).\n- `deliveryType: \"Email\"` — emails the rendered PDF. The recipient resolves\n  from `recipientEmail` (override), else the customer contact, else the\n  customer email. If none can be resolved the request fails with\n  `SALES_DOCUMENT_MISSING_RECIPIENT`.\n\nSproom / e-invoice does **not** apply to order confirmations — there is no legal\ne-invoice type for an order confirmation.\n\nA document that has already been converted is read-only and cannot be sent\n(`SALES_DOCUMENT_LOCKED_CONVERTED`).\n    ",
        "operationId": "PublicOrderConfirmationsController_send_v1",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "description": "The order confirmation id",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PublicSendOrderConfirmation"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Order confirmation sent",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicOrderConfirmation"
                }
              }
            }
          },
          "400": {
            "description": "Error codes: SALES_DOCUMENT_MISSING_RECIPIENT (Email delivery with no resolvable address), SALES_DOCUMENT_LOCKED_CONVERTED (document already converted)."
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 401
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions - API key missing required scopes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 403
                    },
                    "code": {
                      "type": "string",
                      "example": "INSUFFICIENT_PERMISSIONS"
                    },
                    "details": {
                      "type": "object",
                      "properties": {
                        "reason": {
                          "type": "string",
                          "example": "api_key_missing_required_scope"
                        },
                        "requiredScopes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "example": [
                            "usage:write"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Order confirmation not found"
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "OAuth2ClientCredentials": []
          }
        ],
        "summary": "Send an order confirmation",
        "tags": [
          "Order Confirmations"
        ]
      }
    },
    "/v1/portal-sso/handoff/mint": {
      "post": {
        "description": "Back-channel single sign-on into the LedgerBee customer portal. A partner's backend calls this to mint an opaque, single-use, 60-second reference for a customer-portal user; the user's browser then redeems that reference at the portal-API host (<tenant>.portal-api.ledgerbee.com/api/auth/sso/handoff/redeem?ref=<ref>) to establish a portal session — NOT the portal SPA host (<tenant>.portal.ledgerbee.com), which serves the static app and silently ignores the ref. The reference carries no identity — it is a server-resolved pointer. The tenant is resolved from the API key, never the request body, and every asserted organization is validated against that tenant. At least one membership must be asserted: the portal user, organization, and membership are all created at redeem from the asserted customers (no prior provision call is required), and a handoff with no membership cannot establish a session and is rejected with a 400. Requires the portal-sso-mint scope.",
        "operationId": "PublicSsoHandoffController_mint_v1",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PublicHandoffMintRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicHandoffMintResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 400
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Bad Request"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 401
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions - API key missing required scopes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 403
                    },
                    "code": {
                      "type": "string",
                      "example": "INSUFFICIENT_PERMISSIONS"
                    },
                    "details": {
                      "type": "object",
                      "properties": {
                        "reason": {
                          "type": "string",
                          "example": "api_key_missing_required_scope"
                        },
                        "requiredScopes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "example": [
                            "usage:write"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "OAuth2ClientCredentials": []
          }
        ],
        "summary": "Mint a customer-portal SSO handoff reference",
        "tags": [
          "Portal SSO"
        ]
      }
    },
    "/v1/portal-sso/provision": {
      "post": {
        "description": "Ensures a customer (referenced by `customerId`, or upserted idempotently by `customer.customerNumber` within the API key's tenant), bootstraps its portal organization, and grants a credential-less portal user an active membership — so a net-new end-customer can sign in via SSO/handoff. No invitation email is sent. Set mintHandoff=true (and carry the portal-sso-mint scope) to also receive a one-time handoff reference in the response for a single round-trip 'Go to portal'. Set mintCheckoutBindToken=true (also requires the portal-sso-mint scope) to receive a one-time checkout-bind reference the partner embeds so the embedded checkout subscribes directly against this customer. Requires the portal-provision scope.",
        "operationId": "PublicCustomerProvisionController_provisionCustomer_v1",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PublicProvisionCustomerRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicProvisionCustomerResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 400
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Bad Request"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 401
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions - API key missing required scopes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 403
                    },
                    "code": {
                      "type": "string",
                      "example": "INSUFFICIENT_PERMISSIONS"
                    },
                    "details": {
                      "type": "object",
                      "properties": {
                        "reason": {
                          "type": "string",
                          "example": "api_key_missing_required_scope"
                        },
                        "requiredScopes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "example": [
                            "usage:write"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "OAuth2ClientCredentials": []
          }
        ],
        "summary": "Provision a customer + grant portal access (partner JIT provisioning)",
        "tags": [
          "Portal SSO"
        ]
      }
    },
    "/v1/portal-sso/sessions/revoke": {
      "post": {
        "description": "Immediately invalidates every active portal session of the partner-provisioned user (identified by the same `sub` used at mint), forcing re-authentication on their next request. Use for proactive offboarding — it tightens the residual window from the session TTL to immediate. Deprovisioning at the OP is what then prevents re-login. Requires the portal-sso-mint scope.",
        "operationId": "PublicSsoRevokeController_revokeSessions_v1",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PublicRevokeSessionsRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicRevokeSessionsResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 400
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Bad Request"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 401
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions - API key missing required scopes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 403
                    },
                    "code": {
                      "type": "string",
                      "example": "INSUFFICIENT_PERMISSIONS"
                    },
                    "details": {
                      "type": "object",
                      "properties": {
                        "reason": {
                          "type": "string",
                          "example": "api_key_missing_required_scope"
                        },
                        "requiredScopes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "example": [
                            "usage:write"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "OAuth2ClientCredentials": []
          }
        ],
        "summary": "Revoke (force-refresh) a user's customer-portal sessions",
        "tags": [
          "Portal SSO"
        ]
      }
    },
    "/v1/portal/plans": {
      "get": {
        "description": "Returns every ACTIVE plan with a PUBLISHED version in the API key's tenant, projected as its canonical native card and ordered by display order. This is the integrator's FULL catalogue — it does NOT run the per-buyer rule engine, does NOT filter by any plan-routing visibility rule, and mints NO token. Use it to read all your plans (e.g. to build pricing pages), as opposed to `resolve`, which returns only the subset a specific buyer matches. Requires the portal-catalog-read scope.",
        "operationId": "PublicPortalPlansController_listPlans_v1",
        "parameters": [
          {
            "name": "language",
            "required": false,
            "in": "query",
            "description": "Language the resolved cards are localized to. Defaults to `en`.",
            "schema": {
              "example": "en",
              "type": "string",
              "enum": [
                "en",
                "da"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicPortalPlansListResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 400
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Bad Request"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 401
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions - API key missing required scopes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 403
                    },
                    "code": {
                      "type": "string",
                      "example": "INSUFFICIENT_PERMISSIONS"
                    },
                    "details": {
                      "type": "object",
                      "properties": {
                        "reason": {
                          "type": "string",
                          "example": "api_key_missing_required_scope"
                        },
                        "requiredScopes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "example": [
                            "usage:write"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "OAuth2ClientCredentials": []
          }
        ],
        "summary": "List the full plan catalogue",
        "tags": [
          "Portal Plans"
        ]
      }
    },
    "/v1/portal/plans/{planId}": {
      "get": {
        "description": "Returns a single plan by its id, projected as its canonical native card — the integrator's by-id read. Does NOT run the rule engine and does NOT filter by visibility rules: every published plan of the tenant resolves here. Returns 404 PORTAL_PLAN_NOT_FOUND only when the plan id is unknown to the tenant or has no published version. Requires the portal-catalog-read scope.",
        "operationId": "PublicPortalPlansController_getPlan_v1",
        "parameters": [
          {
            "name": "planId",
            "required": true,
            "in": "path",
            "description": "The plan id (uuid).",
            "schema": {
              "example": "550e8400-e29b-41d4-a716-446655440100",
              "type": "string"
            }
          },
          {
            "name": "language",
            "required": false,
            "in": "query",
            "description": "Language the resolved cards are localized to. Defaults to `en`.",
            "schema": {
              "example": "en",
              "type": "string",
              "enum": [
                "en",
                "da"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicPortalPlanResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 400
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Bad Request"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 401
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions - API key missing required scopes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 403
                    },
                    "code": {
                      "type": "string",
                      "example": "INSUFFICIENT_PERMISSIONS"
                    },
                    "details": {
                      "type": "object",
                      "properties": {
                        "reason": {
                          "type": "string",
                          "example": "api_key_missing_required_scope"
                        },
                        "requiredScopes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "example": [
                            "usage:write"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "OAuth2ClientCredentials": []
          }
        ],
        "summary": "Get one plan by id",
        "tags": [
          "Portal Plans"
        ]
      }
    },
    "/v1/portal/plans/resolve": {
      "post": {
        "description": "Runs the plan-routing rule engine for the buyer identified by `customerId` (or the no-customer-yet `countryCode`/`customerType` hints) within the API key's tenant, and returns the plans that buyer can SEE and CHECK OUT — including non-public (gated) plans the buyer matches — plus a reusable, read-only load-time catalog token. The partner returns the token to each embed iframe (via its `fetchCatalogToken` provider) to authorize the by-id pricing-card / checkout-document reads. Does NOT consult allowSelfSignup and never publishes to the CDN. Requires the portal-catalog-read scope.",
        "operationId": "PublicPortalPlansController_resolve_v1",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PublicResolvePortalPlansRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicResolvePortalPlansResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 400
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Bad Request"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 401
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions - API key missing required scopes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 403
                    },
                    "code": {
                      "type": "string",
                      "example": "INSUFFICIENT_PERMISSIONS"
                    },
                    "details": {
                      "type": "object",
                      "properties": {
                        "reason": {
                          "type": "string",
                          "example": "api_key_missing_required_scope"
                        },
                        "requiredScopes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "example": [
                            "usage:write"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "OAuth2ClientCredentials": []
          }
        ],
        "summary": "Resolve the gated pricing catalogue for an identified buyer (partner display)",
        "tags": [
          "Portal Plans"
        ]
      }
    },
    "/v1/product-groups": {
      "get": {
        "description": "\nRetrieves a paginated list of your company's product groups. Each list\nitem includes the number of products in the group.\n\nPass `?search=` to prefix-match on group name or number.\n\n## Required Scope\n\n- `products-read`\n    ",
        "operationId": "PublicProductGroupsController_list_v1",
        "parameters": [
          {
            "name": "page",
            "required": false,
            "in": "query",
            "description": "Page number (1-indexed)",
            "schema": {
              "minimum": 1,
              "default": 1,
              "type": "number"
            }
          },
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "description": "Maximum number of items per page",
            "schema": {
              "minimum": 1,
              "maximum": 100,
              "default": 25,
              "type": "number"
            }
          },
          {
            "name": "search",
            "required": false,
            "in": "query",
            "description": "Prefix search on name or number",
            "schema": {
              "example": "Office",
              "type": "string"
            }
          },
          {
            "name": "sortBy",
            "required": false,
            "in": "query",
            "description": "Field to sort by",
            "schema": {
              "default": "createdAt",
              "type": "string",
              "enum": [
                "number",
                "name",
                "createdAt"
              ]
            }
          },
          {
            "name": "sortOrder",
            "required": false,
            "in": "query",
            "description": "Sort direction",
            "schema": {
              "default": "DESC",
              "type": "string",
              "enum": [
                "ASC",
                "DESC"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Paginated list of product groups for the company",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ListProductGroupsResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 400
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Bad Request"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 401
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions - API key missing required scopes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 403
                    },
                    "code": {
                      "type": "string",
                      "example": "INSUFFICIENT_PERMISSIONS"
                    },
                    "details": {
                      "type": "object",
                      "properties": {
                        "reason": {
                          "type": "string",
                          "example": "api_key_missing_required_scope"
                        },
                        "requiredScopes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "example": [
                            "usage:write"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "OAuth2ClientCredentials": []
          }
        ],
        "summary": "List product groups",
        "tags": [
          "Product Groups"
        ]
      },
      "post": {
        "description": "\nCreates a product group. A group maps its products to the ledger accounts\nused for domestic, EU (Rubric B), abroad (Rubric C), and\ndomestic-without-VAT sales.\n\n## Required Scope\n\n- `products-write`\n    ",
        "operationId": "PublicProductGroupsController_create_v1",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateProductGroupRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Product group created successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProductGroupResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 400
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Bad Request"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 401
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions - API key missing required scopes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 403
                    },
                    "code": {
                      "type": "string",
                      "example": "INSUFFICIENT_PERMISSIONS"
                    },
                    "details": {
                      "type": "object",
                      "properties": {
                        "reason": {
                          "type": "string",
                          "example": "api_key_missing_required_scope"
                        },
                        "requiredScopes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "example": [
                            "usage:write"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "OAuth2ClientCredentials": []
          }
        ],
        "summary": "Create a product group",
        "tags": [
          "Product Groups"
        ]
      }
    },
    "/v1/product-groups/{productGroupId}": {
      "get": {
        "description": "\nReturns a single product group, including its sales-account mappings\n(domestic, EU, abroad, and domestic-without-VAT).\n\n## Required Scope\n\n- `products-read`\n    ",
        "operationId": "PublicProductGroupsController_getById_v1",
        "parameters": [
          {
            "name": "productGroupId",
            "required": true,
            "in": "path",
            "description": "Product group ID",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Product group details",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProductGroupResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 400
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Bad Request"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 401
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions - API key missing required scopes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 403
                    },
                    "code": {
                      "type": "string",
                      "example": "INSUFFICIENT_PERMISSIONS"
                    },
                    "details": {
                      "type": "object",
                      "properties": {
                        "reason": {
                          "type": "string",
                          "example": "api_key_missing_required_scope"
                        },
                        "requiredScopes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "example": [
                            "usage:write"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "OAuth2ClientCredentials": []
          }
        ],
        "summary": "Get a product group",
        "tags": [
          "Product Groups"
        ]
      },
      "patch": {
        "description": "\nUpdates a product group. Only the fields provided in the request are\nchanged.\n\n## Required Scope\n\n- `products-write`\n    ",
        "operationId": "PublicProductGroupsController_update_v1",
        "parameters": [
          {
            "name": "productGroupId",
            "required": true,
            "in": "path",
            "description": "Product group ID",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateProductGroupRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Product group updated successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProductGroupResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 400
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Bad Request"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 401
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions - API key missing required scopes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 403
                    },
                    "code": {
                      "type": "string",
                      "example": "INSUFFICIENT_PERMISSIONS"
                    },
                    "details": {
                      "type": "object",
                      "properties": {
                        "reason": {
                          "type": "string",
                          "example": "api_key_missing_required_scope"
                        },
                        "requiredScopes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "example": [
                            "usage:write"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "OAuth2ClientCredentials": []
          }
        ],
        "summary": "Update a product group",
        "tags": [
          "Product Groups"
        ]
      },
      "delete": {
        "description": "\nDeletes a product group.\n\n## Required Scope\n\n- `products-write`\n    ",
        "operationId": "PublicProductGroupsController_remove_v1",
        "parameters": [
          {
            "name": "productGroupId",
            "required": true,
            "in": "path",
            "description": "Product group ID",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Product group deleted successfully"
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 400
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Bad Request"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 401
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions - API key missing required scopes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 403
                    },
                    "code": {
                      "type": "string",
                      "example": "INSUFFICIENT_PERMISSIONS"
                    },
                    "details": {
                      "type": "object",
                      "properties": {
                        "reason": {
                          "type": "string",
                          "example": "api_key_missing_required_scope"
                        },
                        "requiredScopes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "example": [
                            "usage:write"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "OAuth2ClientCredentials": []
          }
        ],
        "summary": "Delete a product group",
        "tags": [
          "Product Groups"
        ]
      }
    },
    "/v1/product-prices": {
      "post": {
        "description": "\nCreates a price on a product (`productId`). `currency` defaults to the\ncompany default currency when omitted.\n\n## Required Scope\n\n- `products-write`\n    ",
        "operationId": "PublicProductPricesController_create_v1",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateProductPriceRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Product price created successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProductPriceResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 400
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Bad Request"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 401
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions - API key missing required scopes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 403
                    },
                    "code": {
                      "type": "string",
                      "example": "INSUFFICIENT_PERMISSIONS"
                    },
                    "details": {
                      "type": "object",
                      "properties": {
                        "reason": {
                          "type": "string",
                          "example": "api_key_missing_required_scope"
                        },
                        "requiredScopes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "example": [
                            "usage:write"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "OAuth2ClientCredentials": []
          }
        ],
        "summary": "Create a product price",
        "tags": [
          "Product Prices"
        ]
      }
    },
    "/v1/product-prices/{priceId}": {
      "get": {
        "description": "\nReturns a single product price.\n\nPass `?currency=` to get the amount in another ISO 4217 currency — the\namount is converted on the fly when no price-history entry exists for that\ncurrency.\n\n## Required Scope\n\n- `products-read`\n    ",
        "operationId": "PublicProductPricesController_getById_v1",
        "parameters": [
          {
            "name": "priceId",
            "required": true,
            "in": "path",
            "description": "Product price ID",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "currency",
            "required": false,
            "in": "query",
            "description": "ISO 4217 currency to return the amount in. Converts on the fly when no history entry exists.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Product price details",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProductPriceResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 400
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Bad Request"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 401
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions - API key missing required scopes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 403
                    },
                    "code": {
                      "type": "string",
                      "example": "INSUFFICIENT_PERMISSIONS"
                    },
                    "details": {
                      "type": "object",
                      "properties": {
                        "reason": {
                          "type": "string",
                          "example": "api_key_missing_required_scope"
                        },
                        "requiredScopes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "example": [
                            "usage:write"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "OAuth2ClientCredentials": []
          }
        ],
        "summary": "Get a product price",
        "tags": [
          "Product Prices"
        ]
      },
      "patch": {
        "description": "\nUpdates a product price. Only the fields provided in the request are\nchanged.\n\n## Required Scope\n\n- `products-write`\n    ",
        "operationId": "PublicProductPricesController_update_v1",
        "parameters": [
          {
            "name": "priceId",
            "required": true,
            "in": "path",
            "description": "Product price ID",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateProductPriceRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Product price updated successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProductPriceResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 400
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Bad Request"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 401
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions - API key missing required scopes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 403
                    },
                    "code": {
                      "type": "string",
                      "example": "INSUFFICIENT_PERMISSIONS"
                    },
                    "details": {
                      "type": "object",
                      "properties": {
                        "reason": {
                          "type": "string",
                          "example": "api_key_missing_required_scope"
                        },
                        "requiredScopes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "example": [
                            "usage:write"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "OAuth2ClientCredentials": []
          }
        ],
        "summary": "Update a product price",
        "tags": [
          "Product Prices"
        ]
      },
      "delete": {
        "description": "\nDeletes a product price. A price that is locked (in use by a subscription\nor invoice) cannot be deleted.\n\n## Required Scope\n\n- `products-write`\n    ",
        "operationId": "PublicProductPricesController_remove_v1",
        "parameters": [
          {
            "name": "priceId",
            "required": true,
            "in": "path",
            "description": "Product price ID",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Product price deleted successfully"
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 400
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Bad Request"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 401
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions - API key missing required scopes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 403
                    },
                    "code": {
                      "type": "string",
                      "example": "INSUFFICIENT_PERMISSIONS"
                    },
                    "details": {
                      "type": "object",
                      "properties": {
                        "reason": {
                          "type": "string",
                          "example": "api_key_missing_required_scope"
                        },
                        "requiredScopes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "example": [
                            "usage:write"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "OAuth2ClientCredentials": []
          }
        ],
        "summary": "Delete a product price",
        "tags": [
          "Product Prices"
        ]
      }
    },
    "/v1/product-prices/{priceId}/activate": {
      "post": {
        "description": "\nSets the price's status to `active`. Returns the price's new state.\n\n## Required Scope\n\n- `products-write`\n    ",
        "operationId": "PublicProductPricesController_activate_v1",
        "parameters": [
          {
            "name": "priceId",
            "required": true,
            "in": "path",
            "description": "Product price ID",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Product price activated",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProductPriceResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 400
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Bad Request"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 401
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions - API key missing required scopes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 403
                    },
                    "code": {
                      "type": "string",
                      "example": "INSUFFICIENT_PERMISSIONS"
                    },
                    "details": {
                      "type": "object",
                      "properties": {
                        "reason": {
                          "type": "string",
                          "example": "api_key_missing_required_scope"
                        },
                        "requiredScopes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "example": [
                            "usage:write"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "OAuth2ClientCredentials": []
          }
        ],
        "summary": "Activate a product price",
        "tags": [
          "Product Prices"
        ]
      }
    },
    "/v1/product-prices/{priceId}/archive": {
      "post": {
        "description": "\nSets the price's status to `archived`. Returns the price's new state.\n\n## Required Scope\n\n- `products-write`\n    ",
        "operationId": "PublicProductPricesController_archive_v1",
        "parameters": [
          {
            "name": "priceId",
            "required": true,
            "in": "path",
            "description": "Product price ID",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Product price archived",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProductPriceResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 400
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Bad Request"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 401
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions - API key missing required scopes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 403
                    },
                    "code": {
                      "type": "string",
                      "example": "INSUFFICIENT_PERMISSIONS"
                    },
                    "details": {
                      "type": "object",
                      "properties": {
                        "reason": {
                          "type": "string",
                          "example": "api_key_missing_required_scope"
                        },
                        "requiredScopes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "example": [
                            "usage:write"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "OAuth2ClientCredentials": []
          }
        ],
        "summary": "Archive a product price",
        "tags": [
          "Product Prices"
        ]
      }
    },
    "/v1/product-prices/{priceId}/disable": {
      "post": {
        "description": "\nSets the price's status to `inactive`. Returns the price's new state.\n\n## Required Scope\n\n- `products-write`\n    ",
        "operationId": "PublicProductPricesController_disable_v1",
        "parameters": [
          {
            "name": "priceId",
            "required": true,
            "in": "path",
            "description": "Product price ID",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Product price disabled (set to inactive)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProductPriceResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 400
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Bad Request"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 401
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions - API key missing required scopes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 403
                    },
                    "code": {
                      "type": "string",
                      "example": "INSUFFICIENT_PERMISSIONS"
                    },
                    "details": {
                      "type": "object",
                      "properties": {
                        "reason": {
                          "type": "string",
                          "example": "api_key_missing_required_scope"
                        },
                        "requiredScopes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "example": [
                            "usage:write"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "OAuth2ClientCredentials": []
          }
        ],
        "summary": "Disable a product price",
        "tags": [
          "Product Prices"
        ]
      }
    },
    "/v1/product-prices/{priceId}/set-default": {
      "post": {
        "description": "\nMakes this price the default price for its product. Returns the price's\nnew state.\n\n## Required Scope\n\n- `products-write`\n    ",
        "operationId": "PublicProductPricesController_setDefault_v1",
        "parameters": [
          {
            "name": "priceId",
            "required": true,
            "in": "path",
            "description": "Product price ID",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Product price set as the default for its product",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProductPriceResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 400
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Bad Request"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 401
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions - API key missing required scopes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 403
                    },
                    "code": {
                      "type": "string",
                      "example": "INSUFFICIENT_PERMISSIONS"
                    },
                    "details": {
                      "type": "object",
                      "properties": {
                        "reason": {
                          "type": "string",
                          "example": "api_key_missing_required_scope"
                        },
                        "requiredScopes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "example": [
                            "usage:write"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "OAuth2ClientCredentials": []
          }
        ],
        "summary": "Set a price as the product default",
        "tags": [
          "Product Prices"
        ]
      }
    },
    "/v1/products": {
      "get": {
        "description": "\nRetrieves a paginated list of your company's products, each including its\nprices.\n\nPass `?search=` to prefix-match on product name or number, or\n`?productGroupId=` to narrow the list to one product group.\n\n## Required Scope\n\n- `products-read`\n    ",
        "operationId": "PublicProductsController_list_v1",
        "parameters": [
          {
            "name": "page",
            "required": false,
            "in": "query",
            "description": "Page number (1-indexed)",
            "schema": {
              "minimum": 1,
              "default": 1,
              "type": "number"
            }
          },
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "description": "Maximum number of items per page",
            "schema": {
              "minimum": 1,
              "maximum": 100,
              "default": 25,
              "type": "number"
            }
          },
          {
            "name": "search",
            "required": false,
            "in": "query",
            "description": "Prefix search on name or number",
            "schema": {
              "example": "Hosting",
              "type": "string"
            }
          },
          {
            "name": "productGroupId",
            "required": false,
            "in": "query",
            "description": "Filter by product group ID",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "sortBy",
            "required": false,
            "in": "query",
            "description": "Field to sort by",
            "schema": {
              "default": "createdAt",
              "type": "string",
              "enum": [
                "productNumber",
                "name",
                "createdAt"
              ]
            }
          },
          {
            "name": "sortOrder",
            "required": false,
            "in": "query",
            "description": "Sort direction",
            "schema": {
              "default": "DESC",
              "type": "string",
              "enum": [
                "ASC",
                "DESC"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Paginated list of products for the company (each includes its prices)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ListProductsResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 400
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Bad Request"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 401
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions - API key missing required scopes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 403
                    },
                    "code": {
                      "type": "string",
                      "example": "INSUFFICIENT_PERMISSIONS"
                    },
                    "details": {
                      "type": "object",
                      "properties": {
                        "reason": {
                          "type": "string",
                          "example": "api_key_missing_required_scope"
                        },
                        "requiredScopes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "example": [
                            "usage:write"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "OAuth2ClientCredentials": []
          }
        ],
        "summary": "List products",
        "tags": [
          "Products"
        ]
      },
      "post": {
        "description": "\nCreates a product.\n\nAn optional initial price can be supplied inline — it is created,\nactivated, and set as the product's default price in the same transaction.\n\n## Required Scope\n\n- `products-write`\n    ",
        "operationId": "PublicProductsController_create_v1",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateProductRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Product created successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProductResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 400
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Bad Request"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 401
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions - API key missing required scopes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 403
                    },
                    "code": {
                      "type": "string",
                      "example": "INSUFFICIENT_PERMISSIONS"
                    },
                    "details": {
                      "type": "object",
                      "properties": {
                        "reason": {
                          "type": "string",
                          "example": "api_key_missing_required_scope"
                        },
                        "requiredScopes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "example": [
                            "usage:write"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "OAuth2ClientCredentials": []
          }
        ],
        "summary": "Create a product",
        "tags": [
          "Products"
        ]
      }
    },
    "/v1/products/{productId}": {
      "get": {
        "description": "\nReturns a single product, including its prices.\n\n## Required Scope\n\n- `products-read`\n    ",
        "operationId": "PublicProductsController_getById_v1",
        "parameters": [
          {
            "name": "productId",
            "required": true,
            "in": "path",
            "description": "Product ID",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Product details, including its prices",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProductResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 400
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Bad Request"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 401
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions - API key missing required scopes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 403
                    },
                    "code": {
                      "type": "string",
                      "example": "INSUFFICIENT_PERMISSIONS"
                    },
                    "details": {
                      "type": "object",
                      "properties": {
                        "reason": {
                          "type": "string",
                          "example": "api_key_missing_required_scope"
                        },
                        "requiredScopes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "example": [
                            "usage:write"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "OAuth2ClientCredentials": []
          }
        ],
        "summary": "Get a product",
        "tags": [
          "Products"
        ]
      },
      "patch": {
        "description": "\nUpdates a product. Only the fields provided in the request are changed.\n\n## Required Scope\n\n- `products-write`\n    ",
        "operationId": "PublicProductsController_update_v1",
        "parameters": [
          {
            "name": "productId",
            "required": true,
            "in": "path",
            "description": "Product ID",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateProductRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Product updated successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProductResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 400
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Bad Request"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 401
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions - API key missing required scopes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 403
                    },
                    "code": {
                      "type": "string",
                      "example": "INSUFFICIENT_PERMISSIONS"
                    },
                    "details": {
                      "type": "object",
                      "properties": {
                        "reason": {
                          "type": "string",
                          "example": "api_key_missing_required_scope"
                        },
                        "requiredScopes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "example": [
                            "usage:write"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "OAuth2ClientCredentials": []
          }
        ],
        "summary": "Update a product",
        "tags": [
          "Products"
        ]
      },
      "delete": {
        "description": "\nDeletes a product. A product that is locked (in use) cannot be deleted.\n\n## Required Scope\n\n- `products-write`\n    ",
        "operationId": "PublicProductsController_remove_v1",
        "parameters": [
          {
            "name": "productId",
            "required": true,
            "in": "path",
            "description": "Product ID",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Product deleted successfully"
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 400
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Bad Request"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 401
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions - API key missing required scopes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 403
                    },
                    "code": {
                      "type": "string",
                      "example": "INSUFFICIENT_PERMISSIONS"
                    },
                    "details": {
                      "type": "object",
                      "properties": {
                        "reason": {
                          "type": "string",
                          "example": "api_key_missing_required_scope"
                        },
                        "requiredScopes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "example": [
                            "usage:write"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "OAuth2ClientCredentials": []
          }
        ],
        "summary": "Delete a product",
        "tags": [
          "Products"
        ]
      }
    },
    "/v1/projects": {
      "get": {
        "description": "\nRetrieves all projects for your company. By default archived projects are excluded.\n\nUse `?includeArchived=true` to also return archived (read-only) projects.\n\n### Required scope\n`projects-read`\n    ",
        "operationId": "PublicProjectsController_listProjects_v1",
        "parameters": [
          {
            "name": "includeArchived",
            "required": false,
            "in": "query",
            "description": "Set to true to include archived projects. Defaults to false.",
            "schema": {
              "type": "boolean"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Project list returned successfully.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Project"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 400
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Bad Request"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 401
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions - API key missing required scopes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 403
                    },
                    "code": {
                      "type": "string",
                      "example": "INSUFFICIENT_PERMISSIONS"
                    },
                    "details": {
                      "type": "object",
                      "properties": {
                        "reason": {
                          "type": "string",
                          "example": "api_key_missing_required_scope"
                        },
                        "requiredScopes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "example": [
                            "usage:write"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "OAuth2ClientCredentials": []
          }
        ],
        "summary": "List all projects",
        "tags": [
          "Projects"
        ]
      },
      "put": {
        "description": "\nCreates or updates a project identified by `externalReference`.\n\nIf no project with the given `externalReference` exists it is created and the response is **201 Created**.\nIf a matching project already exists it is updated in place and the response is **200 OK**.\nEither way the response body is the project resource (same shape as create / get).\n\nConcurrent requests with the same `externalReference` are safe: a unique-constraint race is caught and resolved to an update.\n\n### Required scope\n`projects-write`\n\n### Error codes\n- `PROJECT_NOT_FOUND` — returned when the matched project is deleted mid-race (extremely rare).\n    ",
        "operationId": "PublicProjectsController_upsertProject_v1",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpsertProjectRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Existing project updated (matched by externalReference).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Project"
                }
              }
            }
          },
          "201": {
            "description": "Project created (no existing project matched the externalReference).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Project"
                }
              }
            }
          },
          "400": {
            "description": "Validation error."
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 401
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions - API key missing required scopes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 403
                    },
                    "code": {
                      "type": "string",
                      "example": "INSUFFICIENT_PERMISSIONS"
                    },
                    "details": {
                      "type": "object",
                      "properties": {
                        "reason": {
                          "type": "string",
                          "example": "api_key_missing_required_scope"
                        },
                        "requiredScopes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "example": [
                            "usage:write"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "OAuth2ClientCredentials": []
          }
        ],
        "summary": "Idempotent project upsert",
        "tags": [
          "Projects"
        ]
      },
      "post": {
        "description": "\nCreates a new project. The project is automatically provisioned with a default (catch-all) subproject.\n\n### Required scope\n`projects-write`\n\n### Error codes\n- `PROJECT_EXTERNAL_REFERENCE_CONFLICT` (409) — another project already has the same `externalReference`.\n    ",
        "operationId": "PublicProjectsController_createProject_v1",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateProjectRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Project created successfully.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Project"
                }
              }
            }
          },
          "400": {
            "description": "Validation error."
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 401
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions - API key missing required scopes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 403
                    },
                    "code": {
                      "type": "string",
                      "example": "INSUFFICIENT_PERMISSIONS"
                    },
                    "details": {
                      "type": "object",
                      "properties": {
                        "reason": {
                          "type": "string",
                          "example": "api_key_missing_required_scope"
                        },
                        "requiredScopes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "example": [
                            "usage:write"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "A project with the same externalReference already exists. Error code: PROJECT_EXTERNAL_REFERENCE_CONFLICT."
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "OAuth2ClientCredentials": []
          }
        ],
        "summary": "Create a project",
        "tags": [
          "Projects"
        ]
      }
    },
    "/v1/projects/{id}": {
      "get": {
        "description": "\nRetrieves a single project by its ID, including all subprojects.\n\n### Required scope\n`projects-read`\n\n### Error codes\n- `PROJECT_NOT_FOUND` (404) — no project with the given ID exists for your company.\n    ",
        "operationId": "PublicProjectsController_getProject_v1",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "description": "The project UUID.",
            "schema": {
              "example": "550e8400-e29b-41d4-a716-446655440000",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Project returned successfully.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Project"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 400
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Bad Request"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 401
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions - API key missing required scopes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 403
                    },
                    "code": {
                      "type": "string",
                      "example": "INSUFFICIENT_PERMISSIONS"
                    },
                    "details": {
                      "type": "object",
                      "properties": {
                        "reason": {
                          "type": "string",
                          "example": "api_key_missing_required_scope"
                        },
                        "requiredScopes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "example": [
                            "usage:write"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Project not found. Error code: PROJECT_NOT_FOUND."
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "OAuth2ClientCredentials": []
          }
        ],
        "summary": "Get a project",
        "tags": [
          "Projects"
        ]
      },
      "put": {
        "description": "\nUpdates a project. All fields are optional — only provided fields are changed.\nSend `null` for an optional field to clear it.\nTo archive a project set `isArchived: true`.\n\n### Required scope\n`projects-write`\n\n### Error codes\n- `PROJECT_NOT_FOUND` (404) — no project with the given ID exists for your company.\n- `PROJECT_EXTERNAL_REFERENCE_CONFLICT` (409) — another project already has the supplied `externalReference`.\n    ",
        "operationId": "PublicProjectsController_updateProject_v1",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "description": "The project UUID.",
            "schema": {
              "example": "550e8400-e29b-41d4-a716-446655440000",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateProjectRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Project updated successfully.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Project"
                }
              }
            }
          },
          "400": {
            "description": "Validation error."
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 401
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions - API key missing required scopes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 403
                    },
                    "code": {
                      "type": "string",
                      "example": "INSUFFICIENT_PERMISSIONS"
                    },
                    "details": {
                      "type": "object",
                      "properties": {
                        "reason": {
                          "type": "string",
                          "example": "api_key_missing_required_scope"
                        },
                        "requiredScopes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "example": [
                            "usage:write"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Project not found. Error code: PROJECT_NOT_FOUND."
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "OAuth2ClientCredentials": []
          }
        ],
        "summary": "Update a project",
        "tags": [
          "Projects"
        ]
      }
    },
    "/v1/projects/{id}/profit": {
      "get": {
        "description": "\nReturns aggregated profit/cost/revenue data for a project and its subprojects over a date range.\n\nWhen `from` and `to` are omitted the current accounting year is used as the default range.\n\n### Required scope\n`projects-read`\n\n### Error codes\n- `PROJECT_NOT_FOUND` (404) — no project with the given ID exists for your company.\n    ",
        "operationId": "PublicProjectsController_getProjectProfit_v1",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "description": "The project UUID.",
            "schema": {
              "example": "550e8400-e29b-41d4-a716-446655440000",
              "type": "string"
            }
          },
          {
            "name": "from",
            "required": false,
            "in": "query",
            "description": "Range start (inclusive), YYYY-MM-DD.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "to",
            "required": false,
            "in": "query",
            "description": "Range end (inclusive), YYYY-MM-DD.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Profit data returned successfully.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProjectProfit"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 400
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Bad Request"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 401
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions - API key missing required scopes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 403
                    },
                    "code": {
                      "type": "string",
                      "example": "INSUFFICIENT_PERMISSIONS"
                    },
                    "details": {
                      "type": "object",
                      "properties": {
                        "reason": {
                          "type": "string",
                          "example": "api_key_missing_required_scope"
                        },
                        "requiredScopes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "example": [
                            "usage:write"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Project not found. Error code: PROJECT_NOT_FOUND."
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "OAuth2ClientCredentials": []
          }
        ],
        "summary": "Get project profit",
        "tags": [
          "Projects"
        ]
      }
    },
    "/v1/projects/{id}/subprojects": {
      "post": {
        "description": "\nCreates a new subproject (dimension value) under the given project.\n\n### Required scope\n`projects-write`\n\n### Error codes\n- `PROJECT_NOT_FOUND` (404) — the parent project does not exist.\n    ",
        "operationId": "PublicProjectsController_createSubproject_v1",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "description": "The project UUID.",
            "schema": {
              "example": "550e8400-e29b-41d4-a716-446655440000",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateSubprojectRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Subproject created successfully.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProjectSubproject"
                }
              }
            }
          },
          "400": {
            "description": "Validation error."
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 401
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions - API key missing required scopes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 403
                    },
                    "code": {
                      "type": "string",
                      "example": "INSUFFICIENT_PERMISSIONS"
                    },
                    "details": {
                      "type": "object",
                      "properties": {
                        "reason": {
                          "type": "string",
                          "example": "api_key_missing_required_scope"
                        },
                        "requiredScopes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "example": [
                            "usage:write"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Project not found. Error code: PROJECT_NOT_FOUND."
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "OAuth2ClientCredentials": []
          }
        ],
        "summary": "Add a subproject",
        "tags": [
          "Projects"
        ]
      }
    },
    "/v1/projects/{id}/subprojects/{subprojectId}": {
      "put": {
        "description": "\nUpdates an existing subproject. All fields are optional. Send `null` for an optional field to clear it.\n\n### Required scope\n`projects-write`\n\n### Error codes\n- `PROJECT_NOT_FOUND` (404) — the parent project does not exist.\n- `SUBPROJECT_NOT_FOUND` (404) — the subproject does not exist on this project.\n    ",
        "operationId": "PublicProjectsController_updateSubproject_v1",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "description": "The project UUID.",
            "schema": {
              "example": "550e8400-e29b-41d4-a716-446655440000",
              "type": "string"
            }
          },
          {
            "name": "subprojectId",
            "required": true,
            "in": "path",
            "description": "The subproject UUID.",
            "schema": {
              "example": "550e8400-e29b-41d4-a716-446655440010",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateSubprojectRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Subproject updated successfully.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProjectSubproject"
                }
              }
            }
          },
          "400": {
            "description": "Validation error."
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 401
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions - API key missing required scopes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 403
                    },
                    "code": {
                      "type": "string",
                      "example": "INSUFFICIENT_PERMISSIONS"
                    },
                    "details": {
                      "type": "object",
                      "properties": {
                        "reason": {
                          "type": "string",
                          "example": "api_key_missing_required_scope"
                        },
                        "requiredScopes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "example": [
                            "usage:write"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Project or subproject not found."
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "OAuth2ClientCredentials": []
          }
        ],
        "summary": "Update a subproject",
        "tags": [
          "Projects"
        ]
      },
      "delete": {
        "description": "\nDeletes a subproject and its associated dimension value.\nThe default (catch-all) subproject cannot be deleted.\n\n### Required scope\n`projects-write`\n\n### Error codes\n- `PROJECT_NOT_FOUND` (404) — the parent project does not exist.\n- `SUBPROJECT_NOT_FOUND` (404) — the subproject does not exist on this project.\n- `SUBPROJECT_IS_DEFAULT` (400) — the subproject is the project's default catch-all and cannot be deleted.\n    ",
        "operationId": "PublicProjectsController_deleteSubproject_v1",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "description": "The project UUID.",
            "schema": {
              "example": "550e8400-e29b-41d4-a716-446655440000",
              "type": "string"
            }
          },
          {
            "name": "subprojectId",
            "required": true,
            "in": "path",
            "description": "The subproject UUID.",
            "schema": {
              "example": "550e8400-e29b-41d4-a716-446655440010",
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Subproject deleted successfully."
          },
          "400": {
            "description": "Cannot delete the default subproject. Error code: SUBPROJECT_IS_DEFAULT."
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 401
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions - API key missing required scopes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 403
                    },
                    "code": {
                      "type": "string",
                      "example": "INSUFFICIENT_PERMISSIONS"
                    },
                    "details": {
                      "type": "object",
                      "properties": {
                        "reason": {
                          "type": "string",
                          "example": "api_key_missing_required_scope"
                        },
                        "requiredScopes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "example": [
                            "usage:write"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Project or subproject not found."
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "OAuth2ClientCredentials": []
          }
        ],
        "summary": "Delete a subproject",
        "tags": [
          "Projects"
        ]
      }
    },
    "/v1/quotes": {
      "get": {
        "description": "\nReturns a paginated list of quotes.\n\n## Filters\n\n| Parameter | Description |\n|-----------|-------------|\n| status | Display status: `draft`, `sent`, `accepted`, `rejected`, `expired`, `converted`. Derived statuses are resolved server-side. |\n| customerId | Filter to one customer. |\n| page / limit | Pagination (defaults: page 1, limit 25, max limit 100). |\n| sortBy / sortOrder | Sort field (e.g. `date`, `documentNumber`, `amount`, `status`, `validUntil`) and direction. Defaults to newest first. |\n    ",
        "operationId": "PublicQuotesController_list_v1",
        "parameters": [
          {
            "name": "page",
            "required": false,
            "in": "query",
            "description": "Page number (1-indexed)",
            "schema": {
              "minimum": 1,
              "default": 1,
              "example": 1,
              "type": "number"
            }
          },
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "description": "Items per page",
            "schema": {
              "minimum": 1,
              "maximum": 100,
              "default": 25,
              "example": 25,
              "type": "number"
            }
          },
          {
            "name": "status",
            "required": false,
            "in": "query",
            "description": "Filter by display status (draft/sent/accepted/rejected/expired/converted). Derived statuses are resolved server-side.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "customerId",
            "required": false,
            "in": "query",
            "description": "Filter by customer id",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "sortBy",
            "required": false,
            "in": "query",
            "description": "Sort field",
            "schema": {
              "example": "date",
              "type": "string"
            }
          },
          {
            "name": "sortOrder",
            "required": false,
            "in": "query",
            "description": "Sort order",
            "schema": {
              "type": "string",
              "enum": [
                "ASC",
                "DESC"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Paginated list of quotes",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicListQuotesResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 400
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Bad Request"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 401
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions - API key missing required scopes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 403
                    },
                    "code": {
                      "type": "string",
                      "example": "INSUFFICIENT_PERMISSIONS"
                    },
                    "details": {
                      "type": "object",
                      "properties": {
                        "reason": {
                          "type": "string",
                          "example": "api_key_missing_required_scope"
                        },
                        "requiredScopes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "example": [
                            "usage:write"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "OAuth2ClientCredentials": []
          }
        ],
        "summary": "List quotes",
        "tags": [
          "Quotes"
        ]
      },
      "post": {
        "description": "\nCreates a draft quote.\n\n- The quote number is **not** allocated here — it is assigned on send.\n- Totals (subtotal/vat/amount) are computed from the line items.\n    ",
        "operationId": "PublicQuotesController_create_v1",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PublicCreateQuote"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Quote created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicQuote"
                }
              }
            }
          },
          "400": {
            "description": "Validation error"
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 401
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions - API key missing required scopes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 403
                    },
                    "code": {
                      "type": "string",
                      "example": "INSUFFICIENT_PERMISSIONS"
                    },
                    "details": {
                      "type": "object",
                      "properties": {
                        "reason": {
                          "type": "string",
                          "example": "api_key_missing_required_scope"
                        },
                        "requiredScopes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "example": [
                            "usage:write"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "OAuth2ClientCredentials": []
          }
        ],
        "summary": "Create a draft quote",
        "tags": [
          "Quotes"
        ]
      }
    },
    "/v1/quotes/{id}": {
      "get": {
        "description": "Returns a single quote, including its line items.",
        "operationId": "PublicQuotesController_findOne_v1",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "description": "The quote id",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The quote",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicQuote"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 400
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Bad Request"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 401
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions - API key missing required scopes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 403
                    },
                    "code": {
                      "type": "string",
                      "example": "INSUFFICIENT_PERMISSIONS"
                    },
                    "details": {
                      "type": "object",
                      "properties": {
                        "reason": {
                          "type": "string",
                          "example": "api_key_missing_required_scope"
                        },
                        "requiredScopes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "example": [
                            "usage:write"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Quote not found"
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "OAuth2ClientCredentials": []
          }
        ],
        "summary": "Get a quote by id",
        "tags": [
          "Quotes"
        ]
      },
      "patch": {
        "description": "\nReplaces the editable fields and line items of a draft quote. This is also how\nyou change `validUntil`.\n\nLine items are replaced wholesale — send the full intended set. A converted\nquote is read-only (`SALES_DOCUMENT_LOCKED_CONVERTED`).\n    ",
        "operationId": "PublicQuotesController_update_v1",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "description": "The quote id",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PublicUpdateQuote"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Quote updated",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicQuote"
                }
              }
            }
          },
          "400": {
            "description": "Validation error, or quote already converted (SALES_DOCUMENT_LOCKED_CONVERTED)."
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 401
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions - API key missing required scopes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 403
                    },
                    "code": {
                      "type": "string",
                      "example": "INSUFFICIENT_PERMISSIONS"
                    },
                    "details": {
                      "type": "object",
                      "properties": {
                        "reason": {
                          "type": "string",
                          "example": "api_key_missing_required_scope"
                        },
                        "requiredScopes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "example": [
                            "usage:write"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Quote not found"
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "OAuth2ClientCredentials": []
          }
        ],
        "summary": "Update a draft quote",
        "tags": [
          "Quotes"
        ]
      }
    },
    "/v1/quotes/{id}/convert": {
      "post": {
        "description": "\nConverts the quote into the next document in the pre-sales chain:\n\n- A quote converts into an **order confirmation** (`target: \"orderConfirmation\"`).\n- A quote can also convert directly into an **invoice** (`target: \"invoice\"`).\n\nBy default the quote's fields and line items are copied verbatim. To\nreview and adjust the target before finalizing, supply an optional `document`\npayload — its fields override the copied values.\n\nA quote converts only once. Re-converting fails with\n`SALES_DOCUMENT_ALREADY_CONVERTED_TO_INVOICE` or\n`SALES_DOCUMENT_ALREADY_CONVERTED_TO_DOCUMENT`.\n\nThe response identifies the produced document via `targetType`\n(\"invoice\" or \"orderConfirmation\") and `targetId`.\n    ",
        "operationId": "PublicQuotesController_convert_v1",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "description": "The quote id to convert",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PublicConvertQuote"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Conversion result",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicConvertQuoteResult"
                }
              }
            }
          },
          "400": {
            "description": "Error codes: SALES_DOCUMENT_ALREADY_CONVERTED_TO_INVOICE, SALES_DOCUMENT_ALREADY_CONVERTED_TO_DOCUMENT."
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 401
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions - API key missing required scopes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 403
                    },
                    "code": {
                      "type": "string",
                      "example": "INSUFFICIENT_PERMISSIONS"
                    },
                    "details": {
                      "type": "object",
                      "properties": {
                        "reason": {
                          "type": "string",
                          "example": "api_key_missing_required_scope"
                        },
                        "requiredScopes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "example": [
                            "usage:write"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Quote not found"
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "OAuth2ClientCredentials": []
          }
        ],
        "summary": "Convert a quote",
        "tags": [
          "Quotes"
        ]
      }
    },
    "/v1/quotes/{id}/pdf": {
      "get": {
        "description": "\nRenders and streams the quote as a PDF (`application/pdf`).\n\nPass `?draft=true` to render an unfinalized \"draft\" watermark preview before\nthe quote is sent.\n    ",
        "operationId": "PublicQuotesController_getPdf_v1",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "description": "The quote id",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "draft",
            "required": false,
            "in": "query",
            "description": "Render a draft-watermarked preview when \"true\".",
            "schema": {
              "type": "boolean"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "PDF binary stream"
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/pdf": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 400
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Bad Request"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/pdf": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 401
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions - API key missing required scopes",
            "content": {
              "application/pdf": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 403
                    },
                    "code": {
                      "type": "string",
                      "example": "INSUFFICIENT_PERMISSIONS"
                    },
                    "details": {
                      "type": "object",
                      "properties": {
                        "reason": {
                          "type": "string",
                          "example": "api_key_missing_required_scope"
                        },
                        "requiredScopes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "example": [
                            "usage:write"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Quote not found"
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "OAuth2ClientCredentials": []
          }
        ],
        "summary": "Download a quote as PDF",
        "tags": [
          "Quotes"
        ]
      }
    },
    "/v1/quotes/{id}/send": {
      "post": {
        "description": "\nSends the quote. This allocates the quote number (if not already set),\nrenders the PDF, optionally emails it, and marks the quote **sent**.\n\n## Delivery\n\n- `deliveryType: \"Manual\"` (default) — allocates the number and marks sent\n  without emailing. Use this when you will deliver the PDF yourself\n  (download it via `GET /:id/pdf`).\n- `deliveryType: \"Email\"` — emails the rendered PDF. The recipient resolves\n  from `recipientEmail` (override), else the customer contact, else the\n  customer email. If none can be resolved the request fails with\n  `SALES_DOCUMENT_MISSING_RECIPIENT`.\n\nSproom / e-invoice does **not** apply to quotes — there is no legal e-invoice\ntype for a quote.\n\nA quote that has already been converted is read-only and cannot be sent\n(`SALES_DOCUMENT_LOCKED_CONVERTED`).\n    ",
        "operationId": "PublicQuotesController_send_v1",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "description": "The quote id",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PublicSendQuote"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Quote sent",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicQuote"
                }
              }
            }
          },
          "400": {
            "description": "Error codes: SALES_DOCUMENT_MISSING_RECIPIENT (Email delivery with no resolvable address), SALES_DOCUMENT_LOCKED_CONVERTED (quote already converted)."
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 401
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions - API key missing required scopes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 403
                    },
                    "code": {
                      "type": "string",
                      "example": "INSUFFICIENT_PERMISSIONS"
                    },
                    "details": {
                      "type": "object",
                      "properties": {
                        "reason": {
                          "type": "string",
                          "example": "api_key_missing_required_scope"
                        },
                        "requiredScopes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "example": [
                            "usage:write"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Quote not found"
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "OAuth2ClientCredentials": []
          }
        ],
        "summary": "Send a quote",
        "tags": [
          "Quotes"
        ]
      }
    },
    "/v1/subscriptions": {
      "get": {
        "description": "\nRetrieves a paginated list of your company's customer subscriptions.\n\nThe list can be narrowed by free-text `search`, subscription `statuses`,\n`customerId`, `planId`, or your own `partnerReferenceId`.\n\n## Required Scope\n\n- `subscriptions-read`\n    ",
        "operationId": "PublicSubscriptionsController_listCustomerSubscriptions_v1",
        "parameters": [
          {
            "name": "page",
            "required": false,
            "in": "query",
            "description": "Page number (1-indexed)",
            "schema": {
              "minimum": 1,
              "default": 1,
              "example": 1,
              "type": "number"
            }
          },
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "description": "Number of items per page",
            "schema": {
              "minimum": 1,
              "maximum": 100,
              "default": 25,
              "example": 25,
              "type": "number"
            }
          },
          {
            "name": "search",
            "required": false,
            "in": "query",
            "description": "Search by customer name or subscription name",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "statuses",
            "required": false,
            "in": "query",
            "description": "Filter by subscription statuses",
            "schema": {
              "type": "array",
              "items": {
                "type": "string",
                "enum": [
                  "scheduled",
                  "trial",
                  "awaiting_payment",
                  "active",
                  "pending_cancellation",
                  "paused",
                  "cancelled",
                  "expired"
                ]
              }
            }
          },
          {
            "name": "customerId",
            "required": false,
            "in": "query",
            "description": "Filter by customer ID",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "planId",
            "required": false,
            "in": "query",
            "description": "Filter by subscription plan ID",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "partnerReferenceId",
            "required": false,
            "in": "query",
            "description": "Filter to the subscription(s) carrying this exact partner reconciliation reference — the `clientReferenceId` you passed at embedded-checkout bind time. Use it to recover a missed subscription webhook: resolve our subscription from your own order id.",
            "schema": {
              "example": "order_7f3a9c21",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "List of customer subscriptions",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicListCustomerSubscriptionsResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 400
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Bad Request"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 401
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions - API key missing required scopes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 403
                    },
                    "code": {
                      "type": "string",
                      "example": "INSUFFICIENT_PERMISSIONS"
                    },
                    "details": {
                      "type": "object",
                      "properties": {
                        "reason": {
                          "type": "string",
                          "example": "api_key_missing_required_scope"
                        },
                        "requiredScopes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "example": [
                            "usage:write"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "OAuth2ClientCredentials": []
          }
        ],
        "summary": "List customer subscriptions",
        "tags": [
          "Subscriptions"
        ]
      },
      "post": {
        "description": "\nCreates a customer subscription from a plan, starting on `startDate`.\n\nWhen `billingDirection` is omitted, the subscription defaults to\nin-advance (`ADVANCE`) billing.\n\nThe response includes the subscription's stable id — use it for all\nsubsequent reads, updates, and cancellations; it stays valid across plan\nreplacements and other scheduled changes.\n\n## Required Scope\n\n- `subscriptions-write`\n    ",
        "operationId": "PublicSubscriptionsController_assignSubscription_v1",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PublicAssignSubscriptionRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Subscription assigned to customer successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicCustomerSubscriptionResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 400
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Bad Request"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 401
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions - API key missing required scopes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 403
                    },
                    "code": {
                      "type": "string",
                      "example": "INSUFFICIENT_PERMISSIONS"
                    },
                    "details": {
                      "type": "object",
                      "properties": {
                        "reason": {
                          "type": "string",
                          "example": "api_key_missing_required_scope"
                        },
                        "requiredScopes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "example": [
                            "usage:write"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "OAuth2ClientCredentials": []
          }
        ],
        "summary": "Assign a subscription to a customer",
        "tags": [
          "Subscriptions"
        ]
      }
    },
    "/v1/subscriptions/{customerSubscriptionId}": {
      "get": {
        "description": "\nReturns the current state of the subscription identified by its stable id —\nthe chain head id returned at creation. The id is resolved against the\nversion chain, so it keeps working across plan replacements,\nbilling-direction / cadence changes, and scheduled cancellations; the\nheadline plan fields always reflect the version running today.\n\n## Required Scope\n\n- `subscriptions-read`\n    ",
        "operationId": "PublicSubscriptionsController_getSubscription_v1",
        "parameters": [
          {
            "name": "customerSubscriptionId",
            "required": true,
            "in": "path",
            "description": "The stable subscription id (chain head id)",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Customer subscription",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicCustomerSubscriptionResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 400
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Bad Request"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 401
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions - API key missing required scopes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 403
                    },
                    "code": {
                      "type": "string",
                      "example": "INSUFFICIENT_PERMISSIONS"
                    },
                    "details": {
                      "type": "object",
                      "properties": {
                        "reason": {
                          "type": "string",
                          "example": "api_key_missing_required_scope"
                        },
                        "requiredScopes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "example": [
                            "usage:write"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "OAuth2ClientCredentials": []
          }
        ],
        "summary": "Get a customer subscription by its stable id",
        "tags": [
          "Subscriptions"
        ]
      },
      "patch": {
        "description": "\nUpdate payment-related settings on an existing customer subscription.\n\n## Required Scope\n\n- `subscriptions-write`\n    ",
        "operationId": "PublicSubscriptionsController_updateSubscription_v1",
        "parameters": [
          {
            "name": "customerSubscriptionId",
            "required": true,
            "in": "path",
            "description": "The stable subscription id (chain head id)",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PublicUpdateSubscriptionRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Customer subscription updated successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicCustomerSubscriptionResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 400
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Bad Request"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 401
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions - API key missing required scopes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 403
                    },
                    "code": {
                      "type": "string",
                      "example": "INSUFFICIENT_PERMISSIONS"
                    },
                    "details": {
                      "type": "object",
                      "properties": {
                        "reason": {
                          "type": "string",
                          "example": "api_key_missing_required_scope"
                        },
                        "requiredScopes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "example": [
                            "usage:write"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "OAuth2ClientCredentials": []
          }
        ],
        "summary": "Update a customer subscription",
        "tags": [
          "Subscriptions"
        ]
      }
    },
    "/v1/subscriptions/{customerSubscriptionId}/scheduled-changes": {
      "get": {
        "description": "\nReturns the queued, not-yet-active changes on the subscription —\nfuture-dated plan replacements, billing-direction / cadence changes, and\nscheduled cancellations. Each carries a `changeId` that can be cancelled\nindividually. Empty array when nothing is queued.\n\n## Required Scope\n\n- `subscriptions-read`\n    ",
        "operationId": "PublicSubscriptionsController_listScheduledChanges_v1",
        "parameters": [
          {
            "name": "customerSubscriptionId",
            "required": true,
            "in": "path",
            "description": "The stable subscription id (chain head id)",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The list of pending scheduled changes",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicScheduledChange"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 400
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Bad Request"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 401
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions - API key missing required scopes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 403
                    },
                    "code": {
                      "type": "string",
                      "example": "INSUFFICIENT_PERMISSIONS"
                    },
                    "details": {
                      "type": "object",
                      "properties": {
                        "reason": {
                          "type": "string",
                          "example": "api_key_missing_required_scope"
                        },
                        "requiredScopes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "example": [
                            "usage:write"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "OAuth2ClientCredentials": []
          }
        ],
        "summary": "List a subscription’s pending scheduled changes",
        "tags": [
          "Subscriptions"
        ]
      }
    },
    "/v1/subscriptions/{customerSubscriptionId}/scheduled-changes/{changeId}": {
      "delete": {
        "description": "\nCancels exactly one queued change (from the scheduled-changes list) without\nending the subscription or touching its other scheduled changes. Returns\nthe subscription’s current state. A `changeId` that has already activated\nor been cancelled returns 404.\n\n## Required Scope\n\n- `subscriptions-write`\n    ",
        "operationId": "PublicSubscriptionsController_cancelScheduledChange_v1",
        "parameters": [
          {
            "name": "customerSubscriptionId",
            "required": true,
            "in": "path",
            "description": "The stable subscription id (chain head id)",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "changeId",
            "required": true,
            "in": "path",
            "description": "The `changeId` of the scheduled change to cancel",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Scheduled change cancelled; the subscription’s current state",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicCustomerSubscriptionResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 400
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Bad Request"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 401
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions - API key missing required scopes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 403
                    },
                    "code": {
                      "type": "string",
                      "example": "INSUFFICIENT_PERMISSIONS"
                    },
                    "details": {
                      "type": "object",
                      "properties": {
                        "reason": {
                          "type": "string",
                          "example": "api_key_missing_required_scope"
                        },
                        "requiredScopes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "example": [
                            "usage:write"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "OAuth2ClientCredentials": []
          }
        ],
        "summary": "Cancel a single pending scheduled change",
        "tags": [
          "Subscriptions"
        ]
      }
    },
    "/v1/subscriptions/cancel": {
      "post": {
        "description": "\nCancels (churns) a customer subscription according to the chosen `strategy`\n— at the end of the current billing cycle, immediately, or on a specific\ndate.\n\n`effectiveDate` is required when the strategy is `SPECIFIC_DATE`, and\n`refundBehavior` only applies when cancelling immediately. A\nnon-immediate cancellation is queued and appears in the subscription's\nscheduled-changes list until it takes effect.\n\nReturns the subscription's current state after the command is applied.\n\n## Required Scope\n\n- `subscriptions-write`\n    ",
        "operationId": "PublicSubscriptionsController_cancelSubscription_v1",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PublicCancelSubscriptionRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Customer subscription cancelled successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicCustomerSubscriptionResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 400
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Bad Request"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 401
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions - API key missing required scopes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 403
                    },
                    "code": {
                      "type": "string",
                      "example": "INSUFFICIENT_PERMISSIONS"
                    },
                    "details": {
                      "type": "object",
                      "properties": {
                        "reason": {
                          "type": "string",
                          "example": "api_key_missing_required_scope"
                        },
                        "requiredScopes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "example": [
                            "usage:write"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "OAuth2ClientCredentials": []
          }
        ],
        "summary": "Cancel a customer subscription",
        "tags": [
          "Subscriptions"
        ]
      }
    },
    "/v1/subscriptions/plans": {
      "get": {
        "description": "\nRetrieves a paginated list of your company's subscription plans.\n\nOnly active plans are returned — archived plans are excluded. Pass\n`?search=` to filter the list by free text.\n\n## Required Scope\n\n- `subscriptions-read`\n    ",
        "operationId": "PublicSubscriptionsController_listPlans_v1",
        "parameters": [
          {
            "name": "page",
            "required": false,
            "in": "query",
            "description": "Page number (1-indexed)",
            "schema": {
              "minimum": 1,
              "default": 1,
              "example": 1,
              "type": "number"
            }
          },
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "description": "Number of items per page",
            "schema": {
              "minimum": 1,
              "maximum": 100,
              "default": 25,
              "example": 25,
              "type": "number"
            }
          },
          {
            "name": "search",
            "required": false,
            "in": "query",
            "description": "Search by plan name",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "List of subscription plans",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicListSubscriptionPlansResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 400
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Bad Request"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 401
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions - API key missing required scopes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 403
                    },
                    "code": {
                      "type": "string",
                      "example": "INSUFFICIENT_PERMISSIONS"
                    },
                    "details": {
                      "type": "object",
                      "properties": {
                        "reason": {
                          "type": "string",
                          "example": "api_key_missing_required_scope"
                        },
                        "requiredScopes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "example": [
                            "usage:write"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "OAuth2ClientCredentials": []
          }
        ],
        "summary": "List subscription plans",
        "tags": [
          "Subscriptions"
        ]
      }
    },
    "/v1/subscriptions/plans/archive/{planId}": {
      "post": {
        "description": "\nArchives a subscription plan. Fails if the plan has any active or\npending-cancellation customer subscriptions.\n\nArchived plans no longer appear in the plan list.\n\n## Required Scope\n\n- `subscriptions-write`\n    ",
        "operationId": "PublicSubscriptionsController_archivePlan_v1",
        "parameters": [
          {
            "name": "planId",
            "required": true,
            "in": "path",
            "description": "The subscription plan ID",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Subscription plan archived successfully"
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 400
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Bad Request"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 401
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions - API key missing required scopes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 403
                    },
                    "code": {
                      "type": "string",
                      "example": "INSUFFICIENT_PERMISSIONS"
                    },
                    "details": {
                      "type": "object",
                      "properties": {
                        "reason": {
                          "type": "string",
                          "example": "api_key_missing_required_scope"
                        },
                        "requiredScopes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "example": [
                            "usage:write"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "OAuth2ClientCredentials": []
          }
        ],
        "summary": "Archive a subscription plan",
        "tags": [
          "Subscriptions"
        ]
      }
    },
    "/v1/vat-codes": {
      "get": {
        "description": "\nRetrieves all VAT codes for your company, sorted by VAT code. VAT codes\ndefine the rate and booking principle used to calculate VAT on journal\nentries — pass a VAT code's `id` as `vatCodeId` on a journal-entry or\ndraft-journal-entry line to apply it.\n\nEach code also carries the ledger account (and contra account) the VAT\namount is booked to. Results are cached for 5 seconds.\n\n## Required Scope\n\n- `vat-codes-read`\n    ",
        "operationId": "PublicVatCodesController_getVatCodes_v1",
        "parameters": [],
        "responses": {
          "200": {
            "description": "List of VAT codes and rates for the company",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/VatCodeResponse"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 400
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Bad Request"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 401
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions - API key missing required scopes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 403
                    },
                    "code": {
                      "type": "string",
                      "example": "INSUFFICIENT_PERMISSIONS"
                    },
                    "details": {
                      "type": "object",
                      "properties": {
                        "reason": {
                          "type": "string",
                          "example": "api_key_missing_required_scope"
                        },
                        "requiredScopes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "example": [
                            "usage:write"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "OAuth2ClientCredentials": []
          }
        ],
        "summary": "List VAT codes",
        "tags": [
          "VAT Codes"
        ]
      }
    },
    "/v1/vendors": {
      "get": {
        "description": "\nRetrieves all vendors for your company, sorted by vendor number.\n\nThe list is cached for 5 seconds; creating a vendor through this API\ninvalidates the cache, so a just-created vendor is immediately visible.\n\n## Required Scope\n\n- `vendors-read`\n    ",
        "operationId": "PublicVendorsController_getVendors_v1",
        "parameters": [],
        "responses": {
          "200": {
            "description": "List of vendors for the company",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/VendorResponse"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 400
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Bad Request"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 401
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions - API key missing required scopes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 403
                    },
                    "code": {
                      "type": "string",
                      "example": "INSUFFICIENT_PERMISSIONS"
                    },
                    "details": {
                      "type": "object",
                      "properties": {
                        "reason": {
                          "type": "string",
                          "example": "api_key_missing_required_scope"
                        },
                        "requiredScopes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "example": [
                            "usage:write"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "OAuth2ClientCredentials": []
          }
        ],
        "summary": "List vendors",
        "tags": [
          "Vendors"
        ]
      },
      "post": {
        "description": "\nCreates a vendor together with its contacts.\n\n`vendorNumber` is trimmed and must be unique within your company — a\nduplicate returns 400 with error code `VENDOR_NUMBER_ALREADY_EXISTS`.\n\nExactly one contact must be marked as default. When you provide a single\ncontact it is made the default automatically; otherwise a missing or\nduplicated default returns 400 with error code `CONTACT_DEFAULT_REQUIRED`\nor `CONTACT_MULTIPLE_DEFAULTS`.\n\n`vendorGroupId` must reference an existing vendor group in your company\n(404 `VENDOR_GROUP_NOT_FOUND`), and `defaultAccountId`, when provided,\nmust reference an existing ledger account (404 `LEDGER_NOT_FOUND`).\n\nThe response contains only the new vendor's `id` and `vendorNumber`;\nfetch the full record via the list endpoint.\n\n## Required Scope\n\n- `vendors-write`\n    ",
        "operationId": "PublicVendorsController_createVendor_v1",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateVendorRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Vendor created successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreateVendorResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 400
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Bad Request"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 401
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions - API key missing required scopes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 403
                    },
                    "code": {
                      "type": "string",
                      "example": "INSUFFICIENT_PERMISSIONS"
                    },
                    "details": {
                      "type": "object",
                      "properties": {
                        "reason": {
                          "type": "string",
                          "example": "api_key_missing_required_scope"
                        },
                        "requiredScopes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "example": [
                            "usage:write"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "OAuth2ClientCredentials": []
          }
        ],
        "summary": "Create a vendor",
        "tags": [
          "Vendors"
        ]
      }
    },
    "/v1/vendors/{vendorId}/contacts": {
      "get": {
        "description": "\nRetrieves all contacts for a vendor, with the default contact first and the\nrest sorted alphabetically by name.\n\nReturns 404 with error code `VENDOR_NOT_FOUND` when the vendor does not\nexist in your company.\n\n## Required Scope\n\n- `vendors-read`\n    ",
        "operationId": "PublicVendorsController_getVendorContacts_v1",
        "parameters": [
          {
            "name": "vendorId",
            "required": true,
            "in": "path",
            "description": "Vendor ID",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "List of contacts for a vendor",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/VendorContactResponse"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 400
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Bad Request"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 401
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions - API key missing required scopes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 403
                    },
                    "code": {
                      "type": "string",
                      "example": "INSUFFICIENT_PERMISSIONS"
                    },
                    "details": {
                      "type": "object",
                      "properties": {
                        "reason": {
                          "type": "string",
                          "example": "api_key_missing_required_scope"
                        },
                        "requiredScopes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "example": [
                            "usage:write"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "OAuth2ClientCredentials": []
          }
        ],
        "summary": "List vendor contacts",
        "tags": [
          "Vendors"
        ]
      }
    },
    "/v1/vendors/{vendorId}/departments": {
      "get": {
        "description": "\nRetrieves all departments for a vendor, with the default department first and\nthe rest sorted alphabetically by name.\n\nReturns 404 with error code `VENDOR_NOT_FOUND` when the vendor does not\nexist in your company.\n\n## Required Scope\n\n- `vendors-read`\n    ",
        "operationId": "PublicVendorsController_getVendorDepartments_v1",
        "parameters": [
          {
            "name": "vendorId",
            "required": true,
            "in": "path",
            "description": "Vendor ID",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "List of departments for a vendor",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/VendorDepartmentResponse"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 400
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Bad Request"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 401
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions - API key missing required scopes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 403
                    },
                    "code": {
                      "type": "string",
                      "example": "INSUFFICIENT_PERMISSIONS"
                    },
                    "details": {
                      "type": "object",
                      "properties": {
                        "reason": {
                          "type": "string",
                          "example": "api_key_missing_required_scope"
                        },
                        "requiredScopes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "example": [
                            "usage:write"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "OAuth2ClientCredentials": []
          }
        ],
        "summary": "List vendor departments",
        "tags": [
          "Vendors"
        ]
      }
    },
    "/v1/vendors/groups": {
      "get": {
        "description": "\nRetrieves all vendor groups for your company, sorted alphabetically by name.\n\nThe list is cached for 5 seconds.\n\n## Required Scope\n\n- `vendors-read`\n    ",
        "operationId": "PublicVendorsController_getVendorGroups_v1",
        "parameters": [],
        "responses": {
          "200": {
            "description": "List of vendor groups for the company",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/VendorGroupResponse"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 400
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Bad Request"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 401
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions - API key missing required scopes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 403
                    },
                    "code": {
                      "type": "string",
                      "example": "INSUFFICIENT_PERMISSIONS"
                    },
                    "details": {
                      "type": "object",
                      "properties": {
                        "reason": {
                          "type": "string",
                          "example": "api_key_missing_required_scope"
                        },
                        "requiredScopes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "example": [
                            "usage:write"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "OAuth2ClientCredentials": []
          }
        ],
        "summary": "List vendor groups",
        "tags": [
          "Vendors"
        ]
      }
    },
    "/v1/webhook-endpoints": {
      "post": {
        "description": "Registers a new endpoint. `url` must be a public HTTPS URL. The response includes the signing `secret` exactly once — store it securely.",
        "operationId": "PublicWebhookEndpointsController_create_v1",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateWebhookEndpointRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Endpoint created. Includes the one-time signing secret.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookEndpointWithSecret"
                }
              }
            }
          },
          "400": {
            "description": "Invalid URL (non-HTTPS or internal host) or unknown event. Error code: WEBHOOK_URL_MUST_BE_HTTPS"
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 401
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions - API key missing required scopes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 403
                    },
                    "code": {
                      "type": "string",
                      "example": "INSUFFICIENT_PERMISSIONS"
                    },
                    "details": {
                      "type": "object",
                      "properties": {
                        "reason": {
                          "type": "string",
                          "example": "api_key_missing_required_scope"
                        },
                        "requiredScopes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "example": [
                            "usage:write"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "OAuth2ClientCredentials": []
          }
        ],
        "summary": "Create a webhook endpoint",
        "tags": [
          "Webhook Endpoints"
        ]
      },
      "get": {
        "description": "Returns the company’s webhook endpoints, newest first.",
        "operationId": "PublicWebhookEndpointsController_list_v1",
        "parameters": [
          {
            "name": "page",
            "required": false,
            "in": "query",
            "description": "Page number (1-based).",
            "schema": {
              "default": 1,
              "example": 1,
              "type": "number"
            }
          },
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "description": "Page size (max 100).",
            "schema": {
              "default": 25,
              "example": 25,
              "type": "number"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Paginated list of webhook endpoints.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookEndpointList"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 400
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Bad Request"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 401
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions - API key missing required scopes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 403
                    },
                    "code": {
                      "type": "string",
                      "example": "INSUFFICIENT_PERMISSIONS"
                    },
                    "details": {
                      "type": "object",
                      "properties": {
                        "reason": {
                          "type": "string",
                          "example": "api_key_missing_required_scope"
                        },
                        "requiredScopes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "example": [
                            "usage:write"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "OAuth2ClientCredentials": []
          }
        ],
        "summary": "List webhook endpoints",
        "tags": [
          "Webhook Endpoints"
        ]
      }
    },
    "/v1/webhook-endpoints/{id}": {
      "get": {
        "description": "\nRetrieves a single webhook endpoint configuration by its id. Returns `404`\nwith code `WEBHOOK_ENDPOINT_NOT_FOUND` when the endpoint does not exist in\nyour company.\n\n## Required Scope\n\n- `webhook-endpoints-read`\n    ",
        "operationId": "PublicWebhookEndpointsController_get_v1",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "description": "The webhook endpoint id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The webhook endpoint.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookEndpoint"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 400
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Bad Request"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 401
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions - API key missing required scopes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 403
                    },
                    "code": {
                      "type": "string",
                      "example": "INSUFFICIENT_PERMISSIONS"
                    },
                    "details": {
                      "type": "object",
                      "properties": {
                        "reason": {
                          "type": "string",
                          "example": "api_key_missing_required_scope"
                        },
                        "requiredScopes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "example": [
                            "usage:write"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Endpoint not found. Error code: WEBHOOK_ENDPOINT_NOT_FOUND"
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "OAuth2ClientCredentials": []
          }
        ],
        "summary": "Retrieve a webhook endpoint",
        "tags": [
          "Webhook Endpoints"
        ]
      },
      "put": {
        "description": "All fields optional. `enabledEvents` replaces the full subscription set. Send `description: null` to clear it.",
        "operationId": "PublicWebhookEndpointsController_update_v1",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "description": "The webhook endpoint id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateWebhookEndpointRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The updated webhook endpoint.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookEndpoint"
                }
              }
            }
          },
          "400": {
            "description": "Invalid URL or unknown event. Error code: WEBHOOK_URL_MUST_BE_HTTPS"
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 401
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions - API key missing required scopes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 403
                    },
                    "code": {
                      "type": "string",
                      "example": "INSUFFICIENT_PERMISSIONS"
                    },
                    "details": {
                      "type": "object",
                      "properties": {
                        "reason": {
                          "type": "string",
                          "example": "api_key_missing_required_scope"
                        },
                        "requiredScopes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "example": [
                            "usage:write"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Endpoint not found. Error code: WEBHOOK_ENDPOINT_NOT_FOUND"
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "OAuth2ClientCredentials": []
          }
        ],
        "summary": "Update a webhook endpoint",
        "tags": [
          "Webhook Endpoints"
        ]
      },
      "delete": {
        "description": "Permanently removes the endpoint and its delivery log.",
        "operationId": "PublicWebhookEndpointsController_delete_v1",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "description": "The webhook endpoint id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Endpoint deleted."
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 400
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Bad Request"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 401
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions - API key missing required scopes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 403
                    },
                    "code": {
                      "type": "string",
                      "example": "INSUFFICIENT_PERMISSIONS"
                    },
                    "details": {
                      "type": "object",
                      "properties": {
                        "reason": {
                          "type": "string",
                          "example": "api_key_missing_required_scope"
                        },
                        "requiredScopes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "example": [
                            "usage:write"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Endpoint not found. Error code: WEBHOOK_ENDPOINT_NOT_FOUND"
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "OAuth2ClientCredentials": []
          }
        ],
        "summary": "Delete a webhook endpoint",
        "tags": [
          "Webhook Endpoints"
        ]
      }
    },
    "/v1/webhook-endpoints/{id}/roll-secret": {
      "post": {
        "description": "Generates a new signing secret for the endpoint, returned once. The endpoint id is unchanged. The previous secret stops verifying immediately.",
        "operationId": "PublicWebhookEndpointsController_rollSecret_v1",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "description": "The webhook endpoint id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The endpoint with its new one-time signing secret.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookEndpointWithSecret"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 400
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Bad Request"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 401
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions - API key missing required scopes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 403
                    },
                    "code": {
                      "type": "string",
                      "example": "INSUFFICIENT_PERMISSIONS"
                    },
                    "details": {
                      "type": "object",
                      "properties": {
                        "reason": {
                          "type": "string",
                          "example": "api_key_missing_required_scope"
                        },
                        "requiredScopes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "example": [
                            "usage:write"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Endpoint not found. Error code: WEBHOOK_ENDPOINT_NOT_FOUND"
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "OAuth2ClientCredentials": []
          }
        ],
        "summary": "Roll the signing secret",
        "tags": [
          "Webhook Endpoints"
        ]
      }
    },
    "/v1/webhook-endpoints/{id}/test": {
      "post": {
        "description": "Synchronously POSTs a signed sample payload for the given event to the endpoint’s URL and returns the result. No delivery is recorded.",
        "operationId": "PublicWebhookEndpointsController_test_v1",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "description": "The webhook endpoint id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TestWebhookEndpointRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The probe result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TestWebhookEndpointResult"
                }
              }
            }
          },
          "400": {
            "description": "The event is not one of the endpoint’s subscribed events. Error code: WEBHOOK_TOPIC_NOT_SUBSCRIBED"
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 401
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions - API key missing required scopes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 403
                    },
                    "code": {
                      "type": "string",
                      "example": "INSUFFICIENT_PERMISSIONS"
                    },
                    "details": {
                      "type": "object",
                      "properties": {
                        "reason": {
                          "type": "string",
                          "example": "api_key_missing_required_scope"
                        },
                        "requiredScopes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "example": [
                            "usage:write"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Endpoint not found. Error code: WEBHOOK_ENDPOINT_NOT_FOUND"
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "OAuth2ClientCredentials": []
          }
        ],
        "summary": "Send a test event",
        "tags": [
          "Webhook Endpoints"
        ]
      }
    },
    "/v2/draft-journal-batches": {
      "post": {
        "description": "Atomically creates 1–100 draft journal entries in a single transaction.\nEach entry follows the same restrictions as POST /api/v2/draft-journal-entries:\nauto-append of the AR/AP leg for locked types, tenant-scoped customerId / vendorId /\njournalCategoryId / line accountId validation.\n\nIf any entry fails validation or persistence the entire batch is rolled back — no draft\nrows are created. journalCategoryId / customerId / vendorId / accountId from another\ntenant rejects the whole batch with the matching error code.\n\nAttachments: each entry may include up to 10 base64-encoded `attachments[]`. A failure on any\nentry rolls back the whole batch and deletes every already-uploaded blob — no orphan documents\nsurvive.",
        "operationId": "PublicDraftJournalBatchesV2Controller_createBatch_v2",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateDraftJournalEntryV2BatchRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Batch created — every draft persisted",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreateDraftJournalEntryV2BatchResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 400
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Bad Request"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 401
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions - API key missing required scopes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 403
                    },
                    "code": {
                      "type": "string",
                      "example": "INSUFFICIENT_PERMISSIONS"
                    },
                    "details": {
                      "type": "object",
                      "properties": {
                        "reason": {
                          "type": "string",
                          "example": "api_key_missing_required_scope"
                        },
                        "requiredScopes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "example": [
                            "usage:write"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "OAuth2ClientCredentials": []
          }
        ],
        "summary": "Create draft journal entries in batch (v2)",
        "tags": [
          "Draft Journal Entries (v2)"
        ]
      }
    },
    "/v2/draft-journal-entries": {
      "post": {
        "description": "Creates a draft journal entry with the V2 restriction matrix enforced at create-time\n(unlike v1, which only validates on book). For CUSTOMER_INVOICE / CUSTOMER_PAYMENT /\nSUPPLIER_INVOICE / SUPPLIER_PAYMENT submit only the counter-side lines — the server\nauto-appends the AR/AP leg on the partner group default account.\n\nTenant scoping: every customerId / vendorId / journalCategoryId / line accountId is\nvalidated against the API key's app company. Cross-tenant or unknown ids reject with 400\n(JOURNAL_CATEGORY_NOT_FOUND, ACCOUNT_NOT_FOUND, CUSTOMER_HAS_NO_GROUP, VENDOR_HAS_NO_GROUP,\nINVOICE_AR_LEG_NOT_ON_GROUP_DEFAULT, PAYMENT_AR_LEG_NOT_ON_GROUP_DEFAULT,\nINVOICE_AP_LEG_NOT_ON_GROUP_DEFAULT, PAYMENT_AP_LEG_NOT_ON_GROUP_DEFAULT).\n\nAttachments: include up to 10 base64-encoded files in the optional `attachments[]` field —\nsame shape and limits as POST /api/v2/journal-entries. Each becomes a Document linked to the\ndraft; when the draft is booked, the documents migrate to the posted JE and surface via\nGET /api/v1/journal-entries/:id/attachments. Rejection paths: an invalid MIME type rejects at\nDTO validation with 400 SHARED_VALIDATION_FAILED; malformed base64 reaches the service and\nrejects with 400 INVALID_ATTACHMENT_TYPE.",
        "operationId": "PublicDraftJournalEntriesV2Controller_create_v2",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateDraftJournalEntryV2Request"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Draft created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DraftJournalEntryResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 400
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Bad Request"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 401
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions - API key missing required scopes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 403
                    },
                    "code": {
                      "type": "string",
                      "example": "INSUFFICIENT_PERMISSIONS"
                    },
                    "details": {
                      "type": "object",
                      "properties": {
                        "reason": {
                          "type": "string",
                          "example": "api_key_missing_required_scope"
                        },
                        "requiredScopes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "example": [
                            "usage:write"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "OAuth2ClientCredentials": []
          }
        ],
        "summary": "Create a draft journal entry (v2)",
        "tags": [
          "Draft Journal Entries (v2)"
        ]
      },
      "get": {
        "description": "Returns a paginated list of draft journal entries owned by the API key's app company. Tenant-scoped: drafts created by other companies are never visible here. Identical response shape to GET /api/v1/draft-journal-entries.",
        "operationId": "PublicDraftJournalEntriesV2Controller_list_v2",
        "parameters": [
          {
            "name": "page",
            "required": false,
            "in": "query",
            "description": "Page number (1-indexed)",
            "schema": {
              "minimum": 1,
              "default": 1,
              "type": "number"
            }
          },
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "description": "Maximum items per page",
            "schema": {
              "minimum": 1,
              "maximum": 100,
              "default": 25,
              "type": "number"
            }
          },
          {
            "name": "fromDate",
            "required": false,
            "in": "query",
            "description": "Only include drafts on or after this date (YYYY-MM-DD)",
            "schema": {
              "example": "2026-01-01",
              "type": "string"
            }
          },
          {
            "name": "toDate",
            "required": false,
            "in": "query",
            "description": "Only include drafts on or before this date (YYYY-MM-DD)",
            "schema": {
              "example": "2026-01-31",
              "type": "string"
            }
          },
          {
            "name": "accountId",
            "required": false,
            "in": "query",
            "description": "Filter by account ID (matches any draft line on this account)",
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          },
          {
            "name": "customerId",
            "required": false,
            "in": "query",
            "description": "Filter by customer ID",
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          },
          {
            "name": "vendorId",
            "required": false,
            "in": "query",
            "description": "Filter by vendor ID",
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          },
          {
            "name": "journalType",
            "required": false,
            "in": "query",
            "description": "Filter by journal type",
            "schema": {
              "type": "string",
              "enum": [
                "JOURNAL_ENTRY",
                "SUPPLIER_INVOICE",
                "SUPPLIER_PAYMENT",
                "CUSTOMER_INVOICE",
                "CUSTOMER_PAYMENT",
                "CUSTOMER_REMINDER",
                "CURRENCY_REVALUATION",
                "VAT_SETTLEMENT",
                "YEAR_END_CLOSING"
              ]
            }
          },
          {
            "name": "minAmount",
            "required": false,
            "in": "query",
            "description": "Only include drafts with an amount greater than or equal to this value (inclusive).",
            "schema": {
              "example": 100,
              "type": "number"
            }
          },
          {
            "name": "maxAmount",
            "required": false,
            "in": "query",
            "description": "Only include drafts with an amount less than or equal to this value (inclusive).",
            "schema": {
              "example": 10000,
              "type": "number"
            }
          },
          {
            "name": "externalSystemId",
            "required": false,
            "in": "query",
            "description": "Exact-match filter on your own system's id. Not unique — several drafts may share one id, so expect zero or more results.",
            "schema": {
              "maxLength": 255,
              "example": "erp-7f3a2c91",
              "type": "string"
            }
          },
          {
            "name": "search",
            "required": false,
            "in": "query",
            "description": "Free-text search in description and reference fields",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Drafts retrieved",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ListDraftJournalEntriesResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 400
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Bad Request"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 401
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions - API key missing required scopes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 403
                    },
                    "code": {
                      "type": "string",
                      "example": "INSUFFICIENT_PERMISSIONS"
                    },
                    "details": {
                      "type": "object",
                      "properties": {
                        "reason": {
                          "type": "string",
                          "example": "api_key_missing_required_scope"
                        },
                        "requiredScopes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "example": [
                            "usage:write"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "OAuth2ClientCredentials": []
          }
        ],
        "summary": "List draft journal entries (v2)",
        "tags": [
          "Draft Journal Entries (v2)"
        ]
      }
    },
    "/v2/draft-journal-entries/{id}": {
      "patch": {
        "description": "Partial update: every create-time field is accepted except `entryType` (the journal type pins\nconstraints decided at creation and is immutable) and `attachments` (own lifecycle). Omitted fields\nkeep their current values; `splitEntries`, when provided, replaces the full line set.\n\n`externalSystemId` is carried onto the booked journal entry when the draft is booked, and is not\nunique: several drafts or entries may share one id. Filter\n`GET /draft-journal-entries?externalSystemId=...` to list carriers.\n\nReviewed (locked) drafts reject updates with 400 DRAFT_REVIEWED_LOCKED — unmark the review first.\nConcurrent updates are last-write-wins.",
        "operationId": "PublicDraftJournalEntriesV2Controller_updateOne_v2",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "description": "Draft journal entry ID (UUID)",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateDraftJournalEntryV2Request"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Draft updated",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DraftJournalEntryResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 400
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Bad Request"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 401
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions - API key missing required scopes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 403
                    },
                    "code": {
                      "type": "string",
                      "example": "INSUFFICIENT_PERMISSIONS"
                    },
                    "details": {
                      "type": "object",
                      "properties": {
                        "reason": {
                          "type": "string",
                          "example": "api_key_missing_required_scope"
                        },
                        "requiredScopes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "example": [
                            "usage:write"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "OAuth2ClientCredentials": []
          }
        ],
        "summary": "Update a draft journal entry (v2)",
        "tags": [
          "Draft Journal Entries (v2)"
        ]
      },
      "get": {
        "description": "Returns the draft if it belongs to the API key's app company; 404 otherwise. Identical response shape to GET /api/v1/draft-journal-entries/:id.",
        "operationId": "PublicDraftJournalEntriesV2Controller_getOne_v2",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "description": "Draft journal entry ID (UUID)",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Draft retrieved",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DraftJournalEntryResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 400
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Bad Request"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 401
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions - API key missing required scopes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 403
                    },
                    "code": {
                      "type": "string",
                      "example": "INSUFFICIENT_PERMISSIONS"
                    },
                    "details": {
                      "type": "object",
                      "properties": {
                        "reason": {
                          "type": "string",
                          "example": "api_key_missing_required_scope"
                        },
                        "requiredScopes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "example": [
                            "usage:write"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "OAuth2ClientCredentials": []
          }
        ],
        "summary": "Get a single draft journal entry (v2)",
        "tags": [
          "Draft Journal Entries (v2)"
        ]
      },
      "delete": {
        "description": "Deletes a draft journal entry. Any attached documents are released back to the inbox (status reset to NEW). Returns 404 if the draft id does not belong to the API key's app company.",
        "operationId": "PublicDraftJournalEntriesV2Controller_remove_v2",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "description": "Draft journal entry ID (UUID)",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Draft deleted successfully"
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 400
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Bad Request"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 401
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions - API key missing required scopes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 403
                    },
                    "code": {
                      "type": "string",
                      "example": "INSUFFICIENT_PERMISSIONS"
                    },
                    "details": {
                      "type": "object",
                      "properties": {
                        "reason": {
                          "type": "string",
                          "example": "api_key_missing_required_scope"
                        },
                        "requiredScopes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "example": [
                            "usage:write"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "OAuth2ClientCredentials": []
          }
        ],
        "summary": "Delete a draft journal entry (v2)",
        "tags": [
          "Draft Journal Entries (v2)"
        ]
      }
    },
    "/v2/draft-journal-entries/{id}/book": {
      "post": {
        "description": "Converts a draft journal entry into a posted journal entry. Validates the posting period and balance, then permanently deletes the draft. V2 drafts already carry the auto-appended AR/AP leg, so booking is a clean handoff to the posted-JE pipeline — no duplicate anchor leg is created. Returns 404 if the draft id does not belong to the API key's app company.",
        "operationId": "PublicDraftJournalEntriesV2Controller_book_v2",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "description": "Draft journal entry ID (UUID)",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "201": {
            "description": "Draft booked successfully — returns the created journal entry",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JournalEntryResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 400
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Bad Request"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 401
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions - API key missing required scopes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 403
                    },
                    "code": {
                      "type": "string",
                      "example": "INSUFFICIENT_PERMISSIONS"
                    },
                    "details": {
                      "type": "object",
                      "properties": {
                        "reason": {
                          "type": "string",
                          "example": "api_key_missing_required_scope"
                        },
                        "requiredScopes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "example": [
                            "usage:write"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "OAuth2ClientCredentials": []
          }
        ],
        "summary": "Book a draft journal entry (v2)",
        "tags": [
          "Draft Journal Entries (v2)"
        ]
      }
    },
    "/v2/journal-entries": {
      "post": {
        "description": "Create a journal entry. For CUSTOMER_INVOICE / CUSTOMER_PAYMENT / SUPPLIER_INVOICE / SUPPLIER_PAYMENT,\nsubmit only the counter-side lines (revenue, expense, bank, etc.). The server appends the AR/AP leg\non the customer's or vendor's group default account, with side derived from the sign of `originalAmount`\n(positive = invoice/payment, negative = credit-note/refund). Including a line on the group default\naccount explicitly will be rejected.\n\nFor all other journal types this endpoint behaves identically to v1: pass through whatever lines you supply.\n\nAttachments: include up to 10 base64-encoded files in the optional `attachments[]` field — same shape and\nlimits as v1. Each becomes a Document linked to the created entry and surfaces via\nGET /api/v1/journal-entries/:id/attachments. Invalid MIME type or malformed base64 rejects the request\nwith 400 INVALID_ATTACHMENT_TYPE. Total request body must stay under 15MB.",
        "operationId": "PublicJournalEntriesV2Controller_createJournalEntry_v2",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateJournalEntryV2Dto"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Journal entry created successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JournalEntryResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 400
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Bad Request"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 401
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions - API key missing required scopes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 403
                    },
                    "code": {
                      "type": "string",
                      "example": "INSUFFICIENT_PERMISSIONS"
                    },
                    "details": {
                      "type": "object",
                      "properties": {
                        "reason": {
                          "type": "string",
                          "example": "api_key_missing_required_scope"
                        },
                        "requiredScopes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "example": [
                            "usage:write"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "OAuth2ClientCredentials": []
          }
        ],
        "summary": "Create a journal entry (v2)",
        "tags": [
          "Journal Entries (v2)"
        ]
      }
    },
    "/v2/journal-entries/batch": {
      "post": {
        "description": "Atomically creates 1–100 journal entries in a single transaction.\nEach entry follows the same restrictions as POST /api/v2/journal-entries:\nfor CUSTOMER_*/SUPPLIER_* types submit only the counter-side lines and the server\nauto-appends the AR/AP leg on the partner group default account.\n\nIf any entry fails validation or persistence the entire batch is rolled back.\njournalCategoryId is validated per entry against the API key's app company —\ncross-tenant or unknown IDs reject the whole batch with 400 JOURNAL_CATEGORY_NOT_FOUND.\n\nAttachments: each entry may include up to 10 base64-encoded `attachments[]`. A failure on any entry\nrolls back the whole batch and deletes every already-uploaded blob — no orphan documents survive.",
        "operationId": "PublicJournalEntriesV2Controller_createBatch_v2",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateJournalEntryV2BatchRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Batch created successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreateJournalEntryV2BatchResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 400
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Bad Request"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 401
                    },
                    "timestamp": {
                      "type": "string",
                      "example": "2025-10-09T15:07:32.736Z"
                    },
                    "path": {
                      "type": "string",
                      "example": "/company"
                    },
                    "message": {
                      "type": "string",
                      "example": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions - API key missing required scopes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "number",
                      "example": 403
                    },
                    "code": {
                      "type": "string",
                      "example": "INSUFFICIENT_PERMISSIONS"
                    },
                    "details": {
                      "type": "object",
                      "properties": {
                        "reason": {
                          "type": "string",
                          "example": "api_key_missing_required_scope"
                        },
                        "requiredScopes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "example": [
                            "usage:write"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "OAuth2ClientCredentials": []
          }
        ],
        "summary": "Create journal entries in batch (v2)",
        "tags": [
          "Journal Entries (v2)"
        ]
      }
    }
  },
  "info": {
    "title": "LedgerBee Public API",
    "description": "The LedgerBee Public API documentation",
    "version": "1.0",
    "contact": {
      "name": "LedgerBee",
      "url": "https://ledgerbee.com",
      "email": "support@ledgerbee.com"
    },
    "license": {
      "name": "Terms & Conditions",
      "url": "https://ledgerbee.com/terms-and-conditions"
    }
  },
  "tags": [
    {
      "name": "Accounts",
      "description": "Account management endpoints"
    },
    {
      "name": "API Key",
      "description": "API key information endpoints"
    },
    {
      "name": "Company",
      "description": "Company information endpoints"
    },
    {
      "name": "Customers",
      "description": "Customer and customer group management endpoints"
    },
    {
      "name": "Dimensions",
      "description": "Dimension categories and values for journal entry tagging"
    },
    {
      "name": "Document Templates",
      "description": "PDF design templates a partner can attach to invoices, quotes and order confirmations."
    },
    {
      "name": "Journal Categories",
      "description": "Journal category management endpoints"
    },
    {
      "name": "Journal Entries",
      "description": "Journal entry creation endpoints"
    },
    {
      "name": "MCP",
      "description": "Model Context Protocol endpoints for AI agents (Streamable-HTTP, JSON-RPC 2.0). See the MCP guide for the tenant-scoped servers, tools, and OAuth flow."
    },
    {
      "name": "Meters",
      "description": "Meter and usage reporting endpoints"
    },
    {
      "name": "Product Groups",
      "description": "Product-group ledger-account mappings. Every product belongs to a group, and the group decides which revenue account a sale posts to per VAT zone (domestic / EU / abroad / domestic-without-VAT)."
    },
    {
      "name": "Product Prices",
      "description": "Prices for catalogue products. A price ID is what an invoice / quote / order-confirmation line references to bill a real product. Covers flat-rate, package, volume, graduated and usage-based (metered) pricing."
    },
    {
      "name": "Products",
      "description": "Catalogue products. Each product belongs to a product group and carries one or more prices."
    },
    {
      "name": "Projects",
      "description": "Project, subproject, and project profit endpoints"
    },
    {
      "name": "Subscriptions",
      "description": "Subscription plan and customer subscription management endpoints"
    },
    {
      "name": "VAT Codes",
      "description": "VAT code and rate endpoints"
    },
    {
      "name": "Webhook Endpoints",
      "description": "Register HTTPS endpoints to receive signed event notifications. Each delivery is signed following the [Standard Webhooks](https://www.standardwebhooks.com/) specification — verify the `webhook-id`, `webhook-timestamp`, and `webhook-signature` headers against the endpoint `secret` (returned once on create / roll-secret) using one of the spec’s drop-in verification libraries instead of implementing the HMAC-SHA256 check yourself."
    }
  ],
  "servers": [
    {
      "url": "https://api.ledgerbee.com/api",
      "description": "LedgerBee Public API"
    }
  ],
  "components": {
    "securitySchemes": {
      "ApiKeyAuth": {
        "type": "apiKey",
        "in": "header",
        "name": "x-api-key",
        "description": "API Key for authentication"
      },
      "OAuth2ClientCredentials": {
        "type": "oauth2",
        "flows": {
          "clientCredentials": {
            "tokenUrl": "/api/v1/auth/token",
            "scopes": {}
          }
        },
        "description": "OAuth2 client credentials flow. Scopes are configured per client in the OAuth Clients UI — any scopes selected here are ignored."
      }
    },
    "schemas": {
      "CompanyResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Unique identifier for the company, uuidv7 based",
            "example": "01234567-89AB-CDEF-0123-456789ABCDEF"
          },
          "name": {
            "type": "string",
            "description": "Company name",
            "example": "Acme Corporation"
          },
          "email": {
            "type": "string",
            "description": "Primary email address",
            "example": "contact@acme.com"
          },
          "vat": {
            "type": "number",
            "description": "VAT number",
            "example": 12345678
          },
          "billingEmail": {
            "type": "string",
            "description": "Billing email address",
            "example": "billing@acme.com"
          },
          "address": {
            "type": "string",
            "description": "Street address",
            "example": "123 Main Street"
          },
          "city": {
            "type": "string",
            "description": "City",
            "example": "Copenhagen"
          },
          "postalCode": {
            "type": "string",
            "description": "Postal code",
            "example": "2100"
          },
          "countryCode": {
            "type": "string",
            "description": "Country code (ISO 3166-1 alpha-2)",
            "example": "DK"
          },
          "phone": {
            "type": "string",
            "description": "Phone number",
            "example": "+45 12 34 56 78"
          },
          "preferredLanguage": {
            "type": "string",
            "description": "Preferred language code",
            "example": "en"
          },
          "contactPersonFirstName": {
            "type": "string",
            "description": "Contact person first name",
            "example": "John"
          },
          "contactPersonLastName": {
            "type": "string",
            "description": "Contact person last name",
            "example": "Doe"
          }
        },
        "required": [
          "id",
          "name",
          "email",
          "address"
        ]
      },
      "RateLimitTierResponse": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "description": "Name of the rate limit tier",
            "example": "short"
          },
          "ttl": {
            "type": "number",
            "description": "Time-to-live in milliseconds for this rate limit tier (0 means no time limit)",
            "example": 1000
          },
          "limit": {
            "type": "number",
            "description": "Maximum number of requests allowed within the TTL window (-1 means unlimited)",
            "example": 3
          }
        },
        "required": [
          "name",
          "ttl",
          "limit"
        ]
      },
      "ApiKeyInfoResponse": {
        "type": "object",
        "properties": {
          "expiresAt": {
            "type": "string",
            "description": "Expiration date and time of the API key",
            "example": "2024-12-31T23:59:59.000Z"
          },
          "ipWhitelist": {
            "description": "List of IP addresses allowed to use this API key",
            "example": [
              "192.168.1.1",
              "10.0.0.1"
            ],
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "scopes": {
            "description": "List of scopes granted to this API key",
            "example": [
              "accounts-read",
              "journal-entries-write"
            ],
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "rateLimitTiers": {
            "description": "Available rate limit tiers for this API key",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/RateLimitTierResponse"
            }
          }
        },
        "required": [
          "rateLimitTiers"
        ]
      },
      "AccountResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The unique identifier of the account",
            "example": "550e8400-e29b-41d4-a716-446655440000"
          },
          "name": {
            "type": "string",
            "description": "Name of the account",
            "example": "Skyldig AM-bidrag"
          },
          "accountNumber": {
            "type": "number",
            "description": "Account type number",
            "example": 1000
          },
          "publicAccountId": {
            "type": "number",
            "description": "Public account id that the account maps to",
            "example": 1000
          },
          "ledgerType": {
            "type": "string",
            "description": "Type of ledger account. Only BALANCE_SHEET and PROFIT_AND_LOSS accounts can be used in journal entries.",
            "enum": [
              "BALANCE_SHEET",
              "HEADING_BREAK",
              "HEADING",
              "PROFIT_AND_LOSS",
              "TOTAL_FROM",
              "TOTAL_INTERVALS"
            ],
            "example": "BALANCE_SHEET"
          },
          "accountClassification": {
            "type": "string",
            "description": "Account classification (ASSET, LIABILITY, EQUITY, REVENUE, EXPENSE)",
            "enum": [
              "ASSET",
              "LIABILITY",
              "EQUITY",
              "REVENUE",
              "EXPENSE"
            ],
            "example": "ASSET",
            "nullable": true
          },
          "controlAccountType": {
            "type": "string",
            "description": "Control account type. ACCOUNTS_RECEIVABLE requires customerId on journal entries, ACCOUNTS_PAYABLE requires vendorId. Null for regular accounts.",
            "enum": [
              "ACCOUNTS_RECEIVABLE",
              "ACCOUNTS_PAYABLE"
            ],
            "example": null,
            "nullable": true
          }
        },
        "required": [
          "id",
          "name",
          "accountNumber",
          "publicAccountId",
          "ledgerType"
        ]
      },
      "CustomerGroupResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The unique identifier of the customer group",
            "example": "550e8400-e29b-41d4-a716-446655440000"
          },
          "number": {
            "type": "string",
            "description": "Customer group number",
            "example": "1"
          },
          "name": {
            "type": "string",
            "description": "Name of the customer group",
            "example": "Domestic Customers"
          },
          "discount": {
            "type": "number",
            "description": "Discount percentage for this customer group",
            "example": 10
          },
          "accountId": {
            "type": "string",
            "description": "The ledger account ID associated with this customer group",
            "example": "550e8400-e29b-41d4-a716-446655440001"
          },
          "accountNumber": {
            "type": "number",
            "description": "The ledger account number associated with this customer group",
            "example": 1100
          },
          "accountName": {
            "type": "string",
            "description": "The ledger account name associated with this customer group",
            "example": "Trade Debtors"
          },
          "metadata": {
            "type": "object",
            "description": "Key-value metadata attached to the customer group",
            "additionalProperties": {
              "type": "string"
            },
            "example": {
              "segment": "enterprise"
            }
          }
        },
        "required": [
          "id",
          "number",
          "name",
          "discount",
          "accountId"
        ]
      },
      "CustomerDepartmentResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The unique identifier of the department",
            "example": "550e8400-e29b-41d4-a716-446655440000"
          },
          "name": {
            "type": "string",
            "description": "Name of the department",
            "example": "Headquarters"
          },
          "isDefault": {
            "type": "boolean",
            "description": "Whether this is the default department for the customer",
            "example": true
          },
          "isActive": {
            "type": "boolean",
            "description": "Whether the department is active",
            "example": true
          },
          "poNumber": {
            "type": "string",
            "description": "Purchase order number",
            "example": "PO-12345"
          },
          "eanNumber": {
            "type": "string",
            "description": "EAN number for e-invoicing",
            "example": "5790000000000"
          },
          "address": {
            "type": "string",
            "description": "Street address",
            "example": "123 Main Street"
          },
          "city": {
            "type": "string",
            "description": "City",
            "example": "Copenhagen"
          },
          "postalCode": {
            "type": "string",
            "description": "Postal code",
            "example": "2100"
          },
          "countryCode": {
            "type": "string",
            "description": "Two-letter country code (ISO 3166-1 alpha-2)",
            "example": "DK"
          }
        },
        "required": [
          "id",
          "name",
          "isDefault",
          "isActive"
        ]
      },
      "CustomerContactResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The unique identifier of the contact",
            "example": "550e8400-e29b-41d4-a716-446655440000"
          },
          "name": {
            "type": "string",
            "description": "Name of the contact",
            "example": "John Doe"
          },
          "email": {
            "type": "string",
            "description": "Email address",
            "example": "john.doe@acme.com"
          },
          "phone": {
            "type": "string",
            "description": "Phone number",
            "example": "+45 12345678"
          },
          "isDefaultForCustomer": {
            "type": "boolean",
            "description": "Whether this is the default contact for the customer",
            "example": true
          }
        },
        "required": [
          "id",
          "name",
          "isDefaultForCustomer"
        ]
      },
      "CustomerResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The unique identifier of the customer",
            "example": "550e8400-e29b-41d4-a716-446655440000"
          },
          "customerNumber": {
            "type": "string",
            "description": "Customer number",
            "example": "C001"
          },
          "customerType": {
            "type": "string",
            "description": "Customer type",
            "enum": [
              "BUSINESS",
              "PRIVATE_PERSON"
            ],
            "example": "BUSINESS"
          },
          "name": {
            "type": "string",
            "description": "Name of the customer",
            "example": "Acme Corporation"
          },
          "vatZone": {
            "type": "string",
            "description": "VAT zone classification",
            "enum": [
              "domestic",
              "eu",
              "abroad",
              "domestic_without_vat"
            ],
            "example": "domestic"
          },
          "customerGroupId": {
            "type": "string",
            "description": "Customer group ID",
            "example": "550e8400-e29b-41d4-a716-446655440001"
          },
          "customerGroupNumber": {
            "type": "string",
            "description": "Customer group number",
            "example": "1"
          },
          "customerGroupName": {
            "type": "string",
            "description": "Customer group name",
            "example": "Domestic Customers"
          },
          "email": {
            "type": "string",
            "description": "Email address",
            "example": "contact@acme.com"
          },
          "phone": {
            "type": "string",
            "description": "Phone number",
            "example": "+45 12345678"
          },
          "address": {
            "type": "string",
            "description": "Street address",
            "example": "123 Main Street"
          },
          "city": {
            "type": "string",
            "description": "City",
            "example": "Copenhagen"
          },
          "postalCode": {
            "type": "string",
            "description": "Postal code",
            "example": "2100"
          },
          "countryCode": {
            "type": "string",
            "description": "Two-letter country code (ISO 3166-1 alpha-2)",
            "example": "DK"
          },
          "vatNumber": {
            "type": "string",
            "description": "VAT registration number",
            "example": "DK12345678"
          },
          "website": {
            "type": "string",
            "description": "Website URL",
            "example": "https://acme.com"
          },
          "externalSystemId": {
            "type": "string",
            "description": "External system identifier for tracking the customer across other systems",
            "example": "crm-12345"
          },
          "creditLimit": {
            "type": "number",
            "description": "Credit limit",
            "example": 50000
          },
          "openingBalance": {
            "type": "number",
            "description": "Opening balance in the company base currency (signed: positive = the customer owes us)",
            "example": 1000
          },
          "paymentTerms": {
            "type": "number",
            "description": "Payment terms in days",
            "example": 30
          },
          "paymentTermType": {
            "type": "string",
            "description": "Payment term type",
            "example": "NET_DAYS",
            "enum": [
              "NET_DAYS",
              "CASH",
              "RUNNING_MONTH_PLUS_DAYS"
            ]
          },
          "defaultCurrency": {
            "type": "string",
            "description": "Default currency code",
            "example": "DKK"
          },
          "isActive": {
            "type": "boolean",
            "description": "Whether the customer is active",
            "example": true
          },
          "parentCustomerId": {
            "type": "string",
            "description": "Parent customer ID. When set, this customer is a child in a parent-child billing relationship. Set together with billingRelationship to change how this customer is billed.",
            "nullable": true,
            "example": "550e8400-e29b-41d4-a716-446655440000"
          },
          "billingRelationship": {
            "type": "string",
            "description": "Billing relationship. `self` = this customer is billed directly. `parent_pays` = the parent customer (set via parentCustomerId) is billed instead.",
            "enum": [
              "self",
              "parent_pays"
            ],
            "example": "self"
          },
          "consolidationMode": {
            "type": "string",
            "description": "Consolidation mode for a parent customer. `single_invoice` = all child subscriptions are consolidated onto one parent invoice on billingDay. `per_child_invoice` = each child receives its own invoice. Only meaningful on parent customers.",
            "enum": [
              "single_invoice",
              "per_child_invoice"
            ],
            "nullable": true
          },
          "billingDay": {
            "type": "number",
            "description": "Day of month (1-28) when the parent consolidated invoice is generated. Required for `single_invoice` consolidation mode.",
            "nullable": true,
            "example": 1
          },
          "includeChildDetailsPdf": {
            "type": "boolean",
            "description": "Whether to attach a zip of per-child detail PDFs when sending consolidated invoices. Only relevant for parent customers in `single_invoice` mode.",
            "example": false
          },
          "parentInvoiceTemplateId": {
            "type": "string",
            "description": "Parent single invoice PDF template override",
            "nullable": true
          },
          "metadata": {
            "type": "object",
            "description": "Key-value metadata attached to the customer",
            "additionalProperties": {
              "type": "string"
            },
            "example": {
              "crmSegment": "enterprise",
              "accountOwner": "jane"
            }
          }
        },
        "required": [
          "id",
          "customerNumber",
          "customerType",
          "name",
          "vatZone",
          "customerGroupId",
          "isActive",
          "billingRelationship",
          "includeChildDetailsPdf"
        ]
      },
      "CreateCustomerRequest": {
        "type": "object",
        "properties": {
          "customerType": {
            "type": "string",
            "enum": [
              "BUSINESS",
              "PRIVATE_PERSON"
            ],
            "example": "BUSINESS",
            "description": "Specifies whether the customer is a business or a private person",
            "default": "BUSINESS"
          },
          "customerNumber": {
            "type": "string",
            "example": "C001",
            "description": "Unique customer number"
          },
          "name": {
            "type": "string",
            "example": "Acme Corporation",
            "description": "Customer name"
          },
          "vatZone": {
            "type": "string",
            "enum": [
              "domestic",
              "eu",
              "abroad",
              "domestic_without_vat"
            ],
            "example": "domestic",
            "description": "VAT zone classification"
          },
          "customerGroupId": {
            "type": "string",
            "example": "550e8400-e29b-41d4-a716-446655440001",
            "description": "Customer group ID"
          },
          "email": {
            "type": "string",
            "example": "contact@acme.com",
            "description": "Email address"
          },
          "phone": {
            "type": "string",
            "example": "+45 12345678",
            "description": "Phone number"
          },
          "address": {
            "type": "string",
            "example": "123 Main Street",
            "description": "Street address"
          },
          "city": {
            "type": "string",
            "example": "Copenhagen",
            "description": "City"
          },
          "postalCode": {
            "type": "string",
            "example": "2100",
            "description": "Postal code"
          },
          "countryCode": {
            "type": "string",
            "example": "DK",
            "description": "Two-letter country code"
          },
          "vatNumber": {
            "type": "string",
            "example": "DK12345678",
            "description": "VAT registration number"
          },
          "website": {
            "type": "string",
            "example": "https://acme.com",
            "description": "Website URL"
          },
          "externalSystemId": {
            "type": "string",
            "example": "crm-12345",
            "description": "External system identifier for tracking the customer across other systems"
          },
          "notes": {
            "type": "string",
            "example": "Key account customer",
            "description": "Additional notes"
          },
          "creditLimit": {
            "type": "number",
            "example": 50000,
            "description": "Credit limit",
            "minimum": 0
          },
          "openingBalance": {
            "type": "number",
            "example": 1000,
            "description": "Opening balance in the company base currency, seeding receivables that predate LedgerBee. Signed: positive = the customer owes us, negative = a credit position."
          },
          "paymentTerms": {
            "type": "number",
            "example": 30,
            "description": "Payment terms in days",
            "minimum": 0
          },
          "paymentTermType": {
            "type": "string",
            "example": "NET_DAYS",
            "description": "Payment term type",
            "enum": [
              "NET_DAYS",
              "CASH",
              "RUNNING_MONTH_PLUS_DAYS"
            ]
          },
          "defaultCurrency": {
            "type": "string",
            "example": "DKK",
            "description": "Default currency code"
          },
          "isActive": {
            "type": "boolean",
            "example": true,
            "description": "Whether the customer is active",
            "default": true
          },
          "parentCustomerId": {
            "type": "string",
            "description": "Parent customer ID. Set when creating this customer as a child in a parent-child billing relationship. Must be combined with billingRelationship = `parent_pays` to route billing to the parent. Send null to create a standalone customer.",
            "nullable": true,
            "example": "550e8400-e29b-41d4-a716-446655440000"
          },
          "billingRelationship": {
            "type": "string",
            "description": "Billing relationship. `self` (default) = this customer is billed directly. `parent_pays` = the parent customer (set via parentCustomerId) is billed instead.",
            "enum": [
              "self",
              "parent_pays"
            ]
          },
          "consolidationMode": {
            "type": "string",
            "description": "Consolidation mode (parent customers only). `single_invoice` = all child subscriptions consolidated onto one invoice on billingDay. `per_child_invoice` = each child receives its own invoice.",
            "enum": [
              "single_invoice",
              "per_child_invoice"
            ],
            "nullable": true
          },
          "billingDay": {
            "type": "number",
            "description": "Day of month (1-28) for the parent consolidated invoice. Required for `single_invoice` consolidation.",
            "nullable": true,
            "example": 1
          },
          "includeChildDetailsPdf": {
            "type": "boolean",
            "description": "Whether to attach a zip of per-child detail PDFs when sending consolidated invoices"
          },
          "parentInvoiceTemplateId": {
            "type": "string",
            "description": "Parent single invoice PDF template override. Send null to clear.",
            "nullable": true
          },
          "metadata": {
            "type": "object",
            "description": "Key-value metadata to attach to the customer. At most 50 entries; keys up to 128 characters, string values up to 500 characters.",
            "additionalProperties": {
              "type": "string"
            },
            "example": {
              "crmSegment": "enterprise"
            }
          }
        },
        "required": [
          "customerType",
          "customerNumber",
          "name",
          "vatZone",
          "customerGroupId",
          "countryCode",
          "defaultCurrency"
        ]
      },
      "CreateCustomerResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The unique identifier of the created customer",
            "example": "550e8400-e29b-41d4-a716-446655440000"
          },
          "customerNumber": {
            "type": "string",
            "description": "Customer number",
            "example": "C001"
          }
        },
        "required": [
          "id",
          "customerNumber"
        ]
      },
      "SubscriptionTransitionItem": {
        "type": "object",
        "properties": {
          "customerSubscriptionId": {
            "type": "string",
            "description": "ID of the customer subscription to transition to parent billing",
            "example": "550e8400-e29b-41d4-a716-446655440000"
          }
        },
        "required": [
          "customerSubscriptionId"
        ]
      },
      "UpdateCustomerRequest": {
        "type": "object",
        "properties": {
          "customerType": {
            "type": "string",
            "enum": [
              "BUSINESS",
              "PRIVATE_PERSON"
            ],
            "example": "BUSINESS",
            "description": "Customer type"
          },
          "customerNumber": {
            "type": "string",
            "example": "C001",
            "description": "Unique customer number"
          },
          "name": {
            "type": "string",
            "example": "Acme Corporation",
            "description": "Customer name"
          },
          "vatZone": {
            "type": "string",
            "enum": [
              "domestic",
              "eu",
              "abroad",
              "domestic_without_vat"
            ],
            "example": "domestic",
            "description": "VAT zone classification"
          },
          "customerGroupId": {
            "type": "string",
            "example": "550e8400-e29b-41d4-a716-446655440001",
            "description": "Customer group ID"
          },
          "email": {
            "type": "string",
            "example": "contact@acme.com",
            "description": "Email address. Send null or empty string to clear.",
            "nullable": true
          },
          "phone": {
            "type": "string",
            "example": "+45 12345678",
            "description": "Phone number"
          },
          "address": {
            "type": "string",
            "example": "123 Main Street",
            "description": "Street address"
          },
          "city": {
            "type": "string",
            "example": "Copenhagen",
            "description": "City"
          },
          "postalCode": {
            "type": "string",
            "example": "2100",
            "description": "Postal code"
          },
          "countryCode": {
            "type": "string",
            "example": "DK",
            "description": "Two-letter country code"
          },
          "vatNumber": {
            "type": "string",
            "example": "DK12345678",
            "description": "VAT registration number"
          },
          "website": {
            "type": "string",
            "example": "https://acme.com",
            "description": "Website URL"
          },
          "externalSystemId": {
            "type": "string",
            "example": "crm-12345",
            "description": "External system identifier for tracking the customer across other systems"
          },
          "notes": {
            "type": "string",
            "example": "Key account customer",
            "description": "Additional notes"
          },
          "creditLimit": {
            "type": "number",
            "example": 50000,
            "description": "Credit limit",
            "minimum": 0
          },
          "openingBalance": {
            "type": "number",
            "example": 1000,
            "description": "Opening balance in the company base currency, seeding receivables that predate LedgerBee. Signed: positive = the customer owes us, negative = a credit position."
          },
          "paymentTerms": {
            "type": "number",
            "example": 30,
            "description": "Payment terms in days",
            "minimum": 0
          },
          "paymentTermType": {
            "type": "string",
            "example": "NET_DAYS",
            "description": "Payment term type",
            "enum": [
              "NET_DAYS",
              "CASH",
              "RUNNING_MONTH_PLUS_DAYS"
            ]
          },
          "defaultCurrency": {
            "type": "string",
            "example": "DKK",
            "description": "Default currency code"
          },
          "isActive": {
            "type": "boolean",
            "example": true,
            "description": "Whether the customer is active"
          },
          "parentCustomerId": {
            "type": "string",
            "description": "Parent customer ID. Send null to detach from parent. Changing this field on a customer with active subscriptions will transition those subscriptions to the parent's billing day with a clean cut at today's date: advance-billed subscriptions receive a credit note for the remaining days of the current period, and arrears-billed subscriptions are invoiced up to the transition date. When transitioning, `subscriptionTransitions` must list every active subscription on this customer as explicit acknowledgement that they will be migrated.",
            "nullable": true,
            "example": "550e8400-e29b-41d4-a716-446655440000"
          },
          "billingRelationship": {
            "type": "string",
            "description": "Billing relationship. Change to `parent_pays` together with parentCustomerId to route billing to the parent.",
            "enum": [
              "self",
              "parent_pays"
            ]
          },
          "consolidationMode": {
            "type": "string",
            "description": "Consolidation mode (parent customers only). Send null to clear.",
            "enum": [
              "single_invoice",
              "per_child_invoice"
            ],
            "nullable": true
          },
          "billingDay": {
            "type": "number",
            "description": "Day of month (1-28) for the parent consolidated invoice. Send null to clear.",
            "nullable": true,
            "example": 1
          },
          "includeChildDetailsPdf": {
            "type": "boolean",
            "description": "Whether to attach a zip of per-child detail PDFs when sending consolidated invoices"
          },
          "parentInvoiceTemplateId": {
            "type": "string",
            "description": "Parent single invoice PDF template override. Send null to clear.",
            "nullable": true
          },
          "subscriptionTransitions": {
            "description": "Subscription transitions — required when changing parentCustomerId, billingRelationship, or consolidationMode on a customer with active subscriptions. Must list every active subscription on this customer as explicit acknowledgement that each one will be migrated to the new billing arrangement with a clean cut at today's date.",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SubscriptionTransitionItem"
            }
          },
          "metadata": {
            "type": "object",
            "description": "Key-value metadata. When provided, REPLACES the customer metadata wholesale — send the complete desired map; an empty object clears all entries. Omit the field to leave metadata unchanged. At most 50 entries; keys up to 128 characters, string values up to 500 characters.",
            "additionalProperties": {
              "type": "string"
            },
            "example": {
              "crmSegment": "enterprise"
            }
          }
        }
      },
      "DimensionValue": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Unique identifier of the dimension value",
            "example": "550e8400-e29b-41d4-a716-446655440000"
          },
          "name": {
            "type": "string",
            "description": "Display name of the dimension value",
            "example": "Marketing",
            "minLength": 2,
            "maxLength": 120
          },
          "parentId": {
            "type": "string",
            "description": "Parent dimension value ID for hierarchical structures. Null for root-level values. Use this to create nested structures like \"Sales > Europe > Denmark\".",
            "example": "550e8400-e29b-41d4-a716-446655440001",
            "nullable": true
          },
          "children": {
            "description": "Child dimension values (nested structure). Only populated in list responses.",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/DimensionValue"
            }
          }
        },
        "required": [
          "id",
          "name"
        ]
      },
      "Dimension": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Unique identifier of the dimension category",
            "example": "550e8400-e29b-41d4-a716-446655440000"
          },
          "name": {
            "type": "string",
            "description": "Display name of the dimension category",
            "example": "Department",
            "minLength": 2,
            "maxLength": 100
          },
          "isUnique": {
            "type": "boolean",
            "description": "When true, only one value from this dimension can be assigned to a journal entry (mutually exclusive). When false, multiple values can be assigned (additive tags). Example: A \"Department\" dimension is typically unique (one department per entry), while a \"Tags\" dimension might allow multiple values.",
            "example": true
          },
          "values": {
            "description": "Available dimension values within this category, organized as a hierarchical tree. Root values have parentId as null, nested values reference their parent.",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/DimensionValue"
            }
          }
        },
        "required": [
          "id",
          "name",
          "isUnique",
          "values"
        ]
      },
      "CreateDimensionRequest": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "description": "Display name for the dimension category. Must be unique within your company. Choose a descriptive name that clearly indicates the categorization purpose.",
            "example": "Cost Center",
            "minLength": 2,
            "maxLength": 100
          },
          "isUnique": {
            "type": "boolean",
            "description": "Whether only one value from this dimension can be assigned to a journal entry. Set to true for mutually exclusive categories (e.g., Department - an entry belongs to exactly one department). Set to false for additive tags (e.g., Tags - an entry can have multiple tags). This constraint is enforced when assigning dimension values to journal entries.",
            "example": true
          }
        },
        "required": [
          "name",
          "isUnique"
        ]
      },
      "DimensionResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Unique identifier of the created/updated dimension category",
            "example": "550e8400-e29b-41d4-a716-446655440000"
          },
          "name": {
            "type": "string",
            "description": "Display name of the dimension category",
            "example": "Department"
          },
          "isUnique": {
            "type": "boolean",
            "description": "Whether only one value from this dimension can be assigned per journal entry",
            "example": true
          }
        },
        "required": [
          "id",
          "name",
          "isUnique"
        ]
      },
      "UpdateDimensionRequest": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "description": "New display name for the dimension category. Must be unique within your company. Changing the name does not affect existing dimension value assignments.",
            "example": "Business Unit",
            "minLength": 2,
            "maxLength": 100
          },
          "isUnique": {
            "type": "boolean",
            "description": "Update the uniqueness constraint for this dimension category. Changing from false to true will fail if any journal entries currently have multiple values assigned from this category. Plan this change carefully as it affects data validation.",
            "example": false
          }
        }
      },
      "CreateDimensionValueRequest": {
        "type": "object",
        "properties": {
          "dimensionId": {
            "type": "string",
            "description": "ID of the dimension category this value belongs to. The category must exist and belong to your company.",
            "example": "550e8400-e29b-41d4-a716-446655440000"
          },
          "name": {
            "type": "string",
            "description": "Display name for the dimension value. Must be unique within the dimension category. Choose descriptive names that will be clear when selecting values in the UI.",
            "example": "Marketing",
            "minLength": 2,
            "maxLength": 120
          },
          "parentId": {
            "type": "string",
            "description": "Parent dimension value ID for creating hierarchical structures. Leave null or omit for root-level values. The parent must exist within the same dimension category. Example: Create \"Europe\" first, then create \"Denmark\" with parentId set to Europe's ID.",
            "example": "550e8400-e29b-41d4-a716-446655440001",
            "nullable": true
          }
        },
        "required": [
          "dimensionId",
          "name"
        ]
      },
      "DimensionValueResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Unique identifier of the created/updated dimension value",
            "example": "550e8400-e29b-41d4-a716-446655440000"
          },
          "name": {
            "type": "string",
            "description": "Display name of the dimension value",
            "example": "Marketing"
          },
          "dimensionId": {
            "type": "string",
            "description": "ID of the dimension category this value belongs to",
            "example": "550e8400-e29b-41d4-a716-446655440001"
          },
          "dimensionName": {
            "type": "string",
            "description": "Name of the dimension category this value belongs to",
            "example": "Department"
          },
          "dimensionIsUnique": {
            "type": "boolean",
            "description": "Whether the parent category enforces single selection",
            "example": true
          },
          "parentId": {
            "type": "string",
            "description": "Parent dimension value ID, if this is a nested value",
            "example": "550e8400-e29b-41d4-a716-446655440002",
            "nullable": true
          }
        },
        "required": [
          "id",
          "name",
          "dimensionId",
          "dimensionName",
          "dimensionIsUnique"
        ]
      },
      "UpdateDimensionValueRequest": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "description": "New display name for the dimension value. Must be unique within the dimension category. Changing the name does not affect existing journal entry assignments.",
            "example": "Digital Marketing",
            "minLength": 2,
            "maxLength": 120
          },
          "parentId": {
            "type": "string",
            "description": "New parent dimension value ID. Set to null to move to root level. The parent must exist within the same dimension category and cannot create circular references (e.g., A cannot be parent of B if B is already an ancestor of A).",
            "example": "550e8400-e29b-41d4-a716-446655440001",
            "nullable": true
          }
        }
      },
      "AttachmentRequest": {
        "type": "object",
        "properties": {
          "filename": {
            "type": "string",
            "description": "Filename with extension",
            "example": "invoice.pdf",
            "maxLength": 255
          },
          "content": {
            "type": "string",
            "description": "Base64-encoded file content. Note: Base64 encoding adds ~33% overhead. Individual files should not exceed 10MB before encoding.",
            "example": "JVBERi0xLjQKJeLjz9MKMyAwIG9iago8PC..."
          },
          "mimeType": {
            "type": "string",
            "description": "MIME type of the file",
            "example": "application/pdf",
            "enum": [
              "application/pdf",
              "image/jpeg",
              "image/png",
              "image/heic",
              "image/heif",
              "image/bmp",
              "image/tiff",
              "application/zip",
              "application/x-zip-compressed",
              "message/rfc822"
            ]
          }
        },
        "required": [
          "filename",
          "content",
          "mimeType"
        ]
      },
      "DraftSplitEntryLine": {
        "type": "object",
        "properties": {
          "accountId": {
            "type": "string",
            "description": "Account ID for this line (UUID). Optional for drafts — empty lines (type + amount with no account) are persisted as placeholders and must be completed in the platform UI before booking. Cannot be a heading or total account when provided.",
            "example": "550e8400-e29b-41d4-a716-446655440000"
          },
          "type": {
            "type": "string",
            "description": "Transaction type for this line (debit or credit)",
            "enum": [
              "debit",
              "credit"
            ],
            "example": "debit"
          },
          "amount": {
            "type": "number",
            "description": "Amount for this line (must be non-negative)",
            "example": 500
          },
          "vatCodeId": {
            "type": "string",
            "description": "VAT/Tax code ID for this line (UUID)",
            "example": "550e8400-e29b-41d4-a716-446655440000"
          },
          "description": {
            "type": "string",
            "description": "Optional per-line memo (max 500 characters). Persisted on the draft line and carried onto the booked ledger transaction when the draft is booked.",
            "example": "Consulting hours — March",
            "maxLength": 500
          },
          "tagIds": {
            "description": "Dimension tag IDs to attach to this specific line. Per-line `tagIds` MUST come from single-select (dimension) categories — multi-select tags belong at the entry-level `tagIds` instead.",
            "example": [
              "550e8400-e29b-41d4-a716-446655440003"
            ],
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        },
        "required": [
          "type",
          "amount"
        ]
      },
      "CreateDraftJournalEntryRequest": {
        "type": "object",
        "properties": {
          "accountId": {
            "type": "string",
            "description": "Primary account ID (UUID). Cannot be a heading or total account. For typed entries (supplier_invoice, customer_invoice, etc.), must have appropriate account classification.",
            "example": "550e8400-e29b-41d4-a716-446655440000"
          },
          "contraAccountId": {
            "type": "string",
            "description": "Contra account ID (UUID). Optional for drafts — partial drafts (primary line only) are allowed and must be completed in the platform UI before booking. Cannot be a heading or total account.",
            "example": "550e8400-e29b-41d4-a716-446655440001"
          },
          "date": {
            "type": "string",
            "description": "Date of the journal entry in YYYY-MM-DD format",
            "example": "2026-01-15"
          },
          "amount": {
            "type": "number",
            "description": "Amount of the transaction (must be positive)",
            "example": 1000
          },
          "entryType": {
            "type": "string",
            "description": "Entry type determines the journal type and enforces account classification rules. Account classification requirements: supplier_invoice: account=EXPENSE|ASSET, contraAccount=LIABILITY; supplier_payment: account=LIABILITY, contraAccount=ASSET; customer_invoice: account=ASSET, contraAccount=REVENUE; customer_payment: account=ASSET, contraAccount=ASSET; journal: no restrictions. Legacy values \"invoice\" and \"payment\" map to supplier types.",
            "enum": [
              "journal",
              "invoice",
              "payment",
              "supplier_invoice",
              "supplier_payment",
              "customer_invoice",
              "customer_payment"
            ],
            "example": "supplier_invoice",
            "default": "journal"
          },
          "type": {
            "type": "string",
            "description": "Transaction type (debit or credit)",
            "enum": [
              "debit",
              "credit"
            ],
            "example": "debit",
            "default": "debit"
          },
          "description": {
            "type": "string",
            "description": "Description of the journal entry",
            "example": "Office supplies purchase"
          },
          "reference": {
            "type": "string",
            "description": "Reference number or identifier",
            "example": "REF-2026-001"
          },
          "currency": {
            "type": "string",
            "description": "Currency code (defaults to DKK)",
            "example": "DKK",
            "default": "DKK"
          },
          "customerId": {
            "type": "string",
            "description": "Customer ID (UUID) for customer-related entries",
            "example": "550e8400-e29b-41d4-a716-446655440002"
          },
          "vendorId": {
            "type": "string",
            "description": "Vendor ID (UUID). Required for supplier_invoice / supplier_payment entry types, and for any posting that touches an accounts-payable control account.",
            "example": "550e8400-e29b-41d4-a716-446655440003"
          },
          "tagIds": {
            "description": "Tag/Dimension IDs to attach to the journal entry",
            "example": [
              "550e8400-e29b-41d4-a716-446655440003"
            ],
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "vatCodeId": {
            "type": "string",
            "description": "VAT/Tax code ID (UUID). Applied to the primary account unless split entries are used.",
            "example": "550e8400-e29b-41d4-a716-446655440000"
          },
          "attachments": {
            "description": "File attachments (base64-encoded). Maximum 10 attachments per entry. Total request size limit is 15MB.",
            "maxItems": 10,
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AttachmentRequest"
            }
          },
          "splitEntries": {
            "description": "Split entry lines for multi-account drafts. Each line may omit `accountId` to act as a placeholder; the draft is persisted with NULL on those lines and the user completes them in the platform UI. Booking still requires every line to carry a real account and the entry to balance.",
            "minItems": 2,
            "maxItems": 50,
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/DraftSplitEntryLine"
            }
          },
          "externalSystemId": {
            "type": "string",
            "description": "Your own system's id for this draft. Carried onto the booked journal entry. Not unique — several drafts/entries may share one id. Filter the list endpoint by `externalSystemId`.",
            "example": "erp-7f3a2c91",
            "maxLength": 255
          }
        },
        "required": [
          "accountId",
          "date",
          "amount"
        ]
      },
      "CreateDraftJournalEntryBatchRequest": {
        "type": "object",
        "properties": {
          "entries": {
            "description": "Array of draft journal entries to create (1-100 entries per batch)",
            "minItems": 1,
            "maxItems": 100,
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CreateDraftJournalEntryRequest"
            }
          }
        },
        "required": [
          "entries"
        ]
      },
      "DraftSplitEntryLineResponse": {
        "type": "object",
        "properties": {
          "accountId": {
            "type": "string",
            "description": "Account ID",
            "example": "550e8400-e29b-41d4-a716-446655440000"
          },
          "type": {
            "type": "string",
            "description": "Transaction type (debit or credit)",
            "example": "debit"
          },
          "amount": {
            "type": "number",
            "description": "Amount for this line in transaction currency",
            "example": 500
          },
          "vatCodeId": {
            "type": "string",
            "description": "VAT/Tax code ID",
            "example": "550e8400-e29b-41d4-a716-446655440000"
          },
          "description": {
            "type": "string",
            "description": "Per-line memo",
            "example": "Consulting hours — March"
          },
          "tagIds": {
            "description": "Tag/Dimension IDs attached to this line. Per-line dimensions override the entry-level `tagIds` on this specific ledger transaction.",
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        },
        "required": [
          "accountId",
          "type",
          "amount"
        ]
      },
      "DraftJournalEntryResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Draft journal entry ID",
            "example": "550e8400-e29b-41d4-a716-446655440000"
          },
          "date": {
            "type": "string",
            "description": "Date in YYYY-MM-DD format",
            "example": "2026-01-15"
          },
          "documentDate": {
            "type": "string",
            "description": "Document date (date on the invoice/voucher). Null when not set.",
            "example": "2026-01-15"
          },
          "amount": {
            "type": "number",
            "description": "Denormalized amount in base/functional currency (e.g. DKK). Computed as MAX(debitTotal, creditTotal) from lines, converted via exchangeRate.",
            "example": 1000
          },
          "currency": {
            "type": "string",
            "description": "Currency code",
            "example": "DKK"
          },
          "description": {
            "type": "string",
            "description": "Description",
            "example": "Office supplies purchase"
          },
          "reference": {
            "type": "string",
            "description": "Reference number",
            "example": "REF-2026-001"
          },
          "externalSystemId": {
            "type": "string",
            "description": "Your own system's id for this draft, when set. Not unique. null when unset or cleared.",
            "example": "erp-7f3a2c91",
            "nullable": true
          },
          "journalType": {
            "type": "string",
            "description": "Journal type",
            "example": "JOURNAL_ENTRY"
          },
          "type": {
            "type": "string",
            "description": "Transaction type (debit or credit)",
            "example": "debit"
          },
          "accountId": {
            "type": "string",
            "description": "Primary account ID",
            "example": "550e8400-e29b-41d4-a716-446655440000"
          },
          "contraAccountId": {
            "type": "string",
            "description": "Contra account ID",
            "example": "550e8400-e29b-41d4-a716-446655440001"
          },
          "customerId": {
            "type": "string",
            "description": "Customer ID",
            "example": "550e8400-e29b-41d4-a716-446655440002"
          },
          "vendorId": {
            "type": "string",
            "description": "Vendor ID",
            "example": "550e8400-e29b-41d4-a716-446655440003"
          },
          "vatCodeId": {
            "type": "string",
            "description": "VAT/Tax code ID",
            "example": "550e8400-e29b-41d4-a716-446655440000"
          },
          "tagIds": {
            "description": "Tag/Dimension IDs",
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "documentRefs": {
            "description": "Document IDs attached to the draft",
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "splitEntries": {
            "description": "Split entry lines",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/DraftSplitEntryLineResponse"
            }
          },
          "status": {
            "type": "string",
            "description": "Always \"DRAFT\" for draft journal entries",
            "example": "DRAFT"
          },
          "createdAt": {
            "type": "string",
            "description": "Creation timestamp",
            "example": "2026-01-15T10:30:00.000Z"
          },
          "updatedAt": {
            "type": "string",
            "description": "Last update timestamp",
            "example": "2026-01-15T10:30:00.000Z"
          }
        },
        "required": [
          "id",
          "date",
          "amount",
          "currency",
          "journalType",
          "status",
          "createdAt",
          "updatedAt"
        ]
      },
      "CreateDraftJournalEntryBatchResponse": {
        "type": "object",
        "properties": {
          "totalCreated": {
            "type": "number",
            "description": "Number of draft entries successfully created",
            "example": 5
          },
          "entries": {
            "description": "Details of all created draft journal entries",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/DraftJournalEntryResponse"
            }
          }
        },
        "required": [
          "totalCreated",
          "entries"
        ]
      },
      "ListDraftJournalEntriesResponse": {
        "type": "object",
        "properties": {
          "data": {
            "description": "List of draft journal entries",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/DraftJournalEntryResponse"
            }
          },
          "total": {
            "type": "number",
            "description": "Total number of matching drafts",
            "example": 42
          },
          "page": {
            "type": "number",
            "description": "Current page number",
            "example": 1
          },
          "limit": {
            "type": "number",
            "description": "Items per page",
            "example": 25
          },
          "totalPages": {
            "type": "number",
            "description": "Total number of pages",
            "example": 2
          }
        },
        "required": [
          "data",
          "total",
          "page",
          "limit",
          "totalPages"
        ]
      },
      "JournalEntryResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Unique identifier of the created journal entry",
            "example": "550e8400-e29b-41d4-a716-446655440000"
          },
          "entryNumber": {
            "type": "string",
            "description": "Entry number assigned to the journal entry",
            "example": "JE-00001"
          },
          "date": {
            "type": "string",
            "description": "Date of the journal entry",
            "example": "2026-01-15"
          },
          "documentDate": {
            "type": "string",
            "description": "Document date (date on the invoice/voucher). Null for legacy entries.",
            "example": "2026-01-15"
          },
          "amount": {
            "type": "number",
            "description": "Amount of the transaction",
            "example": 1000
          },
          "currency": {
            "type": "string",
            "description": "Currency code",
            "example": "DKK"
          },
          "description": {
            "type": "string",
            "description": "Description of the journal entry",
            "example": "Office supplies purchase"
          },
          "reference": {
            "type": "string",
            "description": "Reference number",
            "example": "REF-2026-001"
          },
          "externalSystemId": {
            "type": "string",
            "description": "Your own system's id for this entry, when set. Not unique — several entries may share one id.",
            "example": "erp-7f3a2c91"
          },
          "journalType": {
            "type": "string",
            "description": "Journal type",
            "example": "JOURNAL_ENTRY"
          },
          "type": {
            "type": "string",
            "description": "Transaction type",
            "example": "debit"
          },
          "status": {
            "type": "string",
            "description": "Status of the journal entry",
            "example": "POSTED"
          },
          "accountId": {
            "type": "string",
            "description": "Primary account ID",
            "example": "550e8400-e29b-41d4-a716-446655440000"
          },
          "contraAccountId": {
            "type": "string",
            "description": "Contra account ID",
            "example": "550e8400-e29b-41d4-a716-446655440001"
          },
          "customerId": {
            "type": "string",
            "description": "Customer ID if applicable",
            "example": "550e8400-e29b-41d4-a716-446655440002"
          },
          "vendorId": {
            "type": "string",
            "description": "Vendor ID if applicable",
            "example": "550e8400-e29b-41d4-a716-446655440003"
          },
          "vatCodeId": {
            "type": "string",
            "description": "VAT/Tax code ID if applicable",
            "example": "550e8400-e29b-41d4-a716-446655440000"
          },
          "tagIds": {
            "description": "Tag IDs attached to the entry",
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "documentRefs": {
            "description": "Document IDs attached to the entry",
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "createdAt": {
            "type": "string",
            "description": "Timestamp when the entry was created",
            "example": "2026-01-15T10:30:00.000Z"
          }
        },
        "required": [
          "id",
          "entryNumber",
          "date",
          "amount",
          "currency",
          "journalType",
          "type",
          "status",
          "accountId",
          "createdAt"
        ]
      },
      "SplitEntryLine": {
        "type": "object",
        "properties": {
          "accountId": {
            "type": "string",
            "description": "Account ID for this line (UUID). Cannot be a heading or total account.",
            "example": "550e8400-e29b-41d4-a716-446655440000"
          },
          "type": {
            "type": "string",
            "description": "Transaction type for this line (debit or credit)",
            "enum": [
              "debit",
              "credit"
            ],
            "example": "debit"
          },
          "amount": {
            "type": "number",
            "description": "Amount for this line (must be positive)",
            "example": 500
          },
          "vatCodeId": {
            "type": "string",
            "description": "VAT/Tax code ID for this line (UUID)",
            "example": "550e8400-e29b-41d4-a716-446655440000"
          },
          "description": {
            "type": "string",
            "description": "Optional per-line memo (max 500 characters). Stored on the booked ledger transaction for this line, separate from the entry-level `description`.",
            "example": "Consulting hours — March",
            "maxLength": 500
          },
          "tagIds": {
            "description": "Dimension tag IDs to attach to this specific line. Per-line `tagIds` MUST come from single-select (dimension) categories — multi-select tags belong at the entry-level `tagIds` instead. Each dimension category may appear at most once per line. The booked ledger transaction is tagged with these IDs and VAT derivatives inherit automatically. Validation: a non-dimension tag rejects with `JOURNAL_TAG_LINE_TAG_NOT_A_DIMENSION`; a repeated category rejects with `JOURNAL_TAG_DUPLICATE_LINE_DIMENSION_CATEGORY`.",
            "example": [
              "550e8400-e29b-41d4-a716-446655440003"
            ],
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        },
        "required": [
          "accountId",
          "type",
          "amount"
        ]
      },
      "CreateDraftJournalEntryV2Request": {
        "type": "object",
        "properties": {
          "entryType": {
            "type": "string",
            "description": "Journal type. For CUSTOMER_INVOICE / CUSTOMER_PAYMENT / SUPPLIER_INVOICE / SUPPLIER_PAYMENT the AR/AP leg is appended automatically; do not include it in `lines`.",
            "enum": [
              "journal",
              "invoice",
              "payment",
              "supplier_invoice",
              "supplier_payment",
              "customer_invoice",
              "customer_payment"
            ]
          },
          "date": {
            "type": "string",
            "description": "Posting date (YYYY-MM-DD)."
          },
          "originalAmount": {
            "type": "number",
            "description": "Original amount of the invoice / payment. Sign carries direction: positive = invoice / payment, negative = credit-note / refund."
          },
          "customerId": {
            "type": "string",
            "description": "Customer reference. Required for CUSTOMER_* types."
          },
          "vendorId": {
            "type": "string",
            "description": "Vendor reference. Required for SUPPLIER_* types."
          },
          "description": {
            "type": "string",
            "description": "Optional human-readable description."
          },
          "reference": {
            "type": "string",
            "description": "Invoice number / external reference."
          },
          "currency": {
            "type": "string",
            "description": "ISO 4217 currency code. Defaults to company currency."
          },
          "lines": {
            "description": "Counter-side lines (revenue / expense / bank / outlay). For locked types do NOT include the AR/AP leg.",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SplitEntryLine"
            }
          },
          "tagIds": {
            "description": "Tag IDs applied at the entry level.",
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "journalCategoryId": {
            "type": "string",
            "description": "Journal category ID (UUID). Must belong to the API key's app company; cross-tenant or unknown IDs are rejected with 400 JOURNAL_CATEGORY_NOT_FOUND. When omitted the entry uses the company's default category."
          },
          "attachments": {
            "description": "Inline file attachments (base64-encoded). Same shape and limits as v1: maximum 10 attachments per entry, individual files should not exceed 10MB before encoding, and the total request body (JSON + base64 payload) must stay under 15MB. Each attachment becomes a Document linked to the created journal entry — equivalent to what `GET /api/v1/journal-entries/:id/attachments` returns. Invalid MIME types or malformed base64 reject the whole entry with 400 INVALID_ATTACHMENT_TYPE; in a batch the whole batch rolls back.",
            "maxItems": 10,
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AttachmentRequest"
            }
          },
          "externalSystemId": {
            "type": "string",
            "description": "Your own system's id for this draft. Carried onto the booked journal entry. Not unique — several drafts/entries may share one id. Filter the list endpoint by `externalSystemId`.",
            "example": "erp-7f3a2c91",
            "maxLength": 255
          }
        },
        "required": [
          "entryType",
          "date",
          "originalAmount",
          "lines"
        ]
      },
      "CreateDraftJournalEntryV2BatchRequest": {
        "type": "object",
        "properties": {
          "entries": {
            "minItems": 1,
            "maxItems": 100,
            "description": "Array of 1–100 draft journal entries. Wrapped in a single transaction; one bad entry rolls back the whole batch.",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CreateDraftJournalEntryV2Request"
            }
          }
        },
        "required": [
          "entries"
        ]
      },
      "CreateDraftJournalEntryV2BatchResponse": {
        "type": "object",
        "properties": {
          "totalCreated": {
            "type": "number",
            "description": "Number of drafts created (= entries.length on success)."
          },
          "entries": {
            "description": "Created draft journal entries, ordered to match the request entries[].",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/DraftJournalEntryResponse"
            }
          }
        },
        "required": [
          "totalCreated",
          "entries"
        ]
      },
      "UpdateDraftJournalEntryV2Request": {
        "type": "object",
        "properties": {
          "date": {
            "type": "string",
            "description": "Posting date (YYYY-MM-DD)."
          },
          "originalAmount": {
            "type": "number",
            "description": "Original amount of the invoice / payment. Sign carries direction: positive = invoice / payment, negative = credit-note / refund."
          },
          "customerId": {
            "type": "string",
            "description": "Customer reference. null clears it; omitting keeps it. Changing it reshapes the entry — requires `lines` and re-runs the per-entryType validation (CUSTOMER_* types cannot clear their counterparty).",
            "format": "uuid",
            "nullable": true
          },
          "vendorId": {
            "type": "string",
            "description": "Vendor reference. null clears it; omitting keeps it. Changing it reshapes the entry — requires `lines` and re-runs the per-entryType validation (SUPPLIER_* types cannot clear their counterparty).",
            "format": "uuid",
            "nullable": true
          },
          "description": {
            "type": "string",
            "description": "Optional human-readable description."
          },
          "reference": {
            "type": "string",
            "description": "Invoice number / external reference."
          },
          "currency": {
            "type": "string",
            "description": "ISO 4217 currency code. Defaults to company currency."
          },
          "lines": {
            "description": "Counter-side lines (revenue / expense / bank / outlay). For locked types do NOT include the AR/AP leg.",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SplitEntryLine"
            }
          },
          "tagIds": {
            "description": "Tag IDs applied at the entry level.",
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "journalCategoryId": {
            "type": "string",
            "description": "Journal category ID (UUID). Must belong to the API key's app company; cross-tenant or unknown IDs are rejected with 400 JOURNAL_CATEGORY_NOT_FOUND. When omitted the entry uses the company's default category."
          },
          "externalSystemId": {
            "type": "string",
            "description": "Your own system's id. null clears the value; omitting the field keeps it.",
            "example": "erp-7f3a2c91",
            "maxLength": 255,
            "nullable": true
          }
        }
      },
      "UpdateJournalEntryRequest": {
        "type": "object",
        "properties": {
          "reference": {
            "type": "string",
            "description": "Corrected reference. For invoices this is the invoice number (the anchor is renumbered with it); for payments it is the invoice number the payment settles. Only unmatched entries of the four entity document types accept a reference correction.",
            "example": "INV-1042",
            "maxLength": 255
          },
          "externalSystemId": {
            "type": "string",
            "description": "Your own system's id for this journal entry. Settable on any journal type regardless of match state. Not unique — several entries may carry the same id (e.g. one partner document booked as several entries); filter GET /journal-entries by `externalSystemId` to find all of them. null clears the value; omitting the field keeps it. `reference` does not accept null — it is a matching key, not clearable metadata.",
            "example": "erp-7f3a2c91",
            "maxLength": 255,
            "nullable": true
          }
        }
      },
      "UpdateJournalEntryResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Journal entry ID.",
            "example": "550e8400-e29b-41d4-a716-446655440000"
          },
          "reference": {
            "type": "string",
            "description": "The reference after the update.",
            "nullable": true,
            "example": "INV-1042"
          },
          "externalSystemId": {
            "type": "string",
            "description": "The external system id after the update.",
            "nullable": true,
            "example": "erp-7f3a2c91"
          }
        },
        "required": [
          "id",
          "reference",
          "externalSystemId"
        ]
      },
      "CreateJournalEntryRequest": {
        "type": "object",
        "properties": {
          "accountId": {
            "type": "string",
            "description": "Primary account ID (UUID). Cannot be a heading or total account. For typed entries (supplier_invoice, customer_invoice, etc.), must have appropriate account classification.",
            "example": "550e8400-e29b-41d4-a716-446655440000"
          },
          "contraAccountId": {
            "type": "string",
            "description": "Contra account ID (UUID). Required unless splitEntries is provided. Cannot be a heading or total account. For typed entries, must have appropriate account classification.",
            "example": "550e8400-e29b-41d4-a716-446655440001"
          },
          "date": {
            "type": "string",
            "description": "Date of the journal entry in YYYY-MM-DD format",
            "example": "2026-01-15"
          },
          "amount": {
            "type": "number",
            "description": "Amount of the transaction (must be positive)",
            "example": 1000
          },
          "entryType": {
            "type": "string",
            "description": "Entry type determines the journal type and enforces account classification rules. Account classification requirements: supplier_invoice: account=EXPENSE|ASSET, contraAccount=LIABILITY; supplier_payment: account=LIABILITY, contraAccount=ASSET; customer_invoice: account=ASSET, contraAccount=REVENUE; customer_payment: account=ASSET, contraAccount=ASSET; journal: no restrictions. Legacy values \"invoice\" and \"payment\" map to supplier types.",
            "enum": [
              "journal",
              "invoice",
              "payment",
              "supplier_invoice",
              "supplier_payment",
              "customer_invoice",
              "customer_payment"
            ],
            "example": "supplier_invoice",
            "default": "journal"
          },
          "type": {
            "type": "string",
            "description": "Transaction type (debit or credit)",
            "enum": [
              "debit",
              "credit"
            ],
            "example": "debit",
            "default": "debit"
          },
          "description": {
            "type": "string",
            "description": "Description of the journal entry",
            "example": "Office supplies purchase"
          },
          "reference": {
            "type": "string",
            "description": "Reference number or identifier",
            "example": "REF-2026-001"
          },
          "currency": {
            "type": "string",
            "description": "Currency code (defaults to DKK)",
            "example": "DKK",
            "default": "DKK"
          },
          "customerId": {
            "type": "string",
            "description": "Customer ID (UUID) for customer-related entries",
            "example": "550e8400-e29b-41d4-a716-446655440002"
          },
          "vendorId": {
            "type": "string",
            "description": "Vendor ID (UUID). Required for supplier_invoice / supplier_payment entry types, and for any posting that touches an accounts-payable control account.",
            "example": "550e8400-e29b-41d4-a716-446655440003"
          },
          "tagIds": {
            "description": "Tag/Dimension IDs to attach to the journal entry",
            "example": [
              "550e8400-e29b-41d4-a716-446655440003"
            ],
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "vatCodeId": {
            "type": "string",
            "description": "VAT/Tax code ID (UUID). Applied to the primary account unless split entries are used.",
            "example": "550e8400-e29b-41d4-a716-446655440000"
          },
          "splitEntries": {
            "description": "Split entry lines for multi-account entries. When provided, contraAccountId is not required. Requirements: (1) Total debits must equal total credits; (2) Must have at least one debit AND one credit entry; (3) Minimum 2 lines required; (4) All accounts must be postable (not heading or total accounts). Account classification validation is not applied to split entries.",
            "minItems": 2,
            "maxItems": 50,
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SplitEntryLine"
            }
          },
          "attachments": {
            "description": "File attachments (base64-encoded). Maximum 10 attachments per entry. Total request size limit is 15MB.",
            "maxItems": 10,
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AttachmentRequest"
            }
          }
        },
        "required": [
          "accountId",
          "date",
          "amount"
        ]
      },
      "ReverseJournalEntryRequest": {
        "type": "object",
        "properties": {
          "journalEntryId": {
            "type": "string",
            "description": "UUID of the posted journal entry to reverse.",
            "example": "550e8400-e29b-41d4-a716-446655440000"
          },
          "reversalDate": {
            "type": "string",
            "description": "Date for the reversal posting (YYYY-MM-DD). When omitted, the reversal is dated to the original entry so it lands in the same period. Must fall in an open posting period.",
            "example": "2026-06-01"
          },
          "reason": {
            "type": "string",
            "description": "Free-text reason appended to the reversal description for audit purposes.",
            "example": "Vendor invoice was duplicated",
            "maxLength": 500
          }
        },
        "required": [
          "journalEntryId"
        ]
      },
      "ReverseJournalEntryResponse": {
        "type": "object",
        "properties": {
          "reversalId": {
            "type": "string",
            "description": "Unique identifier of the posted reversal journal entry.",
            "example": "550e8400-e29b-41d4-a716-446655440000"
          }
        },
        "required": [
          "reversalId"
        ]
      },
      "BatchReverseJournalEntriesRequest": {
        "type": "object",
        "properties": {
          "journalEntryIds": {
            "description": "IDs of the journal entries to reverse (1–100). All reversals run in one transaction; one failure rolls back the whole batch. Duplicate IDs are de-duplicated.",
            "example": [
              "550e8400-e29b-41d4-a716-446655440000",
              "550e8400-e29b-41d4-a716-446655440001"
            ],
            "minItems": 1,
            "maxItems": 100,
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "reversalDate": {
            "type": "string",
            "description": "Date for every reversal posting (YYYY-MM-DD). When omitted, each reversal is dated to its own original entry so the pair lands in the same period.",
            "example": "2026-06-01"
          },
          "reason": {
            "type": "string",
            "description": "Free-text reason appended to every reversal description for audit purposes.",
            "example": "Bulk reversal of misclassified subscription invoices",
            "maxLength": 500
          }
        },
        "required": [
          "journalEntryIds"
        ]
      },
      "BatchReverseJournalEntriesResultItem": {
        "type": "object",
        "properties": {
          "originalId": {
            "type": "string",
            "description": "Original journal entry ID supplied in the request.",
            "example": "550e8400-e29b-41d4-a716-446655440000"
          },
          "reversalId": {
            "type": "string",
            "description": "Unique identifier of the posted reversal journal entry.",
            "example": "550e8400-e29b-41d4-a716-446655440010"
          }
        },
        "required": [
          "originalId",
          "reversalId"
        ]
      },
      "BatchReverseJournalEntriesResponse": {
        "type": "object",
        "properties": {
          "totalReversed": {
            "type": "number",
            "description": "Number of reversals posted. Equals the count of unique IDs in the request on success.",
            "example": 2
          },
          "results": {
            "description": "Result rows pairing each original ID with its newly created reversal ID.",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/BatchReverseJournalEntriesResultItem"
            }
          }
        },
        "required": [
          "totalReversed",
          "results"
        ]
      },
      "ListJournalEntriesResponse": {
        "type": "object",
        "properties": {
          "data": {
            "description": "List of journal entries",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/JournalEntryResponse"
            }
          },
          "total": {
            "type": "number",
            "description": "Total number of matching entries",
            "example": 150
          },
          "page": {
            "type": "number",
            "description": "Current page number",
            "example": 1
          },
          "limit": {
            "type": "number",
            "description": "Number of items per page",
            "example": 25
          },
          "totalPages": {
            "type": "number",
            "description": "Total number of pages",
            "example": 6
          }
        },
        "required": [
          "data",
          "total",
          "page",
          "limit",
          "totalPages"
        ]
      },
      "JournalEntryAttachmentResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Unique identifier of the attachment/document",
            "example": "550e8400-e29b-41d4-a716-446655440000"
          },
          "filename": {
            "type": "string",
            "description": "Original filename of the attachment",
            "example": "invoice.pdf"
          },
          "contentType": {
            "type": "string",
            "description": "MIME type of the attachment",
            "example": "application/pdf"
          },
          "fileSize": {
            "type": "number",
            "description": "File size in bytes",
            "example": 102400
          },
          "content": {
            "type": "string",
            "description": "Base64-encoded file content",
            "example": "JVBERi0xLjQKJeLjz9MKMyAwIG9iago8PC..."
          },
          "createdAt": {
            "type": "string",
            "description": "Timestamp when the attachment was created",
            "example": "2026-01-15T10:30:00.000Z"
          }
        },
        "required": [
          "id",
          "filename",
          "contentType",
          "fileSize",
          "content",
          "createdAt"
        ]
      },
      "JournalEntryAttachmentsListResponse": {
        "type": "object",
        "properties": {
          "journalEntryId": {
            "type": "string",
            "description": "Journal entry ID the attachments belong to",
            "example": "550e8400-e29b-41d4-a716-446655440000"
          },
          "attachments": {
            "description": "List of attachments",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/JournalEntryAttachmentResponse"
            }
          }
        },
        "required": [
          "journalEntryId",
          "attachments"
        ]
      },
      "CreateJournalEntryV2Dto": {
        "type": "object",
        "properties": {
          "entryType": {
            "type": "string",
            "description": "Journal type. For CUSTOMER_INVOICE / CUSTOMER_PAYMENT / SUPPLIER_INVOICE / SUPPLIER_PAYMENT the AR/AP leg is appended automatically; do not include it in `lines`.",
            "enum": [
              "journal",
              "invoice",
              "payment",
              "supplier_invoice",
              "supplier_payment",
              "customer_invoice",
              "customer_payment"
            ]
          },
          "date": {
            "type": "string",
            "description": "Posting date (YYYY-MM-DD)."
          },
          "originalAmount": {
            "type": "number",
            "description": "Original amount of the invoice / payment. Sign carries direction: positive = invoice / payment, negative = credit-note / refund."
          },
          "customerId": {
            "type": "string",
            "description": "Customer reference. Required for CUSTOMER_* types."
          },
          "vendorId": {
            "type": "string",
            "description": "Vendor reference. Required for SUPPLIER_* types."
          },
          "description": {
            "type": "string",
            "description": "Optional human-readable description."
          },
          "reference": {
            "type": "string",
            "description": "Invoice number / external reference."
          },
          "currency": {
            "type": "string",
            "description": "ISO 4217 currency code. Defaults to company currency."
          },
          "lines": {
            "description": "Counter-side lines (revenue / expense / bank / outlay). For locked types do NOT include the AR/AP leg.",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SplitEntryLine"
            }
          },
          "tagIds": {
            "description": "Tag IDs applied at the entry level.",
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "journalCategoryId": {
            "type": "string",
            "description": "Journal category ID (UUID). Must belong to the API key's app company; cross-tenant or unknown IDs are rejected with 400 JOURNAL_CATEGORY_NOT_FOUND. When omitted the entry uses the company's default category."
          },
          "attachments": {
            "description": "Inline file attachments (base64-encoded). Same shape and limits as v1: maximum 10 attachments per entry, individual files should not exceed 10MB before encoding, and the total request body (JSON + base64 payload) must stay under 15MB. Each attachment becomes a Document linked to the created journal entry — equivalent to what `GET /api/v1/journal-entries/:id/attachments` returns. Invalid MIME types or malformed base64 reject the whole entry with 400 INVALID_ATTACHMENT_TYPE; in a batch the whole batch rolls back.",
            "maxItems": 10,
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AttachmentRequest"
            }
          }
        },
        "required": [
          "entryType",
          "date",
          "originalAmount",
          "lines"
        ]
      },
      "CreateJournalEntryV2BatchRequest": {
        "type": "object",
        "properties": {
          "entries": {
            "minItems": 1,
            "maxItems": 100,
            "description": "Array of 1–100 journal entries. Wrapped in a single transaction; one bad entry rolls back the whole batch.",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CreateJournalEntryV2Dto"
            }
          }
        },
        "required": [
          "entries"
        ]
      },
      "CreateJournalEntryV2BatchResponse": {
        "type": "object",
        "properties": {
          "totalCreated": {
            "type": "number",
            "description": "Number of journal entries created (= entries.length on success)."
          },
          "entries": {
            "description": "Created journal entries, ordered to match the request entries[].",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/JournalEntryResponse"
            }
          }
        },
        "required": [
          "totalCreated",
          "entries"
        ]
      },
      "CreateJournalEntryBatchRequest": {
        "type": "object",
        "properties": {
          "entries": {
            "description": "Array of journal entries to create (1-100 entries per batch)",
            "minItems": 1,
            "maxItems": 100,
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CreateJournalEntryRequest"
            }
          }
        },
        "required": [
          "entries"
        ]
      },
      "CreateJournalEntryBatchResponse": {
        "type": "object",
        "properties": {
          "totalCreated": {
            "type": "number",
            "description": "Number of entries successfully created",
            "example": 5
          },
          "entries": {
            "description": "Details of all created journal entries",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/JournalEntryResponse"
            }
          }
        },
        "required": [
          "totalCreated",
          "entries"
        ]
      },
      "JournalCategoryResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The unique identifier of the journal category",
            "example": "550e8400-e29b-41d4-a716-446655440000"
          },
          "name": {
            "type": "string",
            "description": "Name of the journal category",
            "example": "General Journal"
          },
          "isDefault": {
            "type": "boolean",
            "description": "Whether this is the default journal category",
            "example": true
          },
          "allowedJournalTypes": {
            "description": "Allowed journal entry types for this journal category",
            "example": [
              "JOURNAL_ENTRY",
              "SUPPLIER_INVOICE",
              "SUPPLIER_PAYMENT",
              "CUSTOMER_INVOICE",
              "CUSTOMER_PAYMENT"
            ],
            "type": "array",
            "items": {
              "type": "array"
            }
          }
        },
        "required": [
          "id",
          "name",
          "isDefault",
          "allowedJournalTypes"
        ]
      },
      "MeterSubscriptionProductDTO": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Product ID",
            "example": "550e8400-e29b-41d4-a716-446655440000"
          },
          "name": {
            "type": "string",
            "description": "Product name",
            "example": "API Calls Package"
          },
          "productNumber": {
            "type": "string",
            "description": "Product number",
            "example": "PROD-001"
          }
        },
        "required": [
          "id",
          "name",
          "productNumber"
        ]
      },
      "MeterSubscriptionDTO": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Subscription ID",
            "example": "550e8400-e29b-41d4-a716-446655440000"
          },
          "name": {
            "type": "string",
            "description": "Subscription name",
            "example": "Enterprise Plan"
          },
          "status": {
            "type": "string",
            "description": "Subscription status",
            "example": "active"
          },
          "products": {
            "description": "Products in this subscription that use the meter",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/MeterSubscriptionProductDTO"
            }
          }
        },
        "required": [
          "id",
          "name",
          "status",
          "products"
        ]
      },
      "MeterSubscriptionsResponseDTO": {
        "type": "object",
        "properties": {
          "meterId": {
            "type": "string",
            "description": "Meter ID",
            "example": "550e8400-e29b-41d4-a716-446655440000"
          },
          "meterName": {
            "type": "string",
            "description": "Meter name",
            "example": "api_calls"
          },
          "subscriptions": {
            "description": "Subscriptions with products using this meter",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/MeterSubscriptionDTO"
            }
          }
        },
        "required": [
          "meterId",
          "meterName",
          "subscriptions"
        ]
      },
      "PaymentMethodResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Unique identifier of the payment method",
            "example": "019D1234-ABCD-7000-8000-123456789ABC"
          },
          "customerId": {
            "type": "string",
            "description": "Customer ID this payment method belongs to",
            "example": "019CBD16-4BFF-766B-BAD7-2F7C36DC3377"
          },
          "provider": {
            "type": "string",
            "description": "Payment provider",
            "enum": [
              "ONPAY",
              "STRIPE"
            ],
            "example": "ONPAY"
          },
          "label": {
            "type": "string",
            "description": "Human-readable label for the payment method",
            "example": "Dankort •••• 1234"
          },
          "cardMask": {
            "type": "string",
            "description": "Masked card number",
            "example": "457199XXXXXX1234"
          },
          "cardType": {
            "type": "string",
            "description": "Card type as reported by the provider",
            "example": "dankort"
          },
          "expiryMonth": {
            "type": "number",
            "description": "Card expiry month",
            "example": 12
          },
          "expiryYear": {
            "type": "number",
            "description": "Card expiry year",
            "example": 2029
          },
          "isDefault": {
            "type": "boolean",
            "description": "Whether this is the default payment method for the customer",
            "example": false
          },
          "status": {
            "type": "string",
            "description": "Current status of the payment method",
            "enum": [
              "ACTIVE",
              "EXPIRED",
              "CANCELLED"
            ],
            "example": "ACTIVE"
          },
          "createdAt": {
            "type": "string",
            "description": "When the payment method was created",
            "example": "2026-03-25T10:30:00.000Z"
          }
        },
        "required": [
          "id",
          "customerId",
          "provider",
          "label",
          "isDefault",
          "status",
          "createdAt"
        ]
      },
      "CreateCardSaveLinkRequest": {
        "type": "object",
        "properties": {
          "provider": {
            "type": "string",
            "description": "Payment provider to use for saving the card",
            "enum": [
              "ONPAY",
              "STRIPE"
            ],
            "example": "ONPAY"
          }
        },
        "required": [
          "provider"
        ]
      },
      "PaymentLinkResponse": {
        "type": "object",
        "properties": {
          "url": {
            "type": "string",
            "description": "URL to the payment provider window. Send this to your customer.",
            "example": "https://onpay.io/window/v3/ce8490fa-282e-11f1-a569-11b5d69909e2?k=FFtXYUNXxkh"
          },
          "expiresAt": {
            "type": "string",
            "description": "When the payment link expires",
            "example": "2026-03-25T11:30:00.000Z"
          }
        },
        "required": [
          "url",
          "expiresAt"
        ]
      },
      "ApplyPaymentMethodToSubscriptionsDto": {
        "type": "object",
        "properties": {
          "enableAutomaticBilling": {
            "type": "boolean",
            "description": "Whether to enable automatic billing on the subscriptions"
          }
        },
        "required": [
          "enableAutomaticBilling"
        ]
      },
      "PublicSubscriptionPlanPhaseProduct": {
        "type": "object",
        "properties": {
          "priceId": {
            "type": "string",
            "description": "Price ID of the product",
            "example": "550e8400-e29b-41d4-a716-446655440000"
          },
          "quantity": {
            "type": "number",
            "description": "Quantity for the product",
            "example": 1
          },
          "customPrice": {
            "type": "string",
            "description": "Custom unit price override",
            "example": "89.99"
          }
        },
        "required": [
          "priceId"
        ]
      },
      "PublicSubscriptionPlanPhase": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Phase ID",
            "example": "550e8400-e29b-41d4-a716-446655440000"
          },
          "sequence": {
            "type": "number",
            "description": "Sequence order of the phase (1-based)",
            "example": 1
          },
          "name": {
            "type": "string",
            "description": "Phase name",
            "example": "Intro promo"
          },
          "discountType": {
            "type": "string",
            "description": "Type of discount applied during the phase",
            "enum": [
              "none",
              "percentage"
            ],
            "example": "percentage"
          },
          "discountValue": {
            "type": "string",
            "description": "Discount value for the phase",
            "example": "10.00"
          },
          "durationValue": {
            "type": "number",
            "description": "Phase duration value",
            "example": 3
          },
          "durationUnit": {
            "type": "string",
            "description": "Phase duration unit",
            "enum": [
              "day",
              "week",
              "month",
              "year"
            ],
            "example": "month"
          },
          "products": {
            "description": "Products for this phase",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PublicSubscriptionPlanPhaseProduct"
            }
          }
        },
        "required": [
          "id",
          "sequence",
          "discountType",
          "products"
        ]
      },
      "PublicSubscriptionPlanResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Subscription plan ID",
            "example": "550e8400-e29b-41d4-a716-446655440000"
          },
          "name": {
            "type": "string",
            "description": "Subscription plan name",
            "example": "Premium Plan"
          },
          "description": {
            "type": "string",
            "description": "Subscription plan description",
            "example": "Our premium subscription plan with all features"
          },
          "isActive": {
            "type": "boolean",
            "description": "Whether the subscription plan is active",
            "example": true
          },
          "currency": {
            "type": "string",
            "description": "Currency code (ISO 4217)",
            "example": "DKK"
          },
          "defaultBillingDirection": {
            "type": "string",
            "description": "Default billing direction for new customer subscriptions",
            "enum": [
              "advance",
              "arrears"
            ],
            "example": "advance"
          },
          "phases": {
            "description": "Phases configured for this plan",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PublicSubscriptionPlanPhase"
            }
          },
          "createdAt": {
            "type": "string",
            "description": "Date the plan was created",
            "example": "2024-01-01T00:00:00.000Z"
          },
          "updatedAt": {
            "type": "string",
            "description": "Date the plan was last updated",
            "example": "2024-01-01T00:00:00.000Z"
          }
        },
        "required": [
          "id",
          "name",
          "isActive",
          "currency",
          "defaultBillingDirection",
          "phases",
          "createdAt",
          "updatedAt"
        ]
      },
      "PublicListSubscriptionPlansResponse": {
        "type": "object",
        "properties": {
          "data": {
            "description": "List of subscription plans",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PublicSubscriptionPlanResponse"
            }
          },
          "total": {
            "type": "number",
            "description": "Total number of subscription plans matching the query",
            "example": 42
          },
          "page": {
            "type": "number",
            "description": "Current page number (1-indexed)",
            "example": 1
          },
          "limit": {
            "type": "number",
            "description": "Maximum number of items per page",
            "example": 25
          },
          "totalPages": {
            "type": "number",
            "description": "Total number of pages available",
            "example": 2
          }
        },
        "required": [
          "data",
          "total",
          "page",
          "limit",
          "totalPages"
        ]
      },
      "PublicCancelSubscriptionRequest": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Customer subscription ID to cancel",
            "example": "550e8400-e29b-41d4-a716-446655440000"
          },
          "strategy": {
            "type": "string",
            "description": "Cancellation strategy",
            "enum": [
              "immediately",
              "end_of_cycle",
              "specific_date",
              "clear_schedule"
            ],
            "example": "end_of_cycle"
          },
          "effectiveDate": {
            "type": "string",
            "description": "Effective churn date (ISO 8601). Required when strategy is SPECIFIC_DATE.",
            "example": "2024-06-30"
          },
          "refundBehavior": {
            "type": "string",
            "description": "Refund behavior when canceling immediately",
            "enum": [
              "none",
              "last_invoice",
              "prorated"
            ],
            "example": "none",
            "default": "none"
          },
          "cancellationReason": {
            "type": "string",
            "description": "Optional reason for cancelling the subscription",
            "example": "Customer requested downgrade"
          }
        },
        "required": [
          "id",
          "strategy"
        ]
      },
      "PublicCustomerSubscriptionResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Customer subscription ID",
            "example": "550e8400-e29b-41d4-a716-446655440000"
          },
          "customerId": {
            "type": "string",
            "description": "Customer ID",
            "example": "550e8400-e29b-41d4-a716-446655440000"
          },
          "customerName": {
            "type": "string",
            "description": "Customer name",
            "example": "Acme Corporation"
          },
          "planId": {
            "type": "string",
            "description": "Subscription plan ID (null for ad-hoc subscriptions)",
            "example": "550e8400-e29b-41d4-a716-446655440000"
          },
          "subscriptionName": {
            "type": "string",
            "description": "Subscription name",
            "example": "Premium Plan"
          },
          "startDate": {
            "type": "string",
            "description": "Start date (ISO 8601)",
            "example": "2024-01-01"
          },
          "endDate": {
            "type": "string",
            "description": "End date (ISO 8601)",
            "example": "2025-01-01"
          },
          "scheduledChurnDate": {
            "type": "string",
            "description": "Scheduled churn date (ISO 8601)",
            "example": "2024-07-15"
          },
          "status": {
            "type": "string",
            "description": "Status of the customer subscription",
            "enum": [
              "scheduled",
              "trial",
              "awaiting_payment",
              "active",
              "pending_cancellation",
              "paused",
              "cancelled",
              "expired"
            ],
            "example": "active"
          },
          "currency": {
            "type": "string",
            "description": "Currency code (ISO 4217)",
            "example": "DKK"
          },
          "trialDays": {
            "type": "number",
            "description": "Number of trial days granted",
            "example": 14
          },
          "cancellationReason": {
            "type": "string",
            "description": "Reason provided when the subscription was cancelled",
            "example": "Customer requested downgrade"
          },
          "billingDirection": {
            "type": "string",
            "description": "Billing direction: ADVANCE bills at period start, ARREARS at period end",
            "enum": [
              "advance",
              "arrears"
            ],
            "example": "advance"
          },
          "effectiveBillingDirection": {
            "type": "string",
            "description": "Effective billing direction for the current period. Can differ from billingDirection if the direction was changed mid-period.",
            "enum": [
              "advance",
              "arrears"
            ],
            "example": "advance"
          },
          "effectiveNextBillingDate": {
            "type": "string",
            "description": "Effective next billing date (ISO 8601)",
            "example": "2024-02-01"
          },
          "commitmentEndDate": {
            "type": "string",
            "description": "End date of the customer commitment period (ISO 8601)",
            "example": "2025-12-31"
          },
          "originalStartDate": {
            "type": "string",
            "description": "Original start date from source system for migrated subscriptions (ISO 8601)",
            "example": "2023-01-01"
          },
          "paymentMethodId": {
            "type": "string",
            "description": "Assigned payment method ID",
            "example": "550e8400-e29b-41d4-a716-446655440000",
            "nullable": true
          },
          "automaticBilling": {
            "type": "boolean",
            "description": "Whether automatic billing is enabled",
            "example": true
          },
          "partnerReferenceId": {
            "type": "string",
            "description": "Your reconciliation reference (the `clientReferenceId` you passed at embedded-checkout bind time), echoed back so you can match this subscription to your order. Null for any subscription not created through a partner-bound checkout.",
            "example": "order_7f3a9c21",
            "nullable": true
          }
        },
        "required": [
          "id",
          "customerId",
          "customerName",
          "subscriptionName",
          "startDate",
          "status",
          "currency",
          "billingDirection",
          "effectiveBillingDirection"
        ]
      },
      "PublicCustomerSubscriptionListItem": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Customer subscription ID",
            "example": "550e8400-e29b-41d4-a716-446655440000"
          },
          "customerId": {
            "type": "string",
            "description": "Customer ID",
            "example": "550e8400-e29b-41d4-a716-446655440000"
          },
          "customerName": {
            "type": "string",
            "description": "Customer name",
            "example": "Acme Corporation"
          },
          "customerNumber": {
            "type": "string",
            "description": "Customer number",
            "example": "C001"
          },
          "planId": {
            "type": "string",
            "description": "Subscription plan ID (null for ad-hoc subscriptions)",
            "example": "550e8400-e29b-41d4-a716-446655440000"
          },
          "subscriptionName": {
            "type": "string",
            "description": "Subscription plan name",
            "example": "Premium Plan"
          },
          "status": {
            "type": "string",
            "description": "Status of the customer subscription",
            "enum": [
              "scheduled",
              "trial",
              "awaiting_payment",
              "active",
              "pending_cancellation",
              "paused",
              "cancelled",
              "expired"
            ],
            "example": "active"
          },
          "startDate": {
            "type": "string",
            "description": "Start date (ISO 8601)",
            "example": "2024-01-01"
          },
          "effectiveNextBillingDate": {
            "type": "string",
            "description": "Effective next billing date (ISO 8601)",
            "example": "2024-02-01"
          },
          "currency": {
            "type": "string",
            "description": "Currency code (ISO 4217)",
            "example": "DKK"
          },
          "partnerReferenceId": {
            "type": "string",
            "description": "Your reconciliation reference (the `clientReferenceId` you passed at embedded-checkout bind time), echoed back so you can match this subscription to your order. Null for any subscription not created through a partner-bound checkout. Filter the list by `partnerReferenceId` to recover a missed webhook.",
            "example": "order_7f3a9c21",
            "nullable": true
          }
        },
        "required": [
          "id",
          "customerId",
          "customerName",
          "subscriptionName",
          "status",
          "startDate",
          "currency"
        ]
      },
      "PublicListCustomerSubscriptionsResponse": {
        "type": "object",
        "properties": {
          "data": {
            "description": "List of customer subscriptions",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PublicCustomerSubscriptionListItem"
            }
          },
          "total": {
            "type": "number",
            "description": "Total number of customer subscriptions matching the query",
            "example": 42
          },
          "page": {
            "type": "number",
            "description": "Current page number (1-indexed)",
            "example": 1
          },
          "limit": {
            "type": "number",
            "description": "Maximum number of items per page",
            "example": 25
          },
          "totalPages": {
            "type": "number",
            "description": "Total number of pages available",
            "example": 2
          }
        },
        "required": [
          "data",
          "total",
          "page",
          "limit",
          "totalPages"
        ]
      },
      "PublicAssignSubscriptionProductOverride": {
        "type": "object",
        "properties": {
          "priceId": {
            "type": "string",
            "description": "Price ID of the product to override",
            "example": "550e8400-e29b-41d4-a716-446655440000"
          },
          "quantity": {
            "type": "number",
            "description": "Quantity to assign (overrides the plan template quantity)",
            "example": 25
          }
        },
        "required": [
          "priceId",
          "quantity"
        ]
      },
      "PublicAssignSubscriptionRequest": {
        "type": "object",
        "properties": {
          "customerId": {
            "type": "string",
            "description": "Customer ID to assign the subscription to",
            "example": "550e8400-e29b-41d4-a716-446655440000"
          },
          "planId": {
            "type": "string",
            "description": "Subscription plan ID",
            "example": "550e8400-e29b-41d4-a716-446655440000"
          },
          "startDate": {
            "type": "string",
            "description": "Start date (ISO 8601)",
            "example": "2024-01-01"
          },
          "endDate": {
            "type": "string",
            "description": "End date (ISO 8601)",
            "example": "2025-01-01"
          },
          "billingCycleAnchor": {
            "type": "string",
            "description": "Billing cycle anchor date (ISO 8601). When the billing cycle should align to. Defaults to startDate if not provided.",
            "example": "2024-02-01"
          },
          "prorationBehavior": {
            "type": "string",
            "description": "How to handle proration from startDate to billingCycleAnchor",
            "enum": [
              "create_prorations",
              "always_invoice",
              "none"
            ],
            "example": "none",
            "default": "none"
          },
          "trialDays": {
            "type": "number",
            "description": "Trial period in days",
            "example": 14,
            "minimum": 0,
            "maximum": 365
          },
          "billingDirection": {
            "type": "string",
            "description": "Billing direction for this subscription",
            "enum": [
              "advance",
              "arrears"
            ],
            "example": "advance"
          },
          "customerDepartmentId": {
            "type": "string",
            "description": "Customer department ID for invoice delivery",
            "example": "550e8400-e29b-41d4-a716-446655440000"
          },
          "departmentContactOverrideId": {
            "type": "string",
            "description": "Contact override ID for department invoice delivery",
            "example": "550e8400-e29b-41d4-a716-446655440000"
          },
          "productOverrides": {
            "description": "Optional quantity overrides for products in the plan",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PublicAssignSubscriptionProductOverride"
            }
          },
          "paymentMethodId": {
            "type": "string",
            "description": "Payment method ID to assign for automatic billing",
            "example": "550e8400-e29b-41d4-a716-446655440000"
          },
          "automaticBilling": {
            "type": "boolean",
            "description": "Whether to enable automatic billing",
            "example": false
          }
        },
        "required": [
          "customerId",
          "planId",
          "startDate"
        ]
      },
      "PublicScheduledChange": {
        "type": "object",
        "properties": {
          "changeId": {
            "type": "string",
            "description": "Identifier of this queued change. Ephemeral — valid only until the change activates or is cancelled, so re-fetch rather than caching it.",
            "example": "550e8400-e29b-41d4-a716-446655440000"
          },
          "kind": {
            "type": "string",
            "description": "The kind of queued change: one of `replace_plan`, `edit_products`, `change_direction`, or `churn`.",
            "example": "replace_plan"
          },
          "effectiveDate": {
            "type": "string",
            "description": "The date (YYYY-MM-DD) the change takes effect.",
            "example": "2024-07-01"
          },
          "planId": {
            "type": "string",
            "description": "The plan the subscription moves to when the change activates (null for ad-hoc / non-plan changes).",
            "example": "550e8400-e29b-41d4-a716-446655440000",
            "nullable": true
          },
          "subscriptionName": {
            "type": "string",
            "description": "The plan name the change moves to.",
            "example": "Pro (annual)"
          }
        },
        "required": [
          "changeId",
          "kind",
          "effectiveDate",
          "planId",
          "subscriptionName"
        ]
      },
      "PublicUpdateSubscriptionRequest": {
        "type": "object",
        "properties": {
          "paymentMethodId": {
            "type": "string",
            "description": "Payment method ID to assign. Set to null to clear.",
            "example": "550e8400-e29b-41d4-a716-446655440000",
            "nullable": true
          },
          "automaticBilling": {
            "type": "boolean",
            "description": "Whether to automatically charge the saved card during billing",
            "example": true
          }
        }
      },
      "DefaultContactDto": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "example": "John Doe",
            "description": "Contact name"
          },
          "email": {
            "type": "string",
            "example": "john@acme.com",
            "description": "Contact email"
          },
          "phone": {
            "type": "string",
            "example": "+45 12345678",
            "description": "Contact phone number"
          }
        },
        "required": [
          "name"
        ]
      },
      "CreateCustomerRequestDto": {
        "type": "object",
        "properties": {
          "customerType": {
            "type": "string",
            "enum": [
              "BUSINESS",
              "PRIVATE_PERSON"
            ],
            "example": "BUSINESS",
            "description": "Specifies whether the customer is a business or a private person",
            "default": "BUSINESS"
          },
          "customerNumber": {
            "type": "string",
            "example": "C001",
            "description": "Unique customer number"
          },
          "name": {
            "type": "string",
            "example": "Acme Corporation",
            "description": "Customer name"
          },
          "vatZone": {
            "type": "string",
            "enum": [
              "domestic",
              "eu",
              "abroad",
              "domestic_without_vat"
            ],
            "example": "domestic",
            "description": "VAT zone classification"
          },
          "customerGroupId": {
            "type": "string",
            "example": "01HQ3Y1234567890ABCDEFGHIJ",
            "description": "Customer group ID"
          },
          "email": {
            "type": "string",
            "example": "contact@acme.com",
            "description": "Email address"
          },
          "phone": {
            "type": "string",
            "example": "+45 12345678",
            "description": "Phone number"
          },
          "address": {
            "type": "string",
            "example": "123 Main Street",
            "description": "Street address"
          },
          "city": {
            "type": "string",
            "example": "Copenhagen",
            "description": "City"
          },
          "postalCode": {
            "type": "string",
            "example": "2100",
            "description": "Postal code"
          },
          "countryCode": {
            "type": "string",
            "example": "DK",
            "description": "Two-letter country code"
          },
          "vatNumber": {
            "type": "string",
            "example": "DK12345678",
            "description": "VAT registration number"
          },
          "eanNumber": {
            "type": "string",
            "example": "5790000000001",
            "description": "EAN/GLN number for Peppol routing"
          },
          "website": {
            "type": "string",
            "example": "https://acme.com",
            "description": "Website URL"
          },
          "notes": {
            "type": "string",
            "example": "Key account customer",
            "description": "Additional notes"
          },
          "locale": {
            "type": "string",
            "example": "da-DK",
            "description": "Locale for formatting invoice data"
          },
          "language": {
            "type": "string",
            "example": "da",
            "description": "Language code for communications"
          },
          "creditLimit": {
            "type": "object",
            "example": 50000,
            "description": "Credit limit",
            "minimum": 0
          },
          "openingBalance": {
            "type": "object",
            "example": 1000,
            "description": "Opening balance in the company base currency, seeding receivables that predate LedgerBee. Signed: positive = the customer owes us, negative = a credit position. Folds into the entity balance only (not into invoiced totals or overdue ageing)."
          },
          "paymentTerms": {
            "type": "number",
            "example": 30,
            "description": "Payment terms in days",
            "minimum": 0
          },
          "paymentTermType": {
            "type": "string",
            "enum": [
              "NET_DAYS",
              "CASH",
              "RUNNING_MONTH_PLUS_DAYS"
            ],
            "description": "Payment term type. Defaults to NET_DAYS.",
            "default": "NET_DAYS"
          },
          "defaultCashAccountId": {
            "type": "string",
            "description": "Default cash payment account ID. Only relevant for CASH payment terms. Send null to clear.",
            "nullable": true
          },
          "defaultCurrency": {
            "type": "string",
            "example": "DKK",
            "description": "Default currency code"
          },
          "poNumber": {
            "type": "string",
            "example": "PO-12345",
            "description": "Default purchase-order number (\"PO-nr.\") prefilled onto sales documents"
          },
          "ourReference": {
            "type": "string",
            "example": "Jane Doe",
            "description": "Default \"Vores ref.\" (our-side reference) prefilled onto sales documents"
          },
          "invoiceDeliveryTypePreference": {
            "type": "string",
            "description": "Preferred invoice delivery type for this customer. If set, overrides the app company default for billing.",
            "enum": [
              "Email",
              "Sproom"
            ],
            "nullable": true
          },
          "reminderConfigId": {
            "type": "string",
            "description": "Reminder config profile ID. Send null to clear.",
            "nullable": true
          },
          "isActive": {
            "type": "boolean",
            "example": true,
            "description": "Whether the customer is active",
            "default": true
          },
          "defaultContact": {
            "description": "Default contact to create for the customer. If not provided, customer name/email/phone will be used as fallback.",
            "allOf": [
              {
                "$ref": "#/components/schemas/DefaultContactDto"
              }
            ]
          },
          "invoiceTemplateId": {
            "type": "string",
            "description": "Invoice PDF template override"
          },
          "creditNoteTemplateId": {
            "type": "string",
            "description": "Credit note PDF template override"
          },
          "quoteTemplateId": {
            "type": "string",
            "description": "Quote PDF template override"
          },
          "orderConfirmationTemplateId": {
            "type": "string",
            "description": "Order confirmation PDF template override"
          },
          "parentInvoiceTemplateId": {
            "type": "string",
            "description": "Parent single invoice PDF template override. Send null to clear.",
            "nullable": true
          },
          "includeChildDetailsPdf": {
            "type": "boolean",
            "description": "Whether to attach a zip of per-child detail PDFs when sending consolidated invoices"
          },
          "parentCustomerId": {
            "type": "string",
            "description": "Parent customer ID. Send null to clear.",
            "nullable": true
          },
          "billingRelationship": {
            "type": "string",
            "description": "Billing relationship",
            "enum": [
              "self",
              "parent_pays"
            ]
          },
          "consolidationMode": {
            "type": "string",
            "description": "Consolidation mode. Send null to clear.",
            "nullable": true,
            "enum": [
              "single_invoice",
              "per_child_invoice"
            ]
          },
          "billingDay": {
            "type": "number",
            "description": "Billing day (1-28). Required for single invoice mode. Send null to clear.",
            "nullable": true
          },
          "metadata": {
            "type": "object",
            "description": "Key-value metadata to attach to the customer",
            "additionalProperties": {
              "type": "string"
            }
          }
        },
        "required": [
          "customerType",
          "customerNumber",
          "name",
          "vatZone",
          "customerGroupId",
          "countryCode"
        ]
      },
      "PublicProvisionCustomerRequest": {
        "type": "object",
        "properties": {
          "customerId": {
            "type": "string",
            "description": "The customer's LedgerBee id. The customer must already exist in the API key's tenant; this endpoint never creates one from an id (a 404 CUSTOMER_NOT_FOUND is returned if it doesn't). Supply either `customerId` or a `customer` payload.",
            "example": "550e8400-e29b-41d4-a716-446655440010"
          },
          "customer": {
            "description": "A customer to upsert, identified idempotently by its `customerNumber`: an existing customer of the API key's tenant with that number is reused, otherwise a new one is created with this payload. Same shape as the gated `POST /customers` request (so `vatZone` and `countryCode` are required here). If `customer.email` is omitted, the portal-user `email` below is used as the customer's contact email (and its auto-created default contact). Supply either this or `customerId`.",
            "allOf": [
              {
                "$ref": "#/components/schemas/CreateCustomerRequestDto"
              }
            ]
          },
          "email": {
            "type": "string",
            "description": "Email of the portal user to grant access to. A credential-less portal user is created if none exists.",
            "example": "jane.doe@acme.example"
          },
          "role": {
            "type": "string",
            "description": "Membership role to grant. Defaults to USER; the org's first member is force-assigned OWNER regardless.",
            "enum": [
              "OWNER",
              "ADMIN",
              "BILLING_ADMIN",
              "USER"
            ],
            "example": "USER"
          },
          "userName": {
            "type": "string",
            "description": "Display name of the portal user (set on first creation).",
            "example": "Jane Doe"
          },
          "organizationDisplayName": {
            "type": "string",
            "description": "Display name for the customer organization (first-invite bootstrap)."
          },
          "mintHandoff": {
            "type": "boolean",
            "description": "When true, also mint a back-channel handoff reference in the same call (one round-trip \"Go to portal\"). Requires the API key to ALSO carry the portal-sso-mint scope, and the tenant to have back-channel handoff enabled.",
            "example": false
          },
          "sub": {
            "type": "string",
            "description": "The partner's stable, unique user identifier — required when mintHandoff is true; keys the handoff identity (with the per-tenant handoff issuer).",
            "example": "partner-user-7f3a9c21"
          },
          "mintCheckoutBindToken": {
            "type": "boolean",
            "description": "When true, also mint a one-time CHECKOUT-BIND reference in the same call — an opaque token the partner's `fetchBindToken` provider returns to the embed at checkout-start so the embedded checkout subscribes directly against THIS customer instead of staging an anonymous magic-link signup. Requires the API key to ALSO carry the portal-sso-mint scope. Independent of mintHandoff (login): a checkout-bind ref can never mint a login session.",
            "example": false
          },
          "clientReferenceId": {
            "type": "string",
            "description": "Your own opaque reference for this order (Stripe `client_reference_id` parity), e.g. your internal order or cart id. It rides the minted checkout-bind ref onto the resulting subscription (as `partnerReferenceId`) and into every later subscription webhook, so you can reconcile our subscription to your record. Server-to-server only — it never reaches a client/iframe surface. Max 200 chars, `[A-Za-z0-9_-]` only.",
            "example": "order_7f3a9c21"
          }
        },
        "required": [
          "email"
        ]
      },
      "PublicProvisionCustomerResponse": {
        "type": "object",
        "properties": {
          "customerId": {
            "type": "string",
            "description": "Resolved customer id.",
            "example": "550e8400-e29b-41d4-a716-446655440010"
          },
          "customerCreated": {
            "type": "boolean",
            "description": "Whether a new customer was created (false = an existing one was reused).",
            "example": true
          },
          "portalUserId": {
            "type": "string",
            "description": "Resolved portal user id.",
            "example": "550e8400-e29b-41d4-a716-446655440020"
          },
          "membershipId": {
            "type": "string",
            "description": "The active organization membership id.",
            "example": "550e8400-e29b-41d4-a716-446655440030"
          },
          "role": {
            "type": "string",
            "description": "The granted membership role.",
            "enum": [
              "OWNER",
              "ADMIN",
              "BILLING_ADMIN",
              "USER"
            ],
            "example": "OWNER"
          },
          "handoffRef": {
            "type": "string",
            "description": "Opaque, single-use, 60s handoff reference — present only when mintHandoff was requested. Null otherwise.",
            "example": "Yk3pQ9sV2nR7tW1xZ4cB8mL6dF0aH5jE2gN9uK3pQ7s",
            "nullable": true
          },
          "handoffExpiresAt": {
            "type": "string",
            "description": "ISO-8601 expiry of the handoff reference, when minted. Null otherwise.",
            "example": "2026-06-04T12:34:56.000Z",
            "nullable": true
          },
          "checkoutBindToken": {
            "type": "string",
            "description": "Opaque, single-use, 60s checkout-bind reference — present only when mintCheckoutBindToken was requested. Null otherwise. The partner's `fetchBindToken` provider returns this to the embed at checkout-start; the embedded checkout redeems it to subscribe directly against this customer.",
            "example": "Yk3pQ9sV2nR7tW1xZ4cB8mL6dF0aH5jE2gN9uK3pQ7s",
            "nullable": true
          },
          "checkoutBindExpiresAt": {
            "type": "string",
            "description": "ISO-8601 expiry of the checkout-bind reference, when minted. Null otherwise.",
            "example": "2026-06-04T12:34:56.000Z",
            "nullable": true
          }
        },
        "required": [
          "customerId",
          "customerCreated",
          "portalUserId",
          "membershipId",
          "role"
        ]
      },
      "PublicResolvePortalPlansRequest": {
        "type": "object",
        "properties": {
          "customerId": {
            "type": "string",
            "description": "The buyer's LedgerBee customer id (an identity HANDLE — the server hydrates customer group / country / type from it; raw rule attributes are never accepted). The customer must exist in the API key's tenant (a 404 CUSTOMER_NOT_FOUND otherwise). When present, the server-resolved identity wins and the countryCode/customerType hints are ignored.",
            "example": "550e8400-e29b-41d4-a716-446655440010"
          },
          "buyerEmail": {
            "type": "string",
            "description": "The specific person (their email) the partner is acting on behalf of under `customerId` — e.g. the user currently signed in on the partner's site. Bound into the catalog token: when that token is later exchanged for a portal login handoff, THIS person is logged in (or bootstrapped credential-less under the customer's organization), instead of the customer's contact email / first member. Ignored without `customerId`; does not affect catalog visibility.",
            "example": "buyer@partner.example"
          },
          "countryCode": {
            "type": "string",
            "description": "ISO 3166-1 alpha-2 country hint for the no-customer-yet preview (drives the `country` rule clause). Ignored when `customerId` is supplied.",
            "example": "DK"
          },
          "customerType": {
            "type": "string",
            "description": "Customer-type hint for the no-customer-yet preview (drives the `customerType` rule clause). Ignored when `customerId` is supplied.",
            "enum": [
              "BUSINESS",
              "PRIVATE_PERSON"
            ],
            "example": "BUSINESS"
          },
          "planIds": {
            "description": "Resolve only these plan ids. Omit to resolve every ACTIVE plan of the tenant. Each must be a uuid.",
            "example": [
              "550e8400-e29b-41d4-a716-446655440100"
            ],
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "language": {
            "type": "string",
            "description": "Language the resolved cards are localized to. Defaults to `en`.",
            "enum": [
              "en",
              "da"
            ],
            "example": "en"
          }
        }
      },
      "PublicResolvePortalPlansResponse": {
        "type": "object",
        "properties": {
          "plans": {
            "type": "array",
            "description": "The plans visible AND checkout-able to the resolved buyer, each carrying the full card content the partner renders. Non-public (gated) plans appear here when the buyer matches their rule.",
            "items": {
              "type": "object",
              "additionalProperties": true
            }
          },
          "catalogToken": {
            "type": "string",
            "description": "Opaque, reusable, read-only load-time catalog token (43-char base64url). The partner returns it to each embed iframe via its `fetchCatalogToken` provider; the iframe presents it as a Bearer token to the by-id pricing-card / checkout-document reads. Scoped to the resolved buyer + the returned plans — replay yields only the same already-authorized cards. Treat it as a client secret (TLS-only, never log, never put on a URL).",
            "example": "Yk3pQ9sV2nR7tW1xZ4cB8mL6dF0aH5jE2gN9uK3pQ7s"
          },
          "expiresAt": {
            "type": "string",
            "description": "ISO-8601 expiry of the catalog token.",
            "example": "2026-06-06T12:34:56.000Z"
          }
        },
        "required": [
          "plans",
          "catalogToken",
          "expiresAt"
        ]
      },
      "PublicPortalPlansListResponse": {
        "type": "object",
        "properties": {
          "plans": {
            "type": "array",
            "description": "Every ACTIVE plan with a PUBLISHED version in the API key's tenant, projected as its canonical native card and ordered by display order. This is the integrator's full catalogue — NOT filtered by any per-visitor visibility rule and NOT run through the plan-routing rule engine. Each entry carries the full card content the integrator renders.",
            "items": {
              "type": "object",
              "additionalProperties": true
            }
          }
        },
        "required": [
          "plans"
        ]
      },
      "PublicPortalPlanResponse": {
        "type": "object",
        "properties": {
          "plan": {
            "type": "object",
            "description": "A single plan projected as its canonical native card. Returns 404 PORTAL_PLAN_NOT_FOUND only when the plan id is unknown to the API key's tenant or has no published version — never filtered by visibility rules or the rule engine.",
            "additionalProperties": true
          }
        },
        "required": [
          "plan"
        ]
      },
      "PublicPortalSsoJwks": {
        "type": "object",
        "properties": {
          "keys": {
            "type": "array",
            "description": "The published public JWK(s). Public key material only — never any private component.",
            "items": {
              "type": "object",
              "additionalProperties": true
            },
            "example": [
              {
                "kty": "RSA",
                "use": "sig",
                "alg": "RS256",
                "kid": "abc123",
                "n": "…",
                "e": "AQAB"
              }
            ]
          }
        },
        "required": [
          "keys"
        ]
      },
      "PublicHandoffMembership": {
        "type": "object",
        "properties": {
          "customerId": {
            "type": "string",
            "description": "The id of the customer (the GET /v1/customers resource) this user belongs to. The portal organization is resolved from it server-side — created automatically on first login if it doesn't exist yet — and a customer that doesn't belong to the API key's tenant is rejected.",
            "example": "550e8400-e29b-41d4-a716-446655440010"
          },
          "role": {
            "type": "string",
            "description": "Role to grant within that organization. One of OWNER, ADMIN, BILLING_ADMIN, USER. Unknown roles are rejected.",
            "example": "OWNER"
          },
          "primary": {
            "type": "boolean",
            "description": "Marks this membership as the organization the user is signed into for this session. When more than one membership is asserted, EXACTLY ONE must be `primary` (otherwise the mint is rejected with a 400). With a single membership it is the implied sign-in organization, so the flag is optional.",
            "example": true
          }
        },
        "required": [
          "customerId",
          "role"
        ]
      },
      "PublicHandoffMintRequest": {
        "type": "object",
        "properties": {
          "email": {
            "type": "string",
            "description": "Email of the partner-provisioned user. Links a first-time SSO login to an existing invited customer-portal user.",
            "example": "jane.doe@partner-customer.com"
          },
          "sub": {
            "type": "string",
            "description": "The partner's stable, unique identifier for the user. Keyed together with the per-tenant handoff issuer to resolve the portal user across logins.",
            "example": "partner-user-7f3a9c21"
          },
          "name": {
            "type": "string",
            "description": "Display name of the user; used to populate the customer-portal user's name on first login.",
            "example": "Jane Doe"
          },
          "memberships": {
            "description": "At least one customer membership to grant this user — required. The customer's portal organization (an opaque internal container) and the membership are created automatically server-side at redeem, so a prior provision call is NOT needed; you only ever reference customers, never organizations. Validated at mint: a customerId that isn't a customer of the API key's tenant, or an unknown role, is rejected with a 400 (rather than failing the user's browser redirect). A handoff with no membership can't establish a portal session, so an empty/omitted array is rejected here rather than minting a ref that would fail at redeem.",
            "example": [
              {
                "customerId": "550e8400-e29b-41d4-a716-446655440010",
                "role": "OWNER"
              }
            ],
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PublicHandoffMembership"
            }
          }
        },
        "required": [
          "email",
          "sub",
          "memberships"
        ]
      },
      "PublicHandoffMintResponse": {
        "type": "object",
        "properties": {
          "ref": {
            "type": "string",
            "description": "Opaque, single-use, short-TTL reference. Carries NO identity — the identity lives only in server-side storage keyed by this reference until it is redeemed once at the customer portal.",
            "example": "Yk3pQ9sV2nR7tW1xZ4cB8mL6dF0aH5jE2gN9uK3pQ7s"
          },
          "expiresAt": {
            "type": "string",
            "description": "ISO-8601 timestamp after which the reference can no longer be redeemed (60 seconds after minting).",
            "example": "2026-06-03T12:34:56.000Z"
          }
        },
        "required": [
          "ref",
          "expiresAt"
        ]
      },
      "PublicRevokeSessionsRequest": {
        "type": "object",
        "properties": {
          "sub": {
            "type": "string",
            "description": "The partner's stable subject id for the user — the same `sub` used when minting their handoff. Every active portal session of that user is force-refreshed.",
            "example": "partner-user-7f3a9c21"
          }
        },
        "required": [
          "sub"
        ]
      },
      "PublicRevokeSessionsResponse": {
        "type": "object",
        "properties": {
          "revoked": {
            "type": "number",
            "description": "Number of memberships whose sessions were force-refreshed (0 when the user has no active sessions).",
            "example": 2
          }
        },
        "required": [
          "revoked"
        ]
      },
      "VatCodeResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The unique identifier of the VAT code",
            "example": "550e8400-e29b-41d4-a716-446655440000"
          },
          "vatCode": {
            "type": "string",
            "description": "VAT code identifier",
            "example": "VAT25"
          },
          "name": {
            "type": "string",
            "description": "Name/description of the VAT code",
            "example": "25% Standard VAT"
          },
          "vatRate": {
            "type": "number",
            "description": "VAT rate percentage",
            "example": 25
          },
          "type": {
            "type": "string",
            "description": "VAT type",
            "example": "Output/sales"
          },
          "principle": {
            "type": "string",
            "description": "VAT principle - Gross (VAT included) or Net (VAT excluded)",
            "example": "gross"
          },
          "accountToBookId": {
            "type": "string",
            "description": "The ledger account ID to book VAT to",
            "example": "550e8400-e29b-41d4-a716-446655440001"
          },
          "accountToBookNumber": {
            "type": "number",
            "description": "The ledger account number to book VAT to",
            "example": 6910
          },
          "accountToBookName": {
            "type": "string",
            "description": "The ledger account name to book VAT to",
            "example": "Output VAT"
          },
          "contraAccountToBookId": {
            "type": "string",
            "description": "The contra account ID for VAT entries",
            "example": "550e8400-e29b-41d4-a716-446655440002"
          },
          "contraAccountToBookNumber": {
            "type": "number",
            "description": "The contra account number for VAT entries",
            "example": 6920
          },
          "contraAccountToBookName": {
            "type": "string",
            "description": "The contra account name for VAT entries",
            "example": "Input VAT"
          }
        },
        "required": [
          "id",
          "vatCode",
          "name",
          "vatRate",
          "type",
          "principle"
        ]
      },
      "VendorGroupResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The unique identifier of the vendor group",
            "example": "550e8400-e29b-41d4-a716-446655440000"
          },
          "name": {
            "type": "string",
            "description": "Name of the vendor group",
            "example": "Domestic Vendors"
          },
          "description": {
            "type": "string",
            "description": "Description of the vendor group",
            "example": "All domestic vendor accounts"
          },
          "defaultAccountId": {
            "type": "string",
            "description": "Default ledger account ID",
            "example": "550e8400-e29b-41d4-a716-446655440001"
          }
        },
        "required": [
          "id",
          "name"
        ]
      },
      "VendorDepartmentResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The unique identifier of the department",
            "example": "550e8400-e29b-41d4-a716-446655440000"
          },
          "name": {
            "type": "string",
            "description": "Name of the department",
            "example": "Headquarters"
          },
          "isDefault": {
            "type": "boolean",
            "description": "Whether this is the default department for the vendor",
            "example": true
          },
          "isActive": {
            "type": "boolean",
            "description": "Whether the department is active",
            "example": true
          },
          "poNumber": {
            "type": "string",
            "description": "Purchase order number",
            "example": "PO-12345"
          },
          "eanNumber": {
            "type": "string",
            "description": "EAN number for e-invoicing",
            "example": "5790000000000"
          },
          "address": {
            "type": "string",
            "description": "Street address",
            "example": "123 Main Street"
          },
          "city": {
            "type": "string",
            "description": "City",
            "example": "Copenhagen"
          },
          "postalCode": {
            "type": "string",
            "description": "Postal code",
            "example": "2100"
          },
          "countryCode": {
            "type": "string",
            "description": "Two-letter country code (ISO 3166-1 alpha-2)",
            "example": "DK"
          }
        },
        "required": [
          "id",
          "name",
          "isDefault",
          "isActive"
        ]
      },
      "VendorContactResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The unique identifier of the contact",
            "example": "550e8400-e29b-41d4-a716-446655440000"
          },
          "name": {
            "type": "string",
            "description": "Name of the contact",
            "example": "John Doe"
          },
          "email": {
            "type": "string",
            "description": "Email address",
            "example": "john.doe@acme-supplies.com"
          },
          "phone": {
            "type": "string",
            "description": "Phone number",
            "example": "+45 12345678"
          },
          "isDefaultForVendor": {
            "type": "boolean",
            "description": "Whether this is the default contact for the vendor",
            "example": true
          }
        },
        "required": [
          "id",
          "name",
          "isDefaultForVendor"
        ]
      },
      "VendorResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The unique identifier of the vendor",
            "example": "550e8400-e29b-41d4-a716-446655440000"
          },
          "vendorNumber": {
            "type": "string",
            "description": "Vendor number",
            "example": "V001"
          },
          "name": {
            "type": "string",
            "description": "Name of the vendor",
            "example": "Acme Supplies"
          },
          "vendorGroupId": {
            "type": "string",
            "description": "Vendor group ID",
            "example": "550e8400-e29b-41d4-a716-446655440001"
          },
          "vendorGroupName": {
            "type": "string",
            "description": "Vendor group name",
            "example": "Domestic Vendors"
          },
          "email": {
            "type": "string",
            "description": "Email address",
            "example": "contact@acme-supplies.com"
          },
          "phone": {
            "type": "string",
            "description": "Phone number",
            "example": "+45 12345678"
          },
          "address": {
            "type": "string",
            "description": "Street address",
            "example": "123 Main Street"
          },
          "city": {
            "type": "string",
            "description": "City",
            "example": "Copenhagen"
          },
          "postalCode": {
            "type": "string",
            "description": "Postal code",
            "example": "2100"
          },
          "countryCode": {
            "type": "string",
            "description": "Two-letter country code (ISO 3166-1 alpha-2)",
            "example": "DK"
          },
          "vatNumber": {
            "type": "string",
            "description": "VAT registration number",
            "example": "DK12345678"
          },
          "currency": {
            "type": "string",
            "description": "Currency code",
            "example": "DKK"
          },
          "attention": {
            "type": "string",
            "description": "Attention field",
            "example": "Accounts Payable"
          },
          "paymentTerms": {
            "type": "number",
            "description": "Payment terms in days",
            "example": 30
          },
          "openingBalance": {
            "type": "number",
            "description": "Opening balance in the company base currency (signed: positive = we owe the vendor)",
            "example": 1000
          },
          "status": {
            "type": "string",
            "description": "Vendor status",
            "enum": [
              "active",
              "inactive",
              "archived"
            ],
            "example": "active"
          }
        },
        "required": [
          "id",
          "vendorNumber",
          "name",
          "vendorGroupId",
          "currency",
          "status"
        ]
      },
      "CreateVendorContactRequest": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "example": "John Doe",
            "description": "Contact name"
          },
          "email": {
            "type": "string",
            "example": "john.doe@acme-supplies.com",
            "description": "Email address"
          },
          "phone": {
            "type": "string",
            "example": "+45 12345678",
            "description": "Phone number"
          },
          "isDefault": {
            "type": "boolean",
            "example": true,
            "description": "Whether this is the default contact for the vendor"
          }
        },
        "required": [
          "name",
          "isDefault"
        ]
      },
      "CreateVendorRequest": {
        "type": "object",
        "properties": {
          "vendorNumber": {
            "type": "string",
            "example": "V001",
            "description": "Unique vendor number"
          },
          "name": {
            "type": "string",
            "example": "Acme Supplies",
            "description": "Vendor name"
          },
          "vendorGroupId": {
            "type": "string",
            "example": "550e8400-e29b-41d4-a716-446655440001",
            "description": "Vendor group ID"
          },
          "currency": {
            "type": "string",
            "example": "DKK",
            "description": "Currency code"
          },
          "countryCode": {
            "type": "string",
            "example": "DK",
            "description": "Two-letter country code"
          },
          "email": {
            "type": "string",
            "example": "contact@acme-supplies.com",
            "description": "Email address"
          },
          "phone": {
            "type": "string",
            "example": "+45 12345678",
            "description": "Phone number"
          },
          "address": {
            "type": "string",
            "example": "123 Main Street",
            "description": "Street address"
          },
          "city": {
            "type": "string",
            "example": "Copenhagen",
            "description": "City"
          },
          "postalCode": {
            "type": "string",
            "example": "2100",
            "description": "Postal code"
          },
          "vatNumber": {
            "type": "string",
            "example": "DK12345678",
            "description": "VAT registration number"
          },
          "attention": {
            "type": "string",
            "example": "Accounts Payable",
            "description": "Attention field"
          },
          "paymentTerms": {
            "type": "number",
            "example": 30,
            "description": "Payment terms in days",
            "minimum": 0
          },
          "openingBalance": {
            "type": "number",
            "example": 1000,
            "description": "Opening balance in the company base currency, seeding payables that predate LedgerBee. Signed: positive = we owe the vendor, negative = a credit position."
          },
          "defaultAccountId": {
            "type": "string",
            "example": "550e8400-e29b-41d4-a716-446655440002",
            "description": "Default ledger account ID"
          },
          "contacts": {
            "description": "Contacts for the vendor. At least one contact with isDefault: true is required.",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CreateVendorContactRequest"
            }
          }
        },
        "required": [
          "vendorNumber",
          "name",
          "vendorGroupId",
          "currency",
          "countryCode",
          "contacts"
        ]
      },
      "CreateVendorResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The unique identifier of the created vendor",
            "example": "550e8400-e29b-41d4-a716-446655440000"
          },
          "vendorNumber": {
            "type": "string",
            "description": "Vendor number",
            "example": "V001"
          }
        },
        "required": [
          "id",
          "vendorNumber"
        ]
      },
      "CreateWebhookEndpointRequest": {
        "type": "object",
        "properties": {
          "url": {
            "type": "string",
            "description": "The HTTPS URL events are delivered to. Must be a public https URL (loopback/private/link-local hosts are rejected).",
            "example": "https://example.com/webhooks/ledgerbee"
          },
          "enabledEvents": {
            "type": "array",
            "description": "The events to subscribe to. Must contain at least one known event type.\n\nAvailable events:\n- `subscription.assigned` — Fired when a subscription is assigned to a customer (may be future-dated / upcoming).\n- `subscription.started` — Fired when a subscription becomes active — grant entitlement/access on this event, not on assigned.\n- `subscription.updated` — Fired when a config property changes without a structural transition (e.g. name, payment method, billing direction).\n- `subscription.transitioned` — Fired on a structural change: plan replace, product edit, billing cadence change, or realign.\n- `subscription.paused` — Fired when a subscription is paused.\n- `subscription.resumed` — Fired when a subscription resumes from a pause.\n- `subscription.trial_ended` — Fired when a subscription trial ends and normal billing begins (the sub stays active).\n- `subscription.cancellation_scheduled` — Fired when a future cancellation is scheduled for a subscription (still active until then).\n- `subscription.cancellation_cleared` — Fired when a previously scheduled cancellation is cleared.\n- `subscription.churned` — Fired when a subscription is cancelled/finalized — revoke entitlement on this event.\n- `subscription.billed` — Fired once per (child) subscription when a billing run produces its invoice.\n- `subscription.payment_succeeded` — Fired when a card charge for the subscription clears — the success pair of the charge_failed error signal.\n- `subscription.error` — Fired when a delivery/processing problem occurs for a subscription (e.g. undeliverable recipient).\n- `billing.invoice_sent` — Fired when an invoice document is sent to the customer.\n- `billing.credit_note_sent` — Fired when a credit note document is sent to the customer.\n- `customer.created` — Fired when a customer is created (payload flags whether it was a portal self-signup).\n- `card.added` — Fired when a card is successfully saved for a customer (provider-opaque).\n- `card.removed` — Fired when a saved card is removed in-app or cancelled at the provider.\n- `card.updated` — Fired when a saved card’s details change (network auto-update or refresh).\n- `card.expiring` — Fired when a saved card is approaching expiry.\n- `card.expired` — Fired when a saved card is observed to have expired.\n- `card.default_changed` — Fired when the customer’s default card changes (explicit or auto-default).\n- `card.backup_changed` — Fired when the customer’s designated backup card is set, replaced, or cleared.\n- `card.add_failed` — Fired when a card-save attempt fails (decline or authentication failure).\n- `quote.sent` — Fired when a quote is sent to the customer.\n- `quote.converted` — Fired when a quote is converted into an order confirmation or an invoice.\n- `order_confirmation.sent` — Fired when an order confirmation is sent to the customer.\n- `order_confirmation.converted` — Fired when an order confirmation is converted into an invoice.\n- `project.created` — Fired when a project is created (payload carries the owned dimension id for correlation with the dimensions API).\n- `project.updated` — Fired when a project's fields are updated (payload lists the changed field names). Also fires on un-archive.\n- `project.archived` — Fired when a project is archived (its dimension is deactivated; postings history is preserved).",
            "example": [
              "subscription.assigned"
            ],
            "items": {
              "type": "string",
              "enum": [
                "subscription.assigned",
                "subscription.started",
                "subscription.updated",
                "subscription.transitioned",
                "subscription.paused",
                "subscription.resumed",
                "subscription.trial_ended",
                "subscription.cancellation_scheduled",
                "subscription.cancellation_cleared",
                "subscription.churned",
                "subscription.billed",
                "subscription.payment_succeeded",
                "subscription.error",
                "billing.invoice_sent",
                "billing.credit_note_sent",
                "customer.created",
                "card.added",
                "card.removed",
                "card.updated",
                "card.expiring",
                "card.expired",
                "card.default_changed",
                "card.backup_changed",
                "card.add_failed",
                "quote.sent",
                "quote.converted",
                "order_confirmation.sent",
                "order_confirmation.converted",
                "project.created",
                "project.updated",
                "project.archived"
              ]
            }
          },
          "description": {
            "type": "string",
            "description": "Optional human-facing description.",
            "example": "Production billing sync",
            "maxLength": 512
          }
        },
        "required": [
          "url",
          "enabledEvents"
        ]
      },
      "WebhookEndpointWithSecret": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Unique identifier of the webhook endpoint.",
            "example": "0192f3a1-..."
          },
          "url": {
            "type": "string",
            "description": "The HTTPS URL events are delivered to.",
            "example": "https://example.com/webhooks/ledgerbee"
          },
          "enabledEvents": {
            "type": "array",
            "description": "The events this endpoint is subscribed to. An event is delivered to every enabled endpoint subscribed to its type.\n\nAvailable events:\n- `subscription.assigned` — Fired when a subscription is assigned to a customer (may be future-dated / upcoming).\n- `subscription.started` — Fired when a subscription becomes active — grant entitlement/access on this event, not on assigned.\n- `subscription.updated` — Fired when a config property changes without a structural transition (e.g. name, payment method, billing direction).\n- `subscription.transitioned` — Fired on a structural change: plan replace, product edit, billing cadence change, or realign.\n- `subscription.paused` — Fired when a subscription is paused.\n- `subscription.resumed` — Fired when a subscription resumes from a pause.\n- `subscription.trial_ended` — Fired when a subscription trial ends and normal billing begins (the sub stays active).\n- `subscription.cancellation_scheduled` — Fired when a future cancellation is scheduled for a subscription (still active until then).\n- `subscription.cancellation_cleared` — Fired when a previously scheduled cancellation is cleared.\n- `subscription.churned` — Fired when a subscription is cancelled/finalized — revoke entitlement on this event.\n- `subscription.billed` — Fired once per (child) subscription when a billing run produces its invoice.\n- `subscription.payment_succeeded` — Fired when a card charge for the subscription clears — the success pair of the charge_failed error signal.\n- `subscription.error` — Fired when a delivery/processing problem occurs for a subscription (e.g. undeliverable recipient).\n- `billing.invoice_sent` — Fired when an invoice document is sent to the customer.\n- `billing.credit_note_sent` — Fired when a credit note document is sent to the customer.\n- `customer.created` — Fired when a customer is created (payload flags whether it was a portal self-signup).\n- `card.added` — Fired when a card is successfully saved for a customer (provider-opaque).\n- `card.removed` — Fired when a saved card is removed in-app or cancelled at the provider.\n- `card.updated` — Fired when a saved card’s details change (network auto-update or refresh).\n- `card.expiring` — Fired when a saved card is approaching expiry.\n- `card.expired` — Fired when a saved card is observed to have expired.\n- `card.default_changed` — Fired when the customer’s default card changes (explicit or auto-default).\n- `card.backup_changed` — Fired when the customer’s designated backup card is set, replaced, or cleared.\n- `card.add_failed` — Fired when a card-save attempt fails (decline or authentication failure).\n- `quote.sent` — Fired when a quote is sent to the customer.\n- `quote.converted` — Fired when a quote is converted into an order confirmation or an invoice.\n- `order_confirmation.sent` — Fired when an order confirmation is sent to the customer.\n- `order_confirmation.converted` — Fired when an order confirmation is converted into an invoice.\n- `project.created` — Fired when a project is created (payload carries the owned dimension id for correlation with the dimensions API).\n- `project.updated` — Fired when a project's fields are updated (payload lists the changed field names). Also fires on un-archive.\n- `project.archived` — Fired when a project is archived (its dimension is deactivated; postings history is preserved).",
            "example": [
              "subscription.assigned"
            ],
            "items": {
              "type": "string",
              "enum": [
                "subscription.assigned",
                "subscription.started",
                "subscription.updated",
                "subscription.transitioned",
                "subscription.paused",
                "subscription.resumed",
                "subscription.trial_ended",
                "subscription.cancellation_scheduled",
                "subscription.cancellation_cleared",
                "subscription.churned",
                "subscription.billed",
                "subscription.payment_succeeded",
                "subscription.error",
                "billing.invoice_sent",
                "billing.credit_note_sent",
                "customer.created",
                "card.added",
                "card.removed",
                "card.updated",
                "card.expiring",
                "card.expired",
                "card.default_changed",
                "card.backup_changed",
                "card.add_failed",
                "quote.sent",
                "quote.converted",
                "order_confirmation.sent",
                "order_confirmation.converted",
                "project.created",
                "project.updated",
                "project.archived"
              ]
            }
          },
          "status": {
            "type": "string",
            "description": "Delivery status. `disabled` endpoints are retained but receive no events.",
            "enum": [
              "enabled",
              "disabled"
            ],
            "example": "enabled"
          },
          "description": {
            "type": "string",
            "description": "Optional human-facing description of what this endpoint is used for.",
            "example": "Production billing sync",
            "nullable": true
          },
          "createdAt": {
            "type": "string",
            "description": "ISO 8601 creation timestamp.",
            "example": "2026-05-29T10:00:00.000Z"
          },
          "updatedAt": {
            "type": "string",
            "description": "ISO 8601 last-update timestamp.",
            "example": "2026-05-29T10:00:00.000Z"
          },
          "secret": {
            "type": "string",
            "description": "The signing secret (shown only on create and roll-secret). Used to verify the `webhook-signature` header.",
            "example": "whsec_..."
          }
        },
        "required": [
          "id",
          "url",
          "enabledEvents",
          "status",
          "createdAt",
          "updatedAt",
          "secret"
        ]
      },
      "WebhookEndpoint": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Unique identifier of the webhook endpoint.",
            "example": "0192f3a1-..."
          },
          "url": {
            "type": "string",
            "description": "The HTTPS URL events are delivered to.",
            "example": "https://example.com/webhooks/ledgerbee"
          },
          "enabledEvents": {
            "type": "array",
            "description": "The events this endpoint is subscribed to. An event is delivered to every enabled endpoint subscribed to its type.\n\nAvailable events:\n- `subscription.assigned` — Fired when a subscription is assigned to a customer (may be future-dated / upcoming).\n- `subscription.started` — Fired when a subscription becomes active — grant entitlement/access on this event, not on assigned.\n- `subscription.updated` — Fired when a config property changes without a structural transition (e.g. name, payment method, billing direction).\n- `subscription.transitioned` — Fired on a structural change: plan replace, product edit, billing cadence change, or realign.\n- `subscription.paused` — Fired when a subscription is paused.\n- `subscription.resumed` — Fired when a subscription resumes from a pause.\n- `subscription.trial_ended` — Fired when a subscription trial ends and normal billing begins (the sub stays active).\n- `subscription.cancellation_scheduled` — Fired when a future cancellation is scheduled for a subscription (still active until then).\n- `subscription.cancellation_cleared` — Fired when a previously scheduled cancellation is cleared.\n- `subscription.churned` — Fired when a subscription is cancelled/finalized — revoke entitlement on this event.\n- `subscription.billed` — Fired once per (child) subscription when a billing run produces its invoice.\n- `subscription.payment_succeeded` — Fired when a card charge for the subscription clears — the success pair of the charge_failed error signal.\n- `subscription.error` — Fired when a delivery/processing problem occurs for a subscription (e.g. undeliverable recipient).\n- `billing.invoice_sent` — Fired when an invoice document is sent to the customer.\n- `billing.credit_note_sent` — Fired when a credit note document is sent to the customer.\n- `customer.created` — Fired when a customer is created (payload flags whether it was a portal self-signup).\n- `card.added` — Fired when a card is successfully saved for a customer (provider-opaque).\n- `card.removed` — Fired when a saved card is removed in-app or cancelled at the provider.\n- `card.updated` — Fired when a saved card’s details change (network auto-update or refresh).\n- `card.expiring` — Fired when a saved card is approaching expiry.\n- `card.expired` — Fired when a saved card is observed to have expired.\n- `card.default_changed` — Fired when the customer’s default card changes (explicit or auto-default).\n- `card.backup_changed` — Fired when the customer’s designated backup card is set, replaced, or cleared.\n- `card.add_failed` — Fired when a card-save attempt fails (decline or authentication failure).\n- `quote.sent` — Fired when a quote is sent to the customer.\n- `quote.converted` — Fired when a quote is converted into an order confirmation or an invoice.\n- `order_confirmation.sent` — Fired when an order confirmation is sent to the customer.\n- `order_confirmation.converted` — Fired when an order confirmation is converted into an invoice.\n- `project.created` — Fired when a project is created (payload carries the owned dimension id for correlation with the dimensions API).\n- `project.updated` — Fired when a project's fields are updated (payload lists the changed field names). Also fires on un-archive.\n- `project.archived` — Fired when a project is archived (its dimension is deactivated; postings history is preserved).",
            "example": [
              "subscription.assigned"
            ],
            "items": {
              "type": "string",
              "enum": [
                "subscription.assigned",
                "subscription.started",
                "subscription.updated",
                "subscription.transitioned",
                "subscription.paused",
                "subscription.resumed",
                "subscription.trial_ended",
                "subscription.cancellation_scheduled",
                "subscription.cancellation_cleared",
                "subscription.churned",
                "subscription.billed",
                "subscription.payment_succeeded",
                "subscription.error",
                "billing.invoice_sent",
                "billing.credit_note_sent",
                "customer.created",
                "card.added",
                "card.removed",
                "card.updated",
                "card.expiring",
                "card.expired",
                "card.default_changed",
                "card.backup_changed",
                "card.add_failed",
                "quote.sent",
                "quote.converted",
                "order_confirmation.sent",
                "order_confirmation.converted",
                "project.created",
                "project.updated",
                "project.archived"
              ]
            }
          },
          "status": {
            "type": "string",
            "description": "Delivery status. `disabled` endpoints are retained but receive no events.",
            "enum": [
              "enabled",
              "disabled"
            ],
            "example": "enabled"
          },
          "description": {
            "type": "string",
            "description": "Optional human-facing description of what this endpoint is used for.",
            "example": "Production billing sync",
            "nullable": true
          },
          "createdAt": {
            "type": "string",
            "description": "ISO 8601 creation timestamp.",
            "example": "2026-05-29T10:00:00.000Z"
          },
          "updatedAt": {
            "type": "string",
            "description": "ISO 8601 last-update timestamp.",
            "example": "2026-05-29T10:00:00.000Z"
          }
        },
        "required": [
          "id",
          "url",
          "enabledEvents",
          "status",
          "createdAt",
          "updatedAt"
        ]
      },
      "WebhookEndpointList": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebhookEndpoint"
            }
          },
          "total": {
            "type": "number",
            "description": "Total number of endpoints matching the query.",
            "example": 3
          },
          "page": {
            "type": "number",
            "description": "Current page (1-based).",
            "example": 1
          },
          "pageSize": {
            "type": "number",
            "description": "Page size.",
            "example": 25
          }
        },
        "required": [
          "data",
          "total",
          "page",
          "pageSize"
        ]
      },
      "UpdateWebhookEndpointRequest": {
        "type": "object",
        "properties": {
          "url": {
            "type": "string",
            "description": "New HTTPS delivery URL.",
            "example": "https://example.com/webhooks/v2"
          },
          "enabledEvents": {
            "type": "array",
            "description": "Replace the full set of subscribed events.\n\nAvailable events:\n- `subscription.assigned` — Fired when a subscription is assigned to a customer (may be future-dated / upcoming).\n- `subscription.started` — Fired when a subscription becomes active — grant entitlement/access on this event, not on assigned.\n- `subscription.updated` — Fired when a config property changes without a structural transition (e.g. name, payment method, billing direction).\n- `subscription.transitioned` — Fired on a structural change: plan replace, product edit, billing cadence change, or realign.\n- `subscription.paused` — Fired when a subscription is paused.\n- `subscription.resumed` — Fired when a subscription resumes from a pause.\n- `subscription.trial_ended` — Fired when a subscription trial ends and normal billing begins (the sub stays active).\n- `subscription.cancellation_scheduled` — Fired when a future cancellation is scheduled for a subscription (still active until then).\n- `subscription.cancellation_cleared` — Fired when a previously scheduled cancellation is cleared.\n- `subscription.churned` — Fired when a subscription is cancelled/finalized — revoke entitlement on this event.\n- `subscription.billed` — Fired once per (child) subscription when a billing run produces its invoice.\n- `subscription.payment_succeeded` — Fired when a card charge for the subscription clears — the success pair of the charge_failed error signal.\n- `subscription.error` — Fired when a delivery/processing problem occurs for a subscription (e.g. undeliverable recipient).\n- `billing.invoice_sent` — Fired when an invoice document is sent to the customer.\n- `billing.credit_note_sent` — Fired when a credit note document is sent to the customer.\n- `customer.created` — Fired when a customer is created (payload flags whether it was a portal self-signup).\n- `card.added` — Fired when a card is successfully saved for a customer (provider-opaque).\n- `card.removed` — Fired when a saved card is removed in-app or cancelled at the provider.\n- `card.updated` — Fired when a saved card’s details change (network auto-update or refresh).\n- `card.expiring` — Fired when a saved card is approaching expiry.\n- `card.expired` — Fired when a saved card is observed to have expired.\n- `card.default_changed` — Fired when the customer’s default card changes (explicit or auto-default).\n- `card.backup_changed` — Fired when the customer’s designated backup card is set, replaced, or cleared.\n- `card.add_failed` — Fired when a card-save attempt fails (decline or authentication failure).\n- `quote.sent` — Fired when a quote is sent to the customer.\n- `quote.converted` — Fired when a quote is converted into an order confirmation or an invoice.\n- `order_confirmation.sent` — Fired when an order confirmation is sent to the customer.\n- `order_confirmation.converted` — Fired when an order confirmation is converted into an invoice.\n- `project.created` — Fired when a project is created (payload carries the owned dimension id for correlation with the dimensions API).\n- `project.updated` — Fired when a project's fields are updated (payload lists the changed field names). Also fires on un-archive.\n- `project.archived` — Fired when a project is archived (its dimension is deactivated; postings history is preserved).",
            "example": [
              "subscription.assigned"
            ],
            "items": {
              "type": "string",
              "enum": [
                "subscription.assigned",
                "subscription.started",
                "subscription.updated",
                "subscription.transitioned",
                "subscription.paused",
                "subscription.resumed",
                "subscription.trial_ended",
                "subscription.cancellation_scheduled",
                "subscription.cancellation_cleared",
                "subscription.churned",
                "subscription.billed",
                "subscription.payment_succeeded",
                "subscription.error",
                "billing.invoice_sent",
                "billing.credit_note_sent",
                "customer.created",
                "card.added",
                "card.removed",
                "card.updated",
                "card.expiring",
                "card.expired",
                "card.default_changed",
                "card.backup_changed",
                "card.add_failed",
                "quote.sent",
                "quote.converted",
                "order_confirmation.sent",
                "order_confirmation.converted",
                "project.created",
                "project.updated",
                "project.archived"
              ]
            }
          },
          "status": {
            "type": "string",
            "description": "Enable or disable delivery without deleting the endpoint.",
            "enum": [
              "enabled",
              "disabled"
            ]
          },
          "description": {
            "type": "string",
            "description": "Update the description. Send null to clear it.",
            "example": "Updated description",
            "maxLength": 512,
            "nullable": true
          }
        }
      },
      "TestWebhookEndpointRequest": {
        "type": "object",
        "properties": {
          "event": {
            "type": "string",
            "description": "The event type to simulate. Must be one of the endpoint’s subscribed events.\n\nAvailable events:\n- `subscription.assigned` — Fired when a subscription is assigned to a customer (may be future-dated / upcoming).\n- `subscription.started` — Fired when a subscription becomes active — grant entitlement/access on this event, not on assigned.\n- `subscription.updated` — Fired when a config property changes without a structural transition (e.g. name, payment method, billing direction).\n- `subscription.transitioned` — Fired on a structural change: plan replace, product edit, billing cadence change, or realign.\n- `subscription.paused` — Fired when a subscription is paused.\n- `subscription.resumed` — Fired when a subscription resumes from a pause.\n- `subscription.trial_ended` — Fired when a subscription trial ends and normal billing begins (the sub stays active).\n- `subscription.cancellation_scheduled` — Fired when a future cancellation is scheduled for a subscription (still active until then).\n- `subscription.cancellation_cleared` — Fired when a previously scheduled cancellation is cleared.\n- `subscription.churned` — Fired when a subscription is cancelled/finalized — revoke entitlement on this event.\n- `subscription.billed` — Fired once per (child) subscription when a billing run produces its invoice.\n- `subscription.payment_succeeded` — Fired when a card charge for the subscription clears — the success pair of the charge_failed error signal.\n- `subscription.error` — Fired when a delivery/processing problem occurs for a subscription (e.g. undeliverable recipient).\n- `billing.invoice_sent` — Fired when an invoice document is sent to the customer.\n- `billing.credit_note_sent` — Fired when a credit note document is sent to the customer.\n- `customer.created` — Fired when a customer is created (payload flags whether it was a portal self-signup).\n- `card.added` — Fired when a card is successfully saved for a customer (provider-opaque).\n- `card.removed` — Fired when a saved card is removed in-app or cancelled at the provider.\n- `card.updated` — Fired when a saved card’s details change (network auto-update or refresh).\n- `card.expiring` — Fired when a saved card is approaching expiry.\n- `card.expired` — Fired when a saved card is observed to have expired.\n- `card.default_changed` — Fired when the customer’s default card changes (explicit or auto-default).\n- `card.backup_changed` — Fired when the customer’s designated backup card is set, replaced, or cleared.\n- `card.add_failed` — Fired when a card-save attempt fails (decline or authentication failure).\n- `quote.sent` — Fired when a quote is sent to the customer.\n- `quote.converted` — Fired when a quote is converted into an order confirmation or an invoice.\n- `order_confirmation.sent` — Fired when an order confirmation is sent to the customer.\n- `order_confirmation.converted` — Fired when an order confirmation is converted into an invoice.\n- `project.created` — Fired when a project is created (payload carries the owned dimension id for correlation with the dimensions API).\n- `project.updated` — Fired when a project's fields are updated (payload lists the changed field names). Also fires on un-archive.\n- `project.archived` — Fired when a project is archived (its dimension is deactivated; postings history is preserved).",
            "enum": [
              "subscription.assigned",
              "subscription.started",
              "subscription.updated",
              "subscription.transitioned",
              "subscription.paused",
              "subscription.resumed",
              "subscription.trial_ended",
              "subscription.cancellation_scheduled",
              "subscription.cancellation_cleared",
              "subscription.churned",
              "subscription.billed",
              "subscription.payment_succeeded",
              "subscription.error",
              "billing.invoice_sent",
              "billing.credit_note_sent",
              "customer.created",
              "card.added",
              "card.removed",
              "card.updated",
              "card.expiring",
              "card.expired",
              "card.default_changed",
              "card.backup_changed",
              "card.add_failed",
              "quote.sent",
              "quote.converted",
              "order_confirmation.sent",
              "order_confirmation.converted",
              "project.created",
              "project.updated",
              "project.archived"
            ],
            "example": "subscription.assigned"
          }
        },
        "required": [
          "event"
        ]
      },
      "TestWebhookEndpointResult": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean",
            "description": "Whether the endpoint responded with a 2xx status.",
            "example": true
          },
          "statusCode": {
            "type": "number",
            "description": "HTTP status returned by the endpoint, or null on a transport error.",
            "example": 200,
            "nullable": true
          },
          "durationMs": {
            "type": "number",
            "description": "Round-trip time of the probe in milliseconds.",
            "example": 142
          },
          "error": {
            "type": "string",
            "description": "Transport/error message when the probe failed, otherwise null.",
            "example": null,
            "nullable": true
          }
        },
        "required": [
          "success",
          "durationMs"
        ]
      },
      "PublicCreateInvoiceLine": {
        "type": "object",
        "properties": {
          "priceId": {
            "type": "string",
            "description": "Product price ID. Required on a billable line — the line bills this product. Omit only for text / separator / discount lines (set lineType instead).",
            "example": "0197A943-2325-7829-B835-B6C71A293065"
          },
          "lineType": {
            "type": "string",
            "description": "Semantic type of the line (subscription, usage, discount, text, separator, etc.)",
            "enum": [
              "subscription",
              "usage",
              "proration_initial",
              "proration_post_trial",
              "proration_credit",
              "proration_charge",
              "proration_adjustment",
              "proration_phase_transition",
              "refund_prorated",
              "refund_full",
              "cancellation_credit",
              "discount",
              "interval_discount",
              "final_usage",
              "one_off",
              "text",
              "separator"
            ]
          },
          "description": {
            "type": "string",
            "description": "Custom description for this line item",
            "example": "Premium widget - Blue color"
          },
          "quantity": {
            "type": "number",
            "description": "Quantity. Required on a billable line; omit for text / separator / discount lines.",
            "example": 2
          },
          "unitPrice": {
            "type": "string",
            "description": "One-time unit-price override (decimal string). Defaults to the price's current amount in the document currency when omitted. totalPrice (= quantity * unitPrice) and VAT are always computed server-side and must not be sent.",
            "example": "1083.32"
          },
          "recognitionPeriodDays": {
            "type": "number",
            "description": "Override the revenue recognition period for this line (in days)",
            "example": 365
          }
        }
      },
      "PublicCreateInvoice": {
        "type": "object",
        "properties": {
          "customerId": {
            "type": "string",
            "description": "Customer ID this invoice is for. Required — every invoice must reference a customer (this mirrors the gated app, which also requires a customer).",
            "example": "0197A943-2325-7829-B835-B6C71A293065"
          },
          "customerDepartmentId": {
            "type": "string",
            "description": "Customer department ID (for EAN-based e-invoicing and address override)",
            "example": "0197A943-2325-7829-B835-B6C71A293065"
          },
          "customerContactId": {
            "type": "string",
            "description": "Customer contact ID (invoice recipient)",
            "example": "0197A943-2325-7829-B835-B6C71A293065"
          },
          "date": {
            "type": "string",
            "description": "Invoice date (ISO date, YYYY-MM-DD)",
            "example": "2024-01-15"
          },
          "dueDate": {
            "type": "string",
            "description": "Due date for payment (ISO date). Derived from payment terms when omitted.",
            "example": "2024-02-15"
          },
          "currency": {
            "type": "string",
            "description": "Currency code (ISO 4217). Defaults to the company default currency.",
            "example": "DKK"
          },
          "paymentTerms": {
            "type": "number",
            "description": "Payment terms in days",
            "example": 30
          },
          "reference": {
            "type": "string",
            "description": "Reference / PO number (\"PO-nr.\")",
            "example": "PO-12345"
          },
          "ourReference": {
            "type": "string",
            "description": "Our reference (\"Vores ref.\")",
            "example": "Jane Doe"
          },
          "description": {
            "type": "string",
            "description": "Optional description of the invoice",
            "example": "Monthly service invoice"
          },
          "notes": {
            "type": "string",
            "description": "Additional notes or comments",
            "example": "Thank you for your business!"
          },
          "lines": {
            "description": "Invoice lines",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PublicCreateInvoiceLine"
            }
          }
        },
        "required": [
          "customerId",
          "date",
          "lines"
        ]
      },
      "PublicInvoiceLine": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Line item ID",
            "example": "0197A943-2325-7829-B835-B6C71A293065"
          },
          "priceId": {
            "type": "string",
            "description": "Price ID this line references",
            "nullable": true
          },
          "description": {
            "type": "string",
            "description": "Custom description for this line item",
            "nullable": true
          },
          "lineType": {
            "type": "string",
            "description": "Semantic line type",
            "enum": [
              "subscription",
              "usage",
              "proration_initial",
              "proration_post_trial",
              "proration_credit",
              "proration_charge",
              "proration_adjustment",
              "proration_phase_transition",
              "refund_prorated",
              "refund_full",
              "cancellation_credit",
              "discount",
              "interval_discount",
              "final_usage",
              "one_off",
              "text",
              "separator"
            ],
            "nullable": true
          },
          "quantity": {
            "type": "number",
            "description": "Quantity",
            "example": 2
          },
          "unitPrice": {
            "type": "string",
            "description": "Unit price (decimal string)",
            "example": "1083.32"
          },
          "totalPrice": {
            "type": "string",
            "description": "Total price (decimal string)",
            "example": "2166.65"
          },
          "vatAmount": {
            "type": "string",
            "description": "VAT amount (decimal string)",
            "nullable": true
          },
          "vatRate": {
            "type": "string",
            "description": "VAT rate percentage (decimal string)",
            "nullable": true
          }
        },
        "required": [
          "id",
          "quantity",
          "unitPrice",
          "totalPrice"
        ]
      },
      "PublicInvoice": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Invoice ID",
            "example": "0197A943-2325-7829-B835-B6C71A293065"
          },
          "number": {
            "type": "string",
            "description": "Invoice number. Null while the invoice is still a draft (allocated at booking).",
            "nullable": true
          },
          "status": {
            "type": "string",
            "description": "Invoice status",
            "enum": [
              "draft",
              "scheduled",
              "sending",
              "sent",
              "paid",
              "partially_paid",
              "cancelled",
              "uncollectible",
              "credited"
            ],
            "example": "sent"
          },
          "date": {
            "type": "string",
            "description": "Invoice date (ISO date)",
            "example": "2024-01-15"
          },
          "dueDate": {
            "type": "string",
            "description": "Due date (ISO date)",
            "nullable": true
          },
          "customerId": {
            "type": "string",
            "description": "Customer ID",
            "nullable": true
          },
          "currency": {
            "type": "string",
            "description": "Currency code (ISO 4217)",
            "example": "DKK"
          },
          "subtotal": {
            "type": "string",
            "description": "Subtotal before VAT (decimal string)",
            "example": "2166.65"
          },
          "vat": {
            "type": "string",
            "description": "VAT amount (decimal string)",
            "example": "541.66"
          },
          "amount": {
            "type": "string",
            "description": "Total amount including VAT (decimal string)",
            "example": "2708.31"
          },
          "reference": {
            "type": "string",
            "description": "Reference / PO number",
            "nullable": true
          },
          "ourReference": {
            "type": "string",
            "description": "Our reference (\"Vores ref.\")",
            "nullable": true
          },
          "notes": {
            "type": "string",
            "description": "Additional notes",
            "nullable": true
          },
          "lines": {
            "description": "Invoice lines",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PublicInvoiceLine"
            }
          },
          "createdAt": {
            "type": "string",
            "description": "Creation timestamp (ISO)",
            "example": "2024-01-15T10:30:00.000Z"
          },
          "updatedAt": {
            "type": "string",
            "description": "Last update timestamp (ISO)",
            "example": "2024-01-15T10:30:00.000Z"
          }
        },
        "required": [
          "id",
          "status",
          "date",
          "currency",
          "subtotal",
          "vat",
          "amount",
          "lines",
          "createdAt",
          "updatedAt"
        ]
      },
      "PublicInvoiceListItem": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Invoice ID",
            "example": "0197A943-2325-7829-B835-B6C71A293065"
          },
          "number": {
            "type": "string",
            "description": "Invoice number. Null while the invoice is still a draft (allocated at booking).",
            "nullable": true
          },
          "status": {
            "type": "string",
            "description": "Invoice status",
            "enum": [
              "draft",
              "scheduled",
              "sending",
              "sent",
              "paid",
              "partially_paid",
              "cancelled",
              "uncollectible",
              "credited"
            ],
            "example": "sent"
          },
          "date": {
            "type": "string",
            "description": "Invoice date (ISO date)",
            "example": "2024-01-15"
          },
          "dueDate": {
            "type": "string",
            "description": "Due date (ISO date)",
            "nullable": true
          },
          "customerId": {
            "type": "string",
            "description": "Customer ID",
            "nullable": true
          },
          "currency": {
            "type": "string",
            "description": "Currency code (ISO 4217)",
            "example": "DKK"
          },
          "subtotal": {
            "type": "string",
            "description": "Subtotal before VAT (decimal string)",
            "example": "2166.65"
          },
          "vat": {
            "type": "string",
            "description": "VAT amount (decimal string)",
            "example": "541.66"
          },
          "amount": {
            "type": "string",
            "description": "Total amount including VAT (decimal string)",
            "example": "2708.31"
          },
          "reference": {
            "type": "string",
            "description": "Reference / PO number",
            "nullable": true
          },
          "ourReference": {
            "type": "string",
            "description": "Our reference (\"Vores ref.\")",
            "nullable": true
          },
          "notes": {
            "type": "string",
            "description": "Additional notes",
            "nullable": true
          },
          "createdAt": {
            "type": "string",
            "description": "Creation timestamp (ISO)",
            "example": "2024-01-15T10:30:00.000Z"
          },
          "updatedAt": {
            "type": "string",
            "description": "Last update timestamp (ISO)",
            "example": "2024-01-15T10:30:00.000Z"
          }
        },
        "required": [
          "id",
          "status",
          "date",
          "currency",
          "subtotal",
          "vat",
          "amount",
          "createdAt",
          "updatedAt"
        ]
      },
      "PublicListInvoicesResponse": {
        "type": "object",
        "properties": {
          "data": {
            "description": "Invoices on this page (line items omitted; GET one invoice for lines)",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PublicInvoiceListItem"
            }
          },
          "total": {
            "type": "number",
            "description": "Total invoices matching the query",
            "example": 42
          },
          "page": {
            "type": "number",
            "description": "Current page (1-indexed)",
            "example": 1
          },
          "limit": {
            "type": "number",
            "description": "Items per page",
            "example": 25
          },
          "totalPages": {
            "type": "number",
            "description": "Total pages",
            "example": 2
          }
        },
        "required": [
          "data",
          "total",
          "page",
          "limit",
          "totalPages"
        ]
      },
      "PublicSendInvoice": {
        "type": "object",
        "properties": {
          "deliveryType": {
            "type": "string",
            "description": "Delivery channel",
            "enum": [
              "Email",
              "Sproom",
              "Manual"
            ],
            "example": "Email"
          },
          "overrideEmail": {
            "type": "string",
            "description": "Override recipient email for this send only"
          },
          "overrideEanNumber": {
            "type": "string",
            "description": "Override EAN number for this send only"
          },
          "updateCustomerRecord": {
            "type": "boolean",
            "description": "Persist the override email / EAN onto the customer record",
            "default": false
          },
          "documentTemplateId": {
            "type": "string",
            "description": "Override document template for PDF generation"
          }
        },
        "required": [
          "deliveryType"
        ]
      },
      "PublicSendInvoiceResponse": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean",
            "description": "Whether the send was accepted",
            "example": true
          },
          "deliveryType": {
            "type": "string",
            "description": "The delivery channel the document was sent through",
            "enum": [
              "Email",
              "Sproom",
              "Manual"
            ],
            "example": "Email"
          },
          "sproomDocumentId": {
            "type": "string",
            "description": "Sproom document ID when sent via e-invoicing",
            "nullable": true
          }
        },
        "required": [
          "success",
          "deliveryType"
        ]
      },
      "PublicDeliveryStatusSummary": {
        "type": "object",
        "properties": {
          "sendCount": {
            "type": "number",
            "description": "Number of send attempts recorded",
            "example": 2
          },
          "lastDeliveryType": {
            "type": "string",
            "description": "Channel of the most recent send",
            "enum": [
              "Email",
              "Sproom",
              "Manual"
            ],
            "nullable": true
          },
          "lastRecipientEmail": {
            "type": "string",
            "description": "Recipient email of the most recent send",
            "nullable": true
          },
          "lastRecipientEan": {
            "type": "string",
            "description": "Recipient EAN of the most recent send",
            "nullable": true
          },
          "lastSentAt": {
            "type": "string",
            "description": "Timestamp of the most recent send (ISO)",
            "nullable": true
          }
        },
        "required": [
          "sendCount"
        ]
      },
      "PublicDeliveryLogEntry": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Delivery log entry ID"
          },
          "status": {
            "type": "string",
            "description": "Outcome of the delivery attempt",
            "enum": [
              "success",
              "failed"
            ]
          },
          "deliveryType": {
            "type": "string",
            "description": "Delivery channel",
            "enum": [
              "Email",
              "Sproom",
              "Manual"
            ]
          },
          "recipientEmail": {
            "type": "string",
            "description": "Recipient email (email sends)",
            "nullable": true
          },
          "recipientEan": {
            "type": "string",
            "description": "Recipient EAN (e-invoice sends)",
            "nullable": true
          },
          "sentAt": {
            "type": "string",
            "description": "Timestamp of the attempt (ISO)",
            "example": "2024-01-15T10:30:00.000Z"
          },
          "errorCode": {
            "type": "string",
            "description": "Error code when the attempt failed",
            "nullable": true
          }
        },
        "required": [
          "id",
          "status",
          "deliveryType",
          "sentAt"
        ]
      },
      "PublicDeliveryStatusResponse": {
        "type": "object",
        "properties": {
          "summary": {
            "description": "Aggregate send summary",
            "allOf": [
              {
                "$ref": "#/components/schemas/PublicDeliveryStatusSummary"
              }
            ]
          },
          "entries": {
            "description": "Per-attempt delivery log entries",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PublicDeliveryLogEntry"
            }
          }
        },
        "required": [
          "summary",
          "entries"
        ]
      },
      "PublicCreateCreditNoteLine": {
        "type": "object",
        "properties": {
          "priceId": {
            "type": "string",
            "description": "Product price ID. Required on a billable line — the line credits this product. Omit only for text / separator / discount lines (set lineType instead).",
            "example": "0197A943-2325-7829-B835-B6C71A293065"
          },
          "lineType": {
            "type": "string",
            "description": "Semantic type of the line (refund, cancellation credit, text, separator, etc.)",
            "enum": [
              "subscription",
              "usage",
              "proration_initial",
              "proration_post_trial",
              "proration_credit",
              "proration_charge",
              "proration_adjustment",
              "proration_phase_transition",
              "refund_prorated",
              "refund_full",
              "cancellation_credit",
              "discount",
              "interval_discount",
              "final_usage",
              "one_off",
              "text",
              "separator"
            ]
          },
          "description": {
            "type": "string",
            "description": "Custom description for this line item",
            "example": "Premium widget - Blue color - Return"
          },
          "quantity": {
            "type": "number",
            "description": "Quantity to credit. Required on a billable line; omit for text / separator / discount lines.",
            "example": 2
          },
          "unitPrice": {
            "type": "string",
            "description": "One-time unit-price override as a POSITIVE decimal string (the magnitude). Defaults to the price's current amount when omitted. The credit (negative) sign, totalPrice, and VAT are applied server-side and must not be sent.",
            "example": "1083.32"
          }
        }
      },
      "PublicCreateCreditNote": {
        "type": "object",
        "properties": {
          "customerId": {
            "type": "string",
            "description": "Customer ID this credit note is for",
            "example": "0197A943-2325-7829-B835-B6C71A293065"
          },
          "customerDepartmentId": {
            "type": "string",
            "description": "Customer department ID (for EAN-based e-invoicing and address override)",
            "example": "0197A943-2325-7829-B835-B6C71A293065"
          },
          "customerContactId": {
            "type": "string",
            "description": "Customer contact ID (credit note recipient)",
            "example": "0197A943-2325-7829-B835-B6C71A293065"
          },
          "invoiceNumber": {
            "type": "string",
            "description": "Original invoice number this credit note credits. When set, the referenced invoice is marked credited.",
            "example": "1"
          },
          "date": {
            "type": "string",
            "description": "Credit note date (ISO date, YYYY-MM-DD)",
            "example": "2024-01-15"
          },
          "currency": {
            "type": "string",
            "description": "Currency code (ISO 4217). Defaults to the company default currency.",
            "example": "DKK"
          },
          "reference": {
            "type": "string",
            "description": "Reference / PO number (\"PO-nr.\")",
            "example": "PO-12345"
          },
          "ourReference": {
            "type": "string",
            "description": "Our reference (\"Vores ref.\")",
            "example": "Jane Doe"
          },
          "description": {
            "type": "string",
            "description": "Optional description of the credit note",
            "example": "Credit for returned items"
          },
          "notes": {
            "type": "string",
            "description": "Additional notes or comments",
            "example": "Credit issued due to product defect"
          },
          "lines": {
            "description": "Credit note lines",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PublicCreateCreditNoteLine"
            }
          }
        },
        "required": [
          "customerId",
          "date",
          "lines"
        ]
      },
      "PublicCreditNoteLine": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Line item ID",
            "example": "0197A943-2325-7829-B835-B6C71A293065"
          },
          "priceId": {
            "type": "string",
            "description": "Price ID this line references",
            "nullable": true
          },
          "description": {
            "type": "string",
            "description": "Custom description for this line item",
            "nullable": true
          },
          "lineType": {
            "type": "string",
            "description": "Semantic line type",
            "enum": [
              "subscription",
              "usage",
              "proration_initial",
              "proration_post_trial",
              "proration_credit",
              "proration_charge",
              "proration_adjustment",
              "proration_phase_transition",
              "refund_prorated",
              "refund_full",
              "cancellation_credit",
              "discount",
              "interval_discount",
              "final_usage",
              "one_off",
              "text",
              "separator"
            ],
            "nullable": true
          },
          "quantity": {
            "type": "number",
            "description": "Quantity",
            "example": 2
          },
          "unitPrice": {
            "type": "string",
            "description": "Unit price (decimal string)",
            "example": "1083.32"
          },
          "totalPrice": {
            "type": "string",
            "description": "Total price (decimal string)",
            "example": "2166.65"
          },
          "vatAmount": {
            "type": "string",
            "description": "VAT amount (decimal string)",
            "nullable": true
          },
          "vatRate": {
            "type": "string",
            "description": "VAT rate percentage (decimal string)",
            "nullable": true
          }
        },
        "required": [
          "id",
          "quantity",
          "unitPrice",
          "totalPrice"
        ]
      },
      "PublicCreditNote": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Credit note ID",
            "example": "0197A943-2325-7829-B835-B6C71A293065"
          },
          "number": {
            "type": "string",
            "description": "Credit note number",
            "example": "1"
          },
          "invoiceNumber": {
            "type": "string",
            "description": "Original invoice number this credit note credits",
            "nullable": true
          },
          "status": {
            "type": "string",
            "description": "Credit note status",
            "enum": [
              "draft",
              "scheduled",
              "sending",
              "sent"
            ],
            "example": "sent"
          },
          "date": {
            "type": "string",
            "description": "Credit note date (ISO date)",
            "example": "2024-01-15"
          },
          "customerId": {
            "type": "string",
            "description": "Customer ID",
            "nullable": true
          },
          "currency": {
            "type": "string",
            "description": "Currency code (ISO 4217)",
            "example": "DKK"
          },
          "subtotal": {
            "type": "string",
            "description": "Subtotal before VAT (decimal string)",
            "example": "2166.65"
          },
          "vat": {
            "type": "string",
            "description": "VAT amount (decimal string)",
            "example": "541.66"
          },
          "amount": {
            "type": "string",
            "description": "Total amount including VAT (decimal string)",
            "example": "2708.31"
          },
          "reference": {
            "type": "string",
            "description": "Reference / PO number",
            "nullable": true
          },
          "ourReference": {
            "type": "string",
            "description": "Our reference (\"Vores ref.\")",
            "nullable": true
          },
          "notes": {
            "type": "string",
            "description": "Additional notes",
            "nullable": true
          },
          "lines": {
            "description": "Credit note lines",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PublicCreditNoteLine"
            }
          },
          "createdAt": {
            "type": "string",
            "description": "Creation timestamp (ISO)",
            "example": "2024-01-15T10:30:00.000Z"
          },
          "updatedAt": {
            "type": "string",
            "description": "Last update timestamp (ISO)",
            "example": "2024-01-15T10:30:00.000Z"
          }
        },
        "required": [
          "id",
          "number",
          "status",
          "date",
          "currency",
          "subtotal",
          "vat",
          "amount",
          "lines",
          "createdAt",
          "updatedAt"
        ]
      },
      "PublicCreditNoteListItem": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Credit note ID",
            "example": "0197A943-2325-7829-B835-B6C71A293065"
          },
          "number": {
            "type": "string",
            "description": "Credit note number",
            "example": "1"
          },
          "invoiceNumber": {
            "type": "string",
            "description": "Original invoice number this credit note credits",
            "nullable": true
          },
          "status": {
            "type": "string",
            "description": "Credit note status",
            "enum": [
              "draft",
              "scheduled",
              "sending",
              "sent"
            ],
            "example": "sent"
          },
          "date": {
            "type": "string",
            "description": "Credit note date (ISO date)",
            "example": "2024-01-15"
          },
          "customerId": {
            "type": "string",
            "description": "Customer ID",
            "nullable": true
          },
          "currency": {
            "type": "string",
            "description": "Currency code (ISO 4217)",
            "example": "DKK"
          },
          "subtotal": {
            "type": "string",
            "description": "Subtotal before VAT (decimal string)",
            "example": "2166.65"
          },
          "vat": {
            "type": "string",
            "description": "VAT amount (decimal string)",
            "example": "541.66"
          },
          "amount": {
            "type": "string",
            "description": "Total amount including VAT (decimal string)",
            "example": "2708.31"
          },
          "reference": {
            "type": "string",
            "description": "Reference / PO number",
            "nullable": true
          },
          "ourReference": {
            "type": "string",
            "description": "Our reference (\"Vores ref.\")",
            "nullable": true
          },
          "notes": {
            "type": "string",
            "description": "Additional notes",
            "nullable": true
          },
          "createdAt": {
            "type": "string",
            "description": "Creation timestamp (ISO)",
            "example": "2024-01-15T10:30:00.000Z"
          },
          "updatedAt": {
            "type": "string",
            "description": "Last update timestamp (ISO)",
            "example": "2024-01-15T10:30:00.000Z"
          }
        },
        "required": [
          "id",
          "number",
          "status",
          "date",
          "currency",
          "subtotal",
          "vat",
          "amount",
          "createdAt",
          "updatedAt"
        ]
      },
      "PublicListCreditNotesResponse": {
        "type": "object",
        "properties": {
          "data": {
            "description": "Credit notes on this page (line items omitted; GET one for lines)",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PublicCreditNoteListItem"
            }
          },
          "total": {
            "type": "number",
            "description": "Total credit notes matching the query",
            "example": 42
          },
          "page": {
            "type": "number",
            "description": "Current page (1-indexed)",
            "example": 1
          },
          "limit": {
            "type": "number",
            "description": "Items per page",
            "example": 25
          },
          "totalPages": {
            "type": "number",
            "description": "Total pages",
            "example": 2
          }
        },
        "required": [
          "data",
          "total",
          "page",
          "limit",
          "totalPages"
        ]
      },
      "PublicSendCreditNote": {
        "type": "object",
        "properties": {
          "deliveryType": {
            "type": "string",
            "description": "Delivery channel",
            "enum": [
              "Email",
              "Sproom",
              "Manual"
            ],
            "example": "Email"
          },
          "overrideEmail": {
            "type": "string",
            "description": "Override recipient email for this send only"
          },
          "overrideEanNumber": {
            "type": "string",
            "description": "Override EAN number for this send only"
          },
          "updateCustomerRecord": {
            "type": "boolean",
            "description": "Persist the override email / EAN onto the customer record",
            "default": false
          },
          "documentTemplateId": {
            "type": "string",
            "description": "Override document template for PDF generation"
          }
        },
        "required": [
          "deliveryType"
        ]
      },
      "PublicQuoteListItem": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Quote identifier"
          },
          "type": {
            "type": "string",
            "enum": [
              "quote",
              "orderConfirmation"
            ],
            "description": "Always \"quote\""
          },
          "status": {
            "type": "object",
            "description": "Stored lifecycle status (draft/sent/accepted/rejected)"
          },
          "displayStatus": {
            "type": "object",
            "description": "Status to display. Equals `status` except derived states: \"converted\" or \"expired\"."
          },
          "documentNumber": {
            "type": "string",
            "description": "Allocated quote number (null until sent)"
          },
          "date": {
            "type": "string",
            "description": "Quote date (ISO, YYYY-MM-DD)",
            "example": "2026-06-11"
          },
          "validUntil": {
            "type": "string",
            "description": "Valid-until date (ISO, YYYY-MM-DD)",
            "example": "2026-07-11"
          },
          "amount": {
            "type": "string",
            "description": "Total amount including VAT"
          },
          "subtotal": {
            "type": "string",
            "description": "Subtotal excluding VAT"
          },
          "vat": {
            "type": "string",
            "description": "Total VAT"
          },
          "currency": {
            "type": "string",
            "description": "Currency code",
            "example": "DKK"
          },
          "reference": {
            "type": "string",
            "description": "PO number (\"PO-nr.\")"
          },
          "ourReference": {
            "type": "string",
            "description": "Our reference (\"Vores ref.\")"
          },
          "notes": {
            "type": "string",
            "description": "Notes"
          },
          "customerId": {
            "type": "string",
            "description": "Customer id"
          },
          "sourceDocumentId": {
            "type": "string",
            "description": "Source document id (set when this quote originated from another document)"
          },
          "convertedToDocumentId": {
            "type": "string",
            "description": "Id of the order confirmation this quote was converted into"
          },
          "convertedToInvoiceId": {
            "type": "string",
            "description": "Id of the invoice this quote was converted into"
          },
          "sentAt": {
            "type": "string",
            "description": "Timestamp the quote was sent (ISO)"
          },
          "createdAt": {
            "type": "string",
            "description": "Created timestamp (ISO)"
          },
          "updatedAt": {
            "type": "string",
            "description": "Updated timestamp (ISO)"
          }
        },
        "required": [
          "id",
          "type",
          "status",
          "displayStatus",
          "date",
          "amount",
          "subtotal",
          "vat",
          "currency",
          "createdAt",
          "updatedAt"
        ]
      },
      "PublicListQuotesResponse": {
        "type": "object",
        "properties": {
          "data": {
            "description": "List of quotes (line items omitted; GET one quote for lines)",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PublicQuoteListItem"
            }
          },
          "total": {
            "type": "number",
            "description": "Total number of quotes matching the query",
            "example": 42
          },
          "page": {
            "type": "number",
            "description": "Current page number (1-indexed)",
            "example": 1
          },
          "limit": {
            "type": "number",
            "description": "Maximum number of items per page",
            "example": 25
          },
          "totalPages": {
            "type": "number",
            "description": "Total number of pages available",
            "example": 2
          }
        },
        "required": [
          "data",
          "total",
          "page",
          "limit",
          "totalPages"
        ]
      },
      "PublicQuoteLine": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Line identifier"
          },
          "description": {
            "type": "string",
            "description": "Line description shown on the quote"
          },
          "lineType": {
            "type": "string",
            "description": "Semantic line type"
          },
          "quantity": {
            "type": "number",
            "description": "Quantity",
            "example": 2
          },
          "unitPrice": {
            "type": "string",
            "description": "Unit price",
            "example": "1000.00"
          },
          "totalPrice": {
            "type": "string",
            "description": "Total price for the line",
            "example": "2000.00"
          },
          "vatRate": {
            "type": "string",
            "description": "VAT rate (percentage)",
            "example": "25"
          },
          "vatAmount": {
            "type": "string",
            "description": "VAT amount for the line"
          }
        },
        "required": [
          "id",
          "quantity",
          "unitPrice",
          "totalPrice"
        ]
      },
      "PublicQuote": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Quote identifier"
          },
          "type": {
            "type": "string",
            "enum": [
              "quote",
              "orderConfirmation"
            ],
            "description": "Always \"quote\""
          },
          "status": {
            "type": "object",
            "description": "Stored lifecycle status (draft/sent/accepted/rejected)"
          },
          "displayStatus": {
            "type": "object",
            "description": "Status to display. Equals `status` except derived states: \"converted\" or \"expired\"."
          },
          "documentNumber": {
            "type": "string",
            "description": "Allocated quote number (null until sent)"
          },
          "date": {
            "type": "string",
            "description": "Quote date (ISO, YYYY-MM-DD)",
            "example": "2026-06-11"
          },
          "validUntil": {
            "type": "string",
            "description": "Valid-until date (ISO, YYYY-MM-DD)",
            "example": "2026-07-11"
          },
          "amount": {
            "type": "string",
            "description": "Total amount including VAT"
          },
          "subtotal": {
            "type": "string",
            "description": "Subtotal excluding VAT"
          },
          "vat": {
            "type": "string",
            "description": "Total VAT"
          },
          "currency": {
            "type": "string",
            "description": "Currency code",
            "example": "DKK"
          },
          "reference": {
            "type": "string",
            "description": "PO number (\"PO-nr.\")"
          },
          "ourReference": {
            "type": "string",
            "description": "Our reference (\"Vores ref.\")"
          },
          "notes": {
            "type": "string",
            "description": "Notes"
          },
          "customerId": {
            "type": "string",
            "description": "Customer id"
          },
          "sourceDocumentId": {
            "type": "string",
            "description": "Source document id (set when this quote originated from another document)"
          },
          "convertedToDocumentId": {
            "type": "string",
            "description": "Id of the order confirmation this quote was converted into"
          },
          "convertedToInvoiceId": {
            "type": "string",
            "description": "Id of the invoice this quote was converted into"
          },
          "sentAt": {
            "type": "string",
            "description": "Timestamp the quote was sent (ISO)"
          },
          "createdAt": {
            "type": "string",
            "description": "Created timestamp (ISO)"
          },
          "updatedAt": {
            "type": "string",
            "description": "Updated timestamp (ISO)"
          },
          "lines": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PublicQuoteLine"
            }
          }
        },
        "required": [
          "id",
          "type",
          "status",
          "displayStatus",
          "date",
          "amount",
          "subtotal",
          "vat",
          "currency",
          "createdAt",
          "updatedAt",
          "lines"
        ]
      },
      "PublicCreateQuoteLine": {
        "type": "object",
        "properties": {
          "priceId": {
            "type": "string",
            "description": "Product price id. Required on a billable line — the line bills this product. Omit only for text / separator / discount lines (set lineType instead)."
          },
          "description": {
            "type": "string",
            "description": "Custom description for the line"
          },
          "lineType": {
            "type": "string",
            "description": "Semantic line type. Use text / separator / discount / interval_discount for non-billable lines; any other value marks the line billable (priceId + quantity required).",
            "enum": [
              "subscription",
              "usage",
              "proration_initial",
              "proration_post_trial",
              "proration_credit",
              "proration_charge",
              "proration_adjustment",
              "proration_phase_transition",
              "refund_prorated",
              "refund_full",
              "cancellation_credit",
              "discount",
              "interval_discount",
              "final_usage",
              "one_off",
              "text",
              "separator"
            ]
          },
          "quantity": {
            "type": "number",
            "description": "Quantity. Required on a billable line; omit for text / separator / discount lines.",
            "example": 2
          },
          "unitPrice": {
            "type": "string",
            "description": "One-time unit-price override. Defaults to the price's current amount in the document currency. totalPrice and VAT are computed server-side and must not be sent.",
            "example": "1000.00"
          }
        }
      },
      "PublicCreateQuote": {
        "type": "object",
        "properties": {
          "customerId": {
            "type": "string",
            "description": "Customer this quote is for"
          },
          "customerDepartmentId": {
            "type": "string",
            "description": "Customer department id"
          },
          "customerContactId": {
            "type": "string",
            "description": "Customer contact id (\"Deres ref.\")"
          },
          "date": {
            "type": "string",
            "description": "Quote date (ISO, YYYY-MM-DD)",
            "example": "2026-06-11"
          },
          "validUntil": {
            "type": "string",
            "description": "Valid-until date (ISO, YYYY-MM-DD)",
            "example": "2026-07-11"
          },
          "currency": {
            "type": "string",
            "description": "Currency code",
            "example": "DKK"
          },
          "reference": {
            "type": "string",
            "description": "PO number (\"PO-nr.\")"
          },
          "ourReference": {
            "type": "string",
            "description": "Our reference (\"Vores ref.\")"
          },
          "notes": {
            "type": "string",
            "description": "Notes shown on the quote"
          },
          "lines": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PublicCreateQuoteLine"
            }
          }
        },
        "required": [
          "customerId",
          "date",
          "lines"
        ]
      },
      "PublicSendQuote": {
        "type": "object",
        "properties": {
          "deliveryType": {
            "type": "string",
            "enum": [
              "Email",
              "Manual"
            ],
            "description": "Delivery method. Defaults to Manual. Sproom/e-invoice does not apply to quotes."
          },
          "recipientEmail": {
            "type": "string",
            "description": "Override recipient email for Email delivery"
          }
        }
      },
      "PublicConvertQuotePayload": {
        "type": "object",
        "properties": {
          "customerId": {
            "type": "string",
            "description": "Customer for the converted document"
          },
          "customerDepartmentId": {
            "type": "string",
            "description": "Customer department id"
          },
          "customerContactId": {
            "type": "string",
            "description": "Customer contact id"
          },
          "date": {
            "type": "string",
            "description": "Document date (ISO, YYYY-MM-DD)",
            "example": "2026-06-11"
          },
          "currency": {
            "type": "string",
            "description": "Currency code"
          },
          "reference": {
            "type": "string",
            "description": "PO number (\"PO-nr.\")"
          },
          "ourReference": {
            "type": "string",
            "description": "Our reference (\"Vores ref.\")"
          },
          "notes": {
            "type": "string",
            "description": "Notes"
          },
          "lines": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PublicCreateQuoteLine"
            }
          }
        },
        "required": [
          "customerId",
          "date",
          "lines"
        ]
      },
      "PublicConvertQuote": {
        "type": "object",
        "properties": {
          "target": {
            "type": "string",
            "enum": [
              "orderConfirmation",
              "invoice"
            ],
            "description": "Target to convert into. Use \"orderConfirmation\" to confirm the quote, or \"invoice\" to convert it directly into an invoice."
          },
          "document": {
            "description": "Edited target document (review-before-finalize). Omit to copy the source verbatim.",
            "allOf": [
              {
                "$ref": "#/components/schemas/PublicConvertQuotePayload"
              }
            ]
          }
        },
        "required": [
          "target"
        ]
      },
      "PublicConvertQuoteResult": {
        "type": "object",
        "properties": {
          "targetType": {
            "type": "string",
            "description": "Type of document produced by the conversion (\"invoice\" or \"orderConfirmation\")",
            "example": "orderConfirmation"
          },
          "targetId": {
            "type": "string",
            "description": "Identifier of the produced document"
          }
        },
        "required": [
          "targetType",
          "targetId"
        ]
      },
      "PublicUpdateQuote": {
        "type": "object",
        "properties": {
          "customerId": {
            "type": "string",
            "description": "Customer this quote is for"
          },
          "customerDepartmentId": {
            "type": "string",
            "description": "Customer department id"
          },
          "customerContactId": {
            "type": "string",
            "description": "Customer contact id (\"Deres ref.\")"
          },
          "date": {
            "type": "string",
            "description": "Quote date (ISO, YYYY-MM-DD)",
            "example": "2026-06-11"
          },
          "validUntil": {
            "type": "string",
            "description": "Valid-until date (ISO, YYYY-MM-DD)",
            "example": "2026-07-11"
          },
          "currency": {
            "type": "string",
            "description": "Currency code",
            "example": "DKK"
          },
          "reference": {
            "type": "string",
            "description": "PO number (\"PO-nr.\")"
          },
          "ourReference": {
            "type": "string",
            "description": "Our reference (\"Vores ref.\")"
          },
          "notes": {
            "type": "string",
            "description": "Notes shown on the quote"
          },
          "lines": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PublicCreateQuoteLine"
            }
          }
        },
        "required": [
          "customerId",
          "date",
          "lines"
        ]
      },
      "PublicOrderConfirmationListItem": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Document identifier"
          },
          "status": {
            "type": "object",
            "description": "Stored lifecycle status (draft/sent)"
          },
          "displayStatus": {
            "type": "object",
            "description": "Status to display. Equals `status` except the derived \"converted\" state."
          },
          "documentNumber": {
            "type": "string",
            "description": "Allocated document number (null until sent)"
          },
          "date": {
            "type": "string",
            "description": "Document date (ISO, YYYY-MM-DD)",
            "example": "2026-06-11"
          },
          "amount": {
            "type": "string",
            "description": "Total amount including VAT"
          },
          "subtotal": {
            "type": "string",
            "description": "Subtotal excluding VAT"
          },
          "vat": {
            "type": "string",
            "description": "Total VAT"
          },
          "currency": {
            "type": "string",
            "description": "Currency code",
            "example": "DKK"
          },
          "reference": {
            "type": "string",
            "description": "PO number (\"PO-nr.\")"
          },
          "ourReference": {
            "type": "string",
            "description": "Our reference (\"Vores ref.\")"
          },
          "notes": {
            "type": "string",
            "description": "Notes"
          },
          "customerId": {
            "type": "string",
            "description": "Customer id"
          },
          "sourceDocumentId": {
            "type": "string",
            "description": "Source document id (the quote this order confirmation was converted from)"
          },
          "convertedToInvoiceId": {
            "type": "string",
            "description": "Id of the invoice this order confirmation was converted into"
          },
          "sentAt": {
            "type": "string",
            "description": "Timestamp the document was sent (ISO)"
          },
          "createdAt": {
            "type": "string",
            "description": "Created timestamp (ISO)"
          },
          "updatedAt": {
            "type": "string",
            "description": "Updated timestamp (ISO)"
          }
        },
        "required": [
          "id",
          "status",
          "displayStatus",
          "date",
          "amount",
          "subtotal",
          "vat",
          "currency",
          "createdAt",
          "updatedAt"
        ]
      },
      "PublicListOrderConfirmationsResponse": {
        "type": "object",
        "properties": {
          "data": {
            "description": "List of order confirmations (line items omitted; GET one for lines)",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PublicOrderConfirmationListItem"
            }
          },
          "total": {
            "type": "number",
            "description": "Total number of documents matching the query",
            "example": 42
          },
          "page": {
            "type": "number",
            "description": "Current page number (1-indexed)",
            "example": 1
          },
          "limit": {
            "type": "number",
            "description": "Maximum number of items per page",
            "example": 25
          },
          "totalPages": {
            "type": "number",
            "description": "Total number of pages available",
            "example": 2
          }
        },
        "required": [
          "data",
          "total",
          "page",
          "limit",
          "totalPages"
        ]
      },
      "PublicOrderConfirmationLine": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Line identifier"
          },
          "description": {
            "type": "string",
            "description": "Line description shown on the document"
          },
          "lineType": {
            "type": "string",
            "description": "Semantic line type"
          },
          "quantity": {
            "type": "number",
            "description": "Quantity",
            "example": 2
          },
          "unitPrice": {
            "type": "string",
            "description": "Unit price",
            "example": "1000.00"
          },
          "totalPrice": {
            "type": "string",
            "description": "Total price for the line",
            "example": "2000.00"
          },
          "vatRate": {
            "type": "string",
            "description": "VAT rate (percentage)",
            "example": "25"
          },
          "vatAmount": {
            "type": "string",
            "description": "VAT amount for the line"
          }
        },
        "required": [
          "id",
          "quantity",
          "unitPrice",
          "totalPrice"
        ]
      },
      "PublicOrderConfirmation": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Document identifier"
          },
          "status": {
            "type": "object",
            "description": "Stored lifecycle status (draft/sent)"
          },
          "displayStatus": {
            "type": "object",
            "description": "Status to display. Equals `status` except the derived \"converted\" state."
          },
          "documentNumber": {
            "type": "string",
            "description": "Allocated document number (null until sent)"
          },
          "date": {
            "type": "string",
            "description": "Document date (ISO, YYYY-MM-DD)",
            "example": "2026-06-11"
          },
          "amount": {
            "type": "string",
            "description": "Total amount including VAT"
          },
          "subtotal": {
            "type": "string",
            "description": "Subtotal excluding VAT"
          },
          "vat": {
            "type": "string",
            "description": "Total VAT"
          },
          "currency": {
            "type": "string",
            "description": "Currency code",
            "example": "DKK"
          },
          "reference": {
            "type": "string",
            "description": "PO number (\"PO-nr.\")"
          },
          "ourReference": {
            "type": "string",
            "description": "Our reference (\"Vores ref.\")"
          },
          "notes": {
            "type": "string",
            "description": "Notes"
          },
          "customerId": {
            "type": "string",
            "description": "Customer id"
          },
          "sourceDocumentId": {
            "type": "string",
            "description": "Source document id (the quote this order confirmation was converted from)"
          },
          "convertedToInvoiceId": {
            "type": "string",
            "description": "Id of the invoice this order confirmation was converted into"
          },
          "sentAt": {
            "type": "string",
            "description": "Timestamp the document was sent (ISO)"
          },
          "createdAt": {
            "type": "string",
            "description": "Created timestamp (ISO)"
          },
          "updatedAt": {
            "type": "string",
            "description": "Updated timestamp (ISO)"
          },
          "lines": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PublicOrderConfirmationLine"
            }
          }
        },
        "required": [
          "id",
          "status",
          "displayStatus",
          "date",
          "amount",
          "subtotal",
          "vat",
          "currency",
          "createdAt",
          "updatedAt",
          "lines"
        ]
      },
      "PublicCreateOrderConfirmationLine": {
        "type": "object",
        "properties": {
          "priceId": {
            "type": "string",
            "description": "Product price id. Required on a billable line — the line bills this product. Omit only for text / separator / discount lines (set lineType instead)."
          },
          "description": {
            "type": "string",
            "description": "Custom description for the line"
          },
          "lineType": {
            "type": "string",
            "description": "Semantic line type. Use text / separator / discount / interval_discount for non-billable lines; any other value marks the line billable (priceId + quantity required).",
            "enum": [
              "subscription",
              "usage",
              "proration_initial",
              "proration_post_trial",
              "proration_credit",
              "proration_charge",
              "proration_adjustment",
              "proration_phase_transition",
              "refund_prorated",
              "refund_full",
              "cancellation_credit",
              "discount",
              "interval_discount",
              "final_usage",
              "one_off",
              "text",
              "separator"
            ]
          },
          "quantity": {
            "type": "number",
            "description": "Quantity. Required on a billable line; omit for text / separator / discount lines.",
            "example": 2
          },
          "unitPrice": {
            "type": "string",
            "description": "One-time unit-price override. Defaults to the price's current amount in the document currency. totalPrice and VAT are computed server-side and must not be sent.",
            "example": "1000.00"
          }
        }
      },
      "PublicCreateOrderConfirmation": {
        "type": "object",
        "properties": {
          "customerId": {
            "type": "string",
            "description": "Customer this order confirmation is for"
          },
          "customerDepartmentId": {
            "type": "string",
            "description": "Customer department id"
          },
          "customerContactId": {
            "type": "string",
            "description": "Customer contact id (\"Deres ref.\")"
          },
          "date": {
            "type": "string",
            "description": "Document date (ISO, YYYY-MM-DD)",
            "example": "2026-06-11"
          },
          "currency": {
            "type": "string",
            "description": "Currency code",
            "example": "DKK"
          },
          "reference": {
            "type": "string",
            "description": "PO number (\"PO-nr.\")"
          },
          "ourReference": {
            "type": "string",
            "description": "Our reference (\"Vores ref.\")"
          },
          "notes": {
            "type": "string",
            "description": "Notes shown on the document"
          },
          "lines": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PublicCreateOrderConfirmationLine"
            }
          }
        },
        "required": [
          "customerId",
          "date",
          "lines"
        ]
      },
      "PublicSendOrderConfirmation": {
        "type": "object",
        "properties": {
          "deliveryType": {
            "type": "string",
            "enum": [
              "Email",
              "Manual"
            ],
            "description": "Delivery method. Defaults to Manual. Sproom/e-invoice does not apply to order confirmations."
          },
          "recipientEmail": {
            "type": "string",
            "description": "Override recipient email for Email delivery"
          }
        }
      },
      "PublicConvertOrderConfirmationPayload": {
        "type": "object",
        "properties": {
          "customerId": {
            "type": "string",
            "description": "Customer for the converted document"
          },
          "customerDepartmentId": {
            "type": "string",
            "description": "Customer department id"
          },
          "customerContactId": {
            "type": "string",
            "description": "Customer contact id"
          },
          "date": {
            "type": "string",
            "description": "Document date (ISO, YYYY-MM-DD)",
            "example": "2026-06-11"
          },
          "currency": {
            "type": "string",
            "description": "Currency code"
          },
          "reference": {
            "type": "string",
            "description": "PO number (\"PO-nr.\")"
          },
          "ourReference": {
            "type": "string",
            "description": "Our reference (\"Vores ref.\")"
          },
          "notes": {
            "type": "string",
            "description": "Notes"
          },
          "lines": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PublicCreateOrderConfirmationLine"
            }
          }
        },
        "required": [
          "customerId",
          "date",
          "lines"
        ]
      },
      "PublicConvertOrderConfirmation": {
        "type": "object",
        "properties": {
          "target": {
            "type": "string",
            "enum": [
              "invoice"
            ],
            "description": "Target to convert into. An order confirmation only ever converts into an \"invoice\"."
          },
          "document": {
            "description": "Edited target document (review-before-finalize). Omit to copy the source verbatim.",
            "allOf": [
              {
                "$ref": "#/components/schemas/PublicConvertOrderConfirmationPayload"
              }
            ]
          }
        },
        "required": [
          "target"
        ]
      },
      "PublicConvertOrderConfirmationResult": {
        "type": "object",
        "properties": {
          "targetType": {
            "type": "string",
            "description": "Type of document produced by the conversion (always \"invoice\")",
            "example": "invoice"
          },
          "targetId": {
            "type": "string",
            "description": "Identifier of the produced document"
          }
        },
        "required": [
          "targetType",
          "targetId"
        ]
      },
      "PublicUpdateOrderConfirmation": {
        "type": "object",
        "properties": {
          "customerId": {
            "type": "string",
            "description": "Customer this order confirmation is for"
          },
          "customerDepartmentId": {
            "type": "string",
            "description": "Customer department id"
          },
          "customerContactId": {
            "type": "string",
            "description": "Customer contact id (\"Deres ref.\")"
          },
          "date": {
            "type": "string",
            "description": "Document date (ISO, YYYY-MM-DD)",
            "example": "2026-06-11"
          },
          "currency": {
            "type": "string",
            "description": "Currency code",
            "example": "DKK"
          },
          "reference": {
            "type": "string",
            "description": "PO number (\"PO-nr.\")"
          },
          "ourReference": {
            "type": "string",
            "description": "Our reference (\"Vores ref.\")"
          },
          "notes": {
            "type": "string",
            "description": "Notes shown on the document"
          },
          "status": {
            "type": "string",
            "description": "New stored status (validated against the document type: draft/sent for order confirmations)."
          },
          "lines": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PublicCreateOrderConfirmationLine"
            }
          }
        },
        "required": [
          "customerId",
          "date",
          "lines"
        ]
      },
      "ProductGroupResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The unique identifier of the product group",
            "example": "550e8400-e29b-41d4-a716-446655440000"
          },
          "number": {
            "type": "string",
            "description": "Unique product-group number within the company",
            "example": "PG001"
          },
          "name": {
            "type": "string",
            "description": "Name of the product group",
            "example": "Office Supplies"
          },
          "description": {
            "type": "string",
            "description": "Optional description",
            "example": "Products for office use",
            "nullable": true
          },
          "domesticAccountId": {
            "type": "string",
            "description": "Ledger account ID for domestic sales",
            "example": "550e8400-e29b-41d4-a716-446655440000"
          },
          "domesticAccountNumber": {
            "type": "number",
            "description": "Domestic account number",
            "example": 1010,
            "nullable": true
          },
          "domesticAccountName": {
            "type": "string",
            "description": "Domestic account name",
            "example": "Sales — domestic",
            "nullable": true
          },
          "euAccountId": {
            "type": "string",
            "description": "Ledger account ID for EU sales (Rubric B)",
            "nullable": true
          },
          "euAccountNumber": {
            "type": "number",
            "description": "EU account number",
            "nullable": true
          },
          "euAccountName": {
            "type": "string",
            "description": "EU account name",
            "nullable": true
          },
          "abroadAccountId": {
            "type": "string",
            "description": "Ledger account ID for sales abroad (Rubric C)",
            "nullable": true
          },
          "abroadAccountNumber": {
            "type": "number",
            "description": "Abroad account number",
            "nullable": true
          },
          "abroadAccountName": {
            "type": "string",
            "description": "Abroad account name",
            "nullable": true
          },
          "domesticWithoutVatAccountId": {
            "type": "string",
            "description": "Ledger account ID for domestic sales without VAT",
            "nullable": true
          },
          "domesticWithoutVatAccountNumber": {
            "type": "number",
            "description": "Domestic-without-VAT account number",
            "nullable": true
          },
          "domesticWithoutVatAccountName": {
            "type": "string",
            "description": "Domestic-without-VAT account name",
            "nullable": true
          },
          "productCount": {
            "type": "number",
            "description": "Number of products in this group (list responses only)",
            "example": 12
          },
          "createdAt": {
            "format": "date-time",
            "type": "string",
            "description": "When the product group was created",
            "example": "2024-01-15T10:30:00Z"
          },
          "updatedAt": {
            "format": "date-time",
            "type": "string",
            "description": "When the product group was last updated",
            "example": "2024-01-15T10:30:00Z"
          }
        },
        "required": [
          "id",
          "number",
          "name",
          "domesticAccountId",
          "createdAt",
          "updatedAt"
        ]
      },
      "ListProductGroupsResponse": {
        "type": "object",
        "properties": {
          "data": {
            "description": "Page of product groups",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ProductGroupResponse"
            }
          },
          "total": {
            "type": "number",
            "description": "Total number of matching product groups",
            "example": 42
          },
          "page": {
            "type": "number",
            "description": "Current page number",
            "example": 1
          },
          "limit": {
            "type": "number",
            "description": "Items per page",
            "example": 25
          },
          "totalPages": {
            "type": "number",
            "description": "Total number of pages",
            "example": 2
          }
        },
        "required": [
          "data",
          "total",
          "page",
          "limit",
          "totalPages"
        ]
      },
      "CreateProductGroupRequest": {
        "type": "object",
        "properties": {
          "number": {
            "type": "string",
            "description": "Unique product-group number within the company",
            "example": "PG001"
          },
          "name": {
            "type": "string",
            "description": "Name of the product group",
            "example": "Office Supplies"
          },
          "description": {
            "type": "string",
            "description": "Optional description",
            "example": "Products for office use"
          },
          "domesticAccountId": {
            "type": "string",
            "description": "Ledger account ID for domestic sales. Must reference an existing account that carries a VAT code valid for sales.",
            "example": "550e8400-e29b-41d4-a716-446655440000"
          },
          "euAccountId": {
            "type": "string",
            "description": "Ledger account ID for EU sales (Rubric B). Must carry a sales-valid VAT code."
          },
          "abroadAccountId": {
            "type": "string",
            "description": "Ledger account ID for sales abroad (Rubric C). Must carry a sales-valid VAT code."
          },
          "domesticWithoutVatAccountId": {
            "type": "string",
            "description": "Ledger account ID for domestic sales without VAT."
          }
        },
        "required": [
          "number",
          "name",
          "domesticAccountId",
          "euAccountId",
          "abroadAccountId",
          "domesticWithoutVatAccountId"
        ]
      },
      "UpdateProductGroupRequest": {
        "type": "object",
        "properties": {
          "number": {
            "type": "string",
            "description": "Unique product-group number within the company",
            "example": "PG001"
          },
          "name": {
            "type": "string",
            "description": "Name of the product group",
            "example": "Office Supplies"
          },
          "description": {
            "type": "string",
            "description": "Optional description",
            "example": "Products for office use"
          },
          "domesticAccountId": {
            "type": "string",
            "description": "Ledger account ID for domestic sales"
          },
          "euAccountId": {
            "type": "string",
            "description": "Ledger account ID for EU sales (Rubric B)"
          },
          "abroadAccountId": {
            "type": "string",
            "description": "Ledger account ID for sales abroad (Rubric C)"
          },
          "domesticWithoutVatAccountId": {
            "type": "string",
            "description": "Ledger account ID for domestic sales without VAT"
          }
        }
      },
      "ProductListItem": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The unique identifier of the product",
            "example": "550e8400-e29b-41d4-a716-446655440000"
          },
          "productNumber": {
            "type": "string",
            "description": "Unique product number within the company",
            "example": "P001"
          },
          "name": {
            "type": "string",
            "description": "Name of the product",
            "example": "Web Hosting"
          },
          "description": {
            "type": "string",
            "description": "Optional description",
            "nullable": true
          },
          "unit": {
            "type": "string",
            "description": "Unit of measurement",
            "example": "pcs"
          },
          "productGroupId": {
            "type": "string",
            "description": "Product group this product belongs to"
          },
          "productType": {
            "type": "string",
            "description": "Product type (goods or services) for EU VAT",
            "enum": [
              "goods",
              "services"
            ]
          },
          "isActive": {
            "type": "boolean",
            "description": "Whether the product is active",
            "example": true
          },
          "isArchived": {
            "type": "boolean",
            "description": "Whether the product is archived",
            "example": false
          },
          "isLocked": {
            "type": "boolean",
            "description": "Whether the product is locked (in use, cannot be deleted)",
            "example": false
          },
          "createdAt": {
            "format": "date-time",
            "type": "string",
            "description": "When the product was created",
            "example": "2024-01-15T10:30:00Z"
          },
          "updatedAt": {
            "format": "date-time",
            "type": "string",
            "description": "When the product was last updated",
            "example": "2024-01-15T10:30:00Z"
          }
        },
        "required": [
          "id",
          "productNumber",
          "name",
          "unit",
          "productGroupId",
          "productType",
          "isActive",
          "isArchived",
          "isLocked",
          "createdAt",
          "updatedAt"
        ]
      },
      "ListProductsResponse": {
        "type": "object",
        "properties": {
          "data": {
            "description": "Page of products (prices omitted; GET one product for its prices)",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ProductListItem"
            }
          },
          "total": {
            "type": "number",
            "description": "Total number of matching products",
            "example": 42
          },
          "page": {
            "type": "number",
            "description": "Current page number",
            "example": 1
          },
          "limit": {
            "type": "number",
            "description": "Items per page",
            "example": 25
          },
          "totalPages": {
            "type": "number",
            "description": "Total number of pages",
            "example": 2
          }
        },
        "required": [
          "data",
          "total",
          "page",
          "limit",
          "totalPages"
        ]
      },
      "ProductPriceTierResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Tier ID",
            "example": "550e8400-e29b-41d4-a716-446655440000"
          },
          "fromQuantity": {
            "type": "number",
            "description": "Starting quantity (inclusive)",
            "example": 1
          },
          "toQuantity": {
            "type": "number",
            "description": "Ending quantity (inclusive). Null = no upper limit.",
            "example": 10,
            "nullable": true
          },
          "unitAmount": {
            "type": "string",
            "description": "Price per unit for this tier",
            "example": "99.99"
          },
          "flatFee": {
            "type": "string",
            "description": "Optional flat fee for this tier",
            "example": "10.00",
            "nullable": true
          }
        },
        "required": [
          "id",
          "fromQuantity",
          "unitAmount"
        ]
      },
      "ProductPriceResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The unique identifier of the price (use as a line `priceId`)",
            "example": "550e8400-e29b-41d4-a716-446655440000"
          },
          "productId": {
            "type": "string",
            "description": "The product this price belongs to"
          },
          "nickname": {
            "type": "string",
            "description": "Optional nickname (e.g. \"Monthly\")",
            "nullable": true
          },
          "unitAmount": {
            "type": "string",
            "description": "Unit amount for flat-rate pricing in `currency`",
            "example": "99.99",
            "nullable": true
          },
          "billingPeriodType": {
            "type": "string",
            "description": "Billing period type",
            "enum": [
              "recurring",
              "usage",
              "one_time"
            ]
          },
          "pricingModel": {
            "type": "string",
            "description": "Pricing model",
            "enum": [
              "flat_rate",
              "package",
              "volume",
              "graduated"
            ]
          },
          "billingInterval": {
            "type": "string",
            "description": "Billing interval (null for one-time)",
            "enum": [
              "day",
              "week",
              "month",
              "year"
            ],
            "nullable": true
          },
          "billingIntervalCount": {
            "type": "number",
            "description": "Billing interval count",
            "example": 1,
            "nullable": true
          },
          "currency": {
            "type": "string",
            "description": "Currency of the displayed unitAmount (ISO 4217)",
            "example": "DKK"
          },
          "baseCurrency": {
            "type": "string",
            "description": "Base currency (source of truth for conversions)",
            "example": "DKK"
          },
          "availableCurrencies": {
            "description": "Currencies with a price-history entry",
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "status": {
            "type": "string",
            "description": "Price status",
            "enum": [
              "draft",
              "active",
              "inactive",
              "archived"
            ]
          },
          "isDefault": {
            "type": "boolean",
            "description": "Whether this is the default price for the product",
            "example": false
          },
          "isLocked": {
            "type": "boolean",
            "description": "Whether the price is locked (in use by a subscription/invoice)",
            "example": false
          },
          "meterId": {
            "type": "string",
            "description": "Meter ID for usage-based pricing",
            "nullable": true
          },
          "tiers": {
            "description": "Pricing tiers (package/volume/graduated)",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ProductPriceTierResponse"
            }
          },
          "vatRatesByZone": {
            "type": "object",
            "description": "VAT rates by zone (derived from the product group), e.g. { domestic: \"25\", eu: \"0\", abroad: \"0\", domestic_without_vat: \"0\" }"
          }
        },
        "required": [
          "id",
          "productId",
          "billingPeriodType",
          "pricingModel",
          "currency",
          "baseCurrency",
          "status",
          "isDefault",
          "isLocked",
          "vatRatesByZone"
        ]
      },
      "ProductResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The unique identifier of the product",
            "example": "550e8400-e29b-41d4-a716-446655440000"
          },
          "productNumber": {
            "type": "string",
            "description": "Unique product number within the company",
            "example": "P001"
          },
          "name": {
            "type": "string",
            "description": "Name of the product",
            "example": "Web Hosting"
          },
          "description": {
            "type": "string",
            "description": "Optional description",
            "nullable": true
          },
          "unit": {
            "type": "string",
            "description": "Unit of measurement",
            "example": "pcs"
          },
          "productGroupId": {
            "type": "string",
            "description": "Product group this product belongs to"
          },
          "productType": {
            "type": "string",
            "description": "Product type (goods or services) for EU VAT",
            "enum": [
              "goods",
              "services"
            ]
          },
          "isActive": {
            "type": "boolean",
            "description": "Whether the product is active",
            "example": true
          },
          "isArchived": {
            "type": "boolean",
            "description": "Whether the product is archived",
            "example": false
          },
          "isLocked": {
            "type": "boolean",
            "description": "Whether the product is locked (in use, cannot be deleted)",
            "example": false
          },
          "prices": {
            "description": "Prices configured for this product",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ProductPriceResponse"
            }
          },
          "createdAt": {
            "format": "date-time",
            "type": "string",
            "description": "When the product was created",
            "example": "2024-01-15T10:30:00Z"
          },
          "updatedAt": {
            "format": "date-time",
            "type": "string",
            "description": "When the product was last updated",
            "example": "2024-01-15T10:30:00Z"
          }
        },
        "required": [
          "id",
          "productNumber",
          "name",
          "unit",
          "productGroupId",
          "productType",
          "isActive",
          "isArchived",
          "isLocked",
          "createdAt",
          "updatedAt"
        ]
      },
      "CreateProductPriceTierRequest": {
        "type": "object",
        "properties": {
          "fromQuantity": {
            "type": "number",
            "description": "Starting quantity (inclusive)",
            "example": 1
          },
          "toQuantity": {
            "type": "number",
            "description": "Ending quantity (inclusive). Omit for the open-ended top tier.",
            "example": 10
          },
          "unitAmount": {
            "type": "string",
            "description": "Price per unit for this tier",
            "example": "99.99"
          },
          "flatFee": {
            "type": "string",
            "description": "Optional flat fee for this tier",
            "example": "10.00"
          }
        },
        "required": [
          "fromQuantity",
          "unitAmount"
        ]
      },
      "CreateProductInitialPriceRequest": {
        "type": "object",
        "properties": {
          "nickname": {
            "type": "string",
            "description": "Optional nickname (e.g. \"Monthly\")",
            "example": "Monthly"
          },
          "unitAmount": {
            "type": "string",
            "description": "Unit amount. Required for FLAT_RATE pricing; for tiered models (PACKAGE/VOLUME/GRADUATED) the amounts live in `tiers`.",
            "example": "99.99"
          },
          "billingPeriodType": {
            "type": "string",
            "description": "Billing period type. RECURRING requires a Subscription license; USAGE requires Subscription + Metered Products.",
            "enum": [
              "recurring",
              "usage",
              "one_time"
            ]
          },
          "pricingModel": {
            "type": "string",
            "description": "Pricing model",
            "enum": [
              "flat_rate",
              "package",
              "volume",
              "graduated"
            ]
          },
          "billingInterval": {
            "type": "string",
            "description": "Billing interval (required unless one-time)",
            "enum": [
              "day",
              "week",
              "month",
              "year"
            ]
          },
          "billingIntervalCount": {
            "type": "number",
            "description": "Billing interval count",
            "example": 1
          },
          "currency": {
            "type": "string",
            "description": "Currency code (ISO 4217)",
            "example": "DKK"
          },
          "meterId": {
            "type": "string",
            "description": "Meter ID (required for USAGE pricing)"
          },
          "tiers": {
            "description": "Pricing tiers. Required for tiered models: PACKAGE (exactly 1), VOLUME / GRADUATED (one or more, last tier open-ended). Omit for FLAT_RATE.",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CreateProductPriceTierRequest"
            }
          }
        },
        "required": [
          "billingPeriodType",
          "pricingModel"
        ]
      },
      "CreateProductRequest": {
        "type": "object",
        "properties": {
          "productNumber": {
            "type": "string",
            "description": "Unique product number within the company",
            "example": "P001"
          },
          "name": {
            "type": "string",
            "description": "Name of the product",
            "example": "Web Hosting"
          },
          "description": {
            "type": "string",
            "description": "Optional description"
          },
          "unit": {
            "type": "string",
            "description": "Unit of measurement",
            "example": "pcs"
          },
          "productGroupId": {
            "type": "string",
            "description": "Product group this product belongs to (must exist)",
            "example": "550e8400-e29b-41d4-a716-446655440000"
          },
          "isActive": {
            "type": "boolean",
            "description": "Whether the product is active",
            "default": true
          },
          "productType": {
            "type": "string",
            "description": "Product type (goods or services)",
            "enum": [
              "goods",
              "services"
            ],
            "default": "services"
          },
          "initialPrice": {
            "description": "Optional initial price. If provided it is created, activated and set as default in one transaction.",
            "allOf": [
              {
                "$ref": "#/components/schemas/CreateProductInitialPriceRequest"
              }
            ]
          }
        },
        "required": [
          "productNumber",
          "name",
          "unit",
          "productGroupId"
        ]
      },
      "UpdateProductRequest": {
        "type": "object",
        "properties": {
          "productNumber": {
            "type": "string",
            "description": "Unique product number within the company",
            "example": "P001"
          },
          "name": {
            "type": "string",
            "description": "Name of the product",
            "example": "Web Hosting"
          },
          "description": {
            "type": "string",
            "description": "Optional description"
          },
          "unit": {
            "type": "string",
            "description": "Unit of measurement",
            "example": "pcs"
          },
          "productGroupId": {
            "type": "string",
            "description": "Product group this product belongs to"
          },
          "isActive": {
            "type": "boolean",
            "description": "Whether the product is active"
          },
          "productType": {
            "type": "string",
            "description": "Product type (goods or services)",
            "enum": [
              "goods",
              "services"
            ]
          }
        }
      },
      "CreateProductPriceRequest": {
        "type": "object",
        "properties": {
          "productId": {
            "type": "string",
            "description": "The product this price belongs to",
            "example": "550e8400-e29b-41d4-a716-446655440000"
          },
          "nickname": {
            "type": "string",
            "description": "Optional nickname (e.g. \"Monthly\")",
            "example": "Monthly"
          },
          "unitAmount": {
            "type": "string",
            "description": "Unit amount. Required for FLAT_RATE pricing; for tiered models (PACKAGE/VOLUME/GRADUATED) the amounts live in `tiers`.",
            "example": "99.99"
          },
          "billingPeriodType": {
            "type": "string",
            "description": "Billing period type. RECURRING requires a Subscription license; USAGE requires Subscription + Metered Products.",
            "enum": [
              "recurring",
              "usage",
              "one_time"
            ]
          },
          "pricingModel": {
            "type": "string",
            "description": "Pricing model",
            "enum": [
              "flat_rate",
              "package",
              "volume",
              "graduated"
            ]
          },
          "billingInterval": {
            "type": "string",
            "description": "Billing interval (required unless one-time)",
            "enum": [
              "day",
              "week",
              "month",
              "year"
            ]
          },
          "billingIntervalCount": {
            "type": "number",
            "description": "Billing interval count",
            "example": 1
          },
          "currency": {
            "type": "string",
            "description": "Currency code (ISO 4217). Defaults to the company default.",
            "example": "DKK"
          },
          "meterId": {
            "type": "string",
            "description": "Meter ID (required for USAGE pricing)"
          },
          "tiers": {
            "description": "Pricing tiers. Required for tiered models: PACKAGE (exactly 1), VOLUME / GRADUATED (one or more, last tier open-ended). Omit for FLAT_RATE.",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CreateProductPriceTierRequest"
            }
          }
        },
        "required": [
          "productId",
          "billingPeriodType",
          "pricingModel"
        ]
      },
      "UpdateProductPriceRequest": {
        "type": "object",
        "properties": {
          "nickname": {
            "type": "string",
            "description": "Optional nickname",
            "example": "Monthly"
          },
          "unitAmount": {
            "type": "string",
            "description": "Unit amount for flat-rate pricing",
            "example": "99.99"
          },
          "billingPeriodType": {
            "type": "string",
            "description": "Billing period type",
            "enum": [
              "recurring",
              "usage",
              "one_time"
            ]
          },
          "pricingModel": {
            "type": "string",
            "description": "Pricing model",
            "enum": [
              "flat_rate",
              "package",
              "volume",
              "graduated"
            ]
          },
          "billingInterval": {
            "type": "string",
            "description": "Billing interval (null for one-time)",
            "enum": [
              "day",
              "week",
              "month",
              "year"
            ],
            "nullable": true
          },
          "billingIntervalCount": {
            "type": "number",
            "description": "Billing interval count",
            "example": 1
          },
          "currency": {
            "type": "string",
            "description": "Currency code (ISO 4217)",
            "example": "DKK"
          },
          "status": {
            "type": "string",
            "description": "Price status",
            "enum": [
              "draft",
              "active",
              "inactive",
              "archived"
            ]
          },
          "meterId": {
            "type": "string",
            "description": "Meter ID for usage-based pricing"
          },
          "tiers": {
            "description": "Pricing tiers",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CreateProductPriceTierRequest"
            }
          }
        }
      },
      "DocumentTemplateListItem": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The unique identifier of the template",
            "example": "550e8400-e29b-41d4-a716-446655440000"
          },
          "name": {
            "type": "string",
            "description": "Template name",
            "example": "Premium Invoice"
          },
          "documentType": {
            "type": "string",
            "description": "Document type this template applies to",
            "enum": [
              "invoice-template",
              "credit-note-template",
              "quote-template",
              "order-confirmation-template"
            ]
          },
          "isDefault": {
            "type": "boolean",
            "description": "Whether this is the default template for its document type",
            "example": false
          },
          "createdAt": {
            "format": "date-time",
            "type": "string",
            "description": "When the template was created",
            "example": "2024-01-15T10:30:00Z"
          },
          "updatedAt": {
            "format": "date-time",
            "type": "string",
            "description": "When the template was last updated",
            "example": "2024-01-15T10:30:00Z"
          }
        },
        "required": [
          "id",
          "name",
          "documentType",
          "isDefault",
          "createdAt",
          "updatedAt"
        ]
      },
      "ListDocumentTemplatesResponse": {
        "type": "object",
        "properties": {
          "data": {
            "description": "Page of document templates",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/DocumentTemplateListItem"
            }
          },
          "total": {
            "type": "number",
            "description": "Total number of matching templates",
            "example": 7
          },
          "page": {
            "type": "number",
            "description": "Current page number",
            "example": 1
          },
          "limit": {
            "type": "number",
            "description": "Items per page",
            "example": 25
          },
          "totalPages": {
            "type": "number",
            "description": "Total number of pages",
            "example": 1
          }
        },
        "required": [
          "data",
          "total",
          "page",
          "limit",
          "totalPages"
        ]
      },
      "ProjectSubproject": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Unique identifier of the subproject.",
            "example": "550e8400-e29b-41d4-a716-446655440010"
          },
          "dimensionValueId": {
            "type": "string",
            "description": "The journal-tag value ID that represents this subproject in the dimensions system. Use this value when tagging ledger transactions to the subproject.",
            "example": "550e8400-e29b-41d4-a716-446655440011"
          },
          "name": {
            "type": "string",
            "description": "Display name of the subproject.",
            "example": "Phase 1"
          },
          "isDefault": {
            "type": "boolean",
            "description": "Whether this is the default (catch-all) subproject for the project.",
            "example": false
          },
          "budgetHours": {
            "type": "number",
            "description": "Budget in hours for this subproject. Null when no budget is set.",
            "example": 120,
            "nullable": true
          },
          "budgetAmount": {
            "type": "number",
            "description": "Budget amount in the project currency for this subproject. Null when no budget is set.",
            "example": 15000,
            "nullable": true
          },
          "color": {
            "type": "string",
            "description": "Hex colour code for visual identification in the UI. Null when not set.",
            "example": "#4A90E2",
            "nullable": true
          },
          "sortOrder": {
            "type": "number",
            "description": "Display sort order (ascending).",
            "example": 1
          }
        },
        "required": [
          "id",
          "dimensionValueId",
          "name",
          "isDefault",
          "sortOrder"
        ]
      },
      "Project": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Unique identifier of the project.",
            "example": "550e8400-e29b-41d4-a716-446655440000"
          },
          "name": {
            "type": "string",
            "description": "Display name of the project.",
            "example": "Website Redesign 2025"
          },
          "isArchived": {
            "type": "boolean",
            "description": "Whether the project has been archived. Archived projects are read-only.",
            "example": false
          },
          "customerId": {
            "type": "string",
            "description": "ID of the customer this project belongs to. Null when not linked to a customer.",
            "example": "550e8400-e29b-41d4-a716-446655440001",
            "nullable": true
          },
          "currency": {
            "type": "string",
            "description": "ISO 4217 currency code used for budget amounts on this project.",
            "example": "DKK"
          },
          "budgetHours": {
            "type": "number",
            "description": "Total budget in hours across all subprojects. Null when not set.",
            "example": 500,
            "nullable": true
          },
          "budgetAmount": {
            "type": "number",
            "description": "Total budget amount in the project currency. Null when not set.",
            "example": 100000,
            "nullable": true
          },
          "startDate": {
            "type": "string",
            "description": "Project start date (inclusive), ISO 8601 date string. Null when not set.",
            "example": "2025-01-01",
            "nullable": true
          },
          "endDate": {
            "type": "string",
            "description": "Project end date (inclusive), ISO 8601 date string. Null when not set.",
            "example": "2025-12-31",
            "nullable": true
          },
          "externalReference": {
            "type": "string",
            "description": "Your system external reference for this project. Useful for idempotent upserts and cross-system reconciliation. Null when not set.",
            "example": "proj-external-123",
            "nullable": true
          },
          "color": {
            "type": "string",
            "description": "Hex colour code for visual identification. Null when not set.",
            "example": "#FF5733",
            "nullable": true
          },
          "dimensionId": {
            "type": "string",
            "description": "The dimension category ID (journal-tag category) that backs this project. Subproject values live as dimension values under this category.",
            "example": "550e8400-e29b-41d4-a716-446655440002"
          },
          "defaultSubprojectId": {
            "type": "string",
            "description": "ID of the default subproject (the catch-all subproject created with the project).",
            "example": "550e8400-e29b-41d4-a716-446655440010"
          },
          "subprojects": {
            "description": "All subprojects for this project, sorted by sortOrder ascending.",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ProjectSubproject"
            }
          },
          "createdAt": {
            "type": "string",
            "description": "ISO 8601 timestamp when the project was created.",
            "example": "2025-01-15T10:00:00.000Z"
          },
          "updatedAt": {
            "type": "string",
            "description": "ISO 8601 timestamp when the project was last updated.",
            "example": "2025-06-01T14:30:00.000Z"
          }
        },
        "required": [
          "id",
          "name",
          "isArchived",
          "currency",
          "dimensionId",
          "defaultSubprojectId",
          "subprojects",
          "createdAt",
          "updatedAt"
        ]
      },
      "UpsertProjectRequest": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "description": "Display name for the project. Must be unique within your company.",
            "example": "Website Redesign 2025",
            "minLength": 1,
            "maxLength": 120
          },
          "customerId": {
            "type": "string",
            "description": "ID of the customer this project belongs to.",
            "example": "550e8400-e29b-41d4-a716-446655440001",
            "nullable": true
          },
          "currency": {
            "type": "string",
            "description": "ISO 4217 currency code for budget amounts. Defaults to the customer's currency or the company base currency when omitted.",
            "example": "DKK",
            "minLength": 3,
            "maxLength": 3
          },
          "budgetHours": {
            "type": "number",
            "description": "Total budget in hours. Null clears the budget.",
            "example": 500,
            "nullable": true
          },
          "budgetAmount": {
            "type": "number",
            "description": "Total budget amount in the project currency. Null clears the budget.",
            "example": 100000,
            "nullable": true
          },
          "startDate": {
            "type": "string",
            "description": "Project start date (inclusive), ISO 8601 date string.",
            "example": "2025-01-01",
            "nullable": true
          },
          "endDate": {
            "type": "string",
            "description": "Project end date (inclusive), ISO 8601 date string.",
            "example": "2025-12-31",
            "nullable": true
          },
          "externalReference": {
            "type": "string",
            "description": "Your system external reference for this project. Must be unique within your company. The upsert finds an existing project by this value and updates it, or creates a new one.",
            "example": "proj-external-123",
            "nullable": true,
            "minLength": 1,
            "maxLength": 255
          },
          "color": {
            "type": "string",
            "description": "Hex colour code for visual identification.",
            "example": "#FF5733",
            "nullable": true,
            "maxLength": 16
          }
        },
        "required": [
          "name"
        ]
      },
      "CreateProjectRequest": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "description": "Display name for the project. Must be unique within your company.",
            "example": "Website Redesign 2025",
            "minLength": 1,
            "maxLength": 120
          },
          "customerId": {
            "type": "string",
            "description": "ID of the customer this project belongs to.",
            "example": "550e8400-e29b-41d4-a716-446655440001",
            "nullable": true
          },
          "currency": {
            "type": "string",
            "description": "ISO 4217 currency code for budget amounts. Defaults to the customer's currency or the company base currency when omitted.",
            "example": "DKK",
            "minLength": 3,
            "maxLength": 3
          },
          "budgetHours": {
            "type": "number",
            "description": "Total budget in hours. Null clears the budget.",
            "example": 500,
            "nullable": true
          },
          "budgetAmount": {
            "type": "number",
            "description": "Total budget amount in the project currency. Null clears the budget.",
            "example": 100000,
            "nullable": true
          },
          "startDate": {
            "type": "string",
            "description": "Project start date (inclusive), ISO 8601 date string.",
            "example": "2025-01-01",
            "nullable": true
          },
          "endDate": {
            "type": "string",
            "description": "Project end date (inclusive), ISO 8601 date string.",
            "example": "2025-12-31",
            "nullable": true
          },
          "externalReference": {
            "type": "string",
            "description": "Your system external reference for this project. Must be unique within your company. Can be used for idempotent upserts via PUT /.",
            "example": "proj-external-123",
            "nullable": true,
            "minLength": 1,
            "maxLength": 255
          },
          "color": {
            "type": "string",
            "description": "Hex colour code for visual identification.",
            "example": "#FF5733",
            "nullable": true,
            "maxLength": 16
          }
        },
        "required": [
          "name"
        ]
      },
      "ProjectProfitTotals": {
        "type": "object",
        "properties": {
          "revenue": {
            "type": "number",
            "description": "Base-currency revenue in the date range (positive figure, sign-flipped from REVENUE ledgers).",
            "example": 80000
          },
          "cost": {
            "type": "number",
            "description": "Base-currency cost in the date range (positive figure, EXPENSE ledgers).",
            "example": 60000
          },
          "profit": {
            "type": "number",
            "description": "revenue - cost.",
            "example": 20000
          },
          "budgetAmount": {
            "type": "number",
            "description": "The budget amount this burn is measured against. Null when no budget is set.",
            "example": 100000,
            "nullable": true
          },
          "burnPercent": {
            "type": "number",
            "description": "cost / budgetAmount * 100, rounded. Null when no budget is set or budgetAmount is 0.",
            "example": 60,
            "nullable": true
          },
          "isOverBudget": {
            "type": "boolean",
            "description": "True when burnPercent > 100 (over budget). False when under budget or no budget.",
            "example": false
          }
        },
        "required": [
          "revenue",
          "cost",
          "profit",
          "isOverBudget"
        ]
      },
      "ProjectSubprojectProfit": {
        "type": "object",
        "properties": {
          "revenue": {
            "type": "number",
            "description": "Base-currency revenue in the date range (positive figure, sign-flipped from REVENUE ledgers).",
            "example": 80000
          },
          "cost": {
            "type": "number",
            "description": "Base-currency cost in the date range (positive figure, EXPENSE ledgers).",
            "example": 60000
          },
          "profit": {
            "type": "number",
            "description": "revenue - cost.",
            "example": 20000
          },
          "budgetAmount": {
            "type": "number",
            "description": "The budget amount this burn is measured against. Null when no budget is set.",
            "example": 100000,
            "nullable": true
          },
          "burnPercent": {
            "type": "number",
            "description": "cost / budgetAmount * 100, rounded. Null when no budget is set or budgetAmount is 0.",
            "example": 60,
            "nullable": true
          },
          "isOverBudget": {
            "type": "boolean",
            "description": "True when burnPercent > 100 (over budget). False when under budget or no budget.",
            "example": false
          },
          "subprojectId": {
            "type": "string",
            "description": "Subproject ID.",
            "example": "550e8400-e29b-41d4-a716-446655440010"
          },
          "dimensionValueId": {
            "type": "string",
            "description": "The dimension value ID (journal-tag ID) for this subproject.",
            "example": "550e8400-e29b-41d4-a716-446655440011"
          },
          "name": {
            "type": "string",
            "description": "Display name of the subproject.",
            "example": "Phase 1"
          },
          "isDefault": {
            "type": "boolean",
            "description": "Whether this is the default (catch-all) subproject.",
            "example": false
          }
        },
        "required": [
          "revenue",
          "cost",
          "profit",
          "isOverBudget",
          "subprojectId",
          "dimensionValueId",
          "name",
          "isDefault"
        ]
      },
      "ProjectProfit": {
        "type": "object",
        "properties": {
          "projectId": {
            "type": "string",
            "description": "Project ID.",
            "example": "550e8400-e29b-41d4-a716-446655440000"
          },
          "from": {
            "type": "string",
            "description": "Inclusive range start actually used (after defaulting), YYYY-MM-DD.",
            "example": "2025-01-01"
          },
          "to": {
            "type": "string",
            "description": "Inclusive range end actually used (after defaulting), YYYY-MM-DD.",
            "example": "2025-12-31"
          },
          "currency": {
            "type": "string",
            "description": "Company base currency the amounts are expressed in.",
            "example": "DKK"
          },
          "total": {
            "description": "Aggregate totals for the project.",
            "allOf": [
              {
                "$ref": "#/components/schemas/ProjectProfitTotals"
              }
            ]
          },
          "subprojects": {
            "description": "Per-subproject profit breakdown.",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ProjectSubprojectProfit"
            }
          }
        },
        "required": [
          "projectId",
          "from",
          "to",
          "currency",
          "total",
          "subprojects"
        ]
      },
      "UpdateProjectRequest": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "description": "New display name for the project.",
            "example": "Website Redesign 2026",
            "minLength": 1,
            "maxLength": 120
          },
          "customerId": {
            "type": "string",
            "description": "Customer ID. Null clears the customer link.",
            "example": "550e8400-e29b-41d4-a716-446655440001",
            "nullable": true
          },
          "currency": {
            "type": "string",
            "description": "ISO 4217 currency code.",
            "example": "EUR",
            "minLength": 3,
            "maxLength": 3
          },
          "budgetHours": {
            "type": "number",
            "description": "Budget in hours. Null clears the budget.",
            "example": 600,
            "nullable": true
          },
          "budgetAmount": {
            "type": "number",
            "description": "Budget amount in the project currency. Null clears the budget.",
            "example": 120000,
            "nullable": true
          },
          "startDate": {
            "type": "string",
            "description": "Project start date (inclusive), ISO 8601. Null clears the date.",
            "example": "2025-01-01",
            "nullable": true
          },
          "endDate": {
            "type": "string",
            "description": "Project end date (inclusive), ISO 8601. Null clears the date.",
            "example": "2025-12-31",
            "nullable": true
          },
          "externalReference": {
            "type": "string",
            "description": "External reference. Null clears the value.",
            "example": "proj-external-123",
            "nullable": true,
            "maxLength": 255
          },
          "color": {
            "type": "string",
            "description": "Hex colour code. Null clears the value.",
            "example": "#FF5733",
            "nullable": true,
            "maxLength": 16
          },
          "isArchived": {
            "type": "boolean",
            "description": "Archive or un-archive the project.",
            "example": false
          }
        }
      },
      "CreateSubprojectRequest": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "description": "Display name for the subproject.",
            "example": "Phase 1",
            "minLength": 1,
            "maxLength": 120
          },
          "budgetHours": {
            "type": "number",
            "description": "Budget in hours for this subproject. Null clears the budget.",
            "example": 120,
            "nullable": true
          },
          "budgetAmount": {
            "type": "number",
            "description": "Budget amount in the project currency. Null clears the budget.",
            "example": 15000,
            "nullable": true
          },
          "color": {
            "type": "string",
            "description": "Hex colour code. Null clears the value.",
            "example": "#4A90E2",
            "nullable": true,
            "maxLength": 16
          },
          "sortOrder": {
            "type": "number",
            "description": "Sort order (ascending). Defaults to 0.",
            "example": 1
          }
        },
        "required": [
          "name"
        ]
      },
      "UpdateSubprojectRequest": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "description": "New display name for the subproject.",
            "example": "Phase 2",
            "minLength": 1,
            "maxLength": 120
          },
          "budgetHours": {
            "type": "number",
            "description": "Budget in hours. Null clears the budget.",
            "example": 200,
            "nullable": true
          },
          "budgetAmount": {
            "type": "number",
            "description": "Budget amount in the project currency. Null clears the budget.",
            "example": 25000,
            "nullable": true
          },
          "color": {
            "type": "string",
            "description": "Hex colour code. Null clears the value.",
            "example": "#4A90E2",
            "nullable": true,
            "maxLength": 16
          },
          "sortOrder": {
            "type": "number",
            "description": "Sort order (ascending).",
            "example": 2
          }
        }
      },
      "UsageReportRequestDto": {
        "type": "object",
        "properties": {
          "meterId": {
            "type": "string",
            "description": "Meter identifier. Provide meterId or meterName. Meter must be ACTIVE; usage will be rejected for archived meters.",
            "example": "550e8400-e29b-41d4-a716-446655440000"
          },
          "meterName": {
            "type": "string",
            "description": "Meter name. Provide meterId or meterName. Meter must be ACTIVE; usage will be rejected for archived meters.",
            "example": "api_calls"
          },
          "value": {
            "type": "number",
            "description": "Usage value to record",
            "example": 100
          },
          "timestamp": {
            "type": "string",
            "description": "ISO-8601 timestamp. Defaults to now.",
            "example": "2024-01-15T10:30:00Z"
          },
          "customerId": {
            "type": "string",
            "description": "Customer ID this usage is associated with.",
            "example": "550e8400-e29b-41d4-a716-446655440000"
          },
          "metadata": {
            "type": "object",
            "description": "Additional metadata for the usage event (values must be string, number, or boolean)",
            "example": {
              "region": "us-east-1",
              "feature": "api-calls"
            }
          }
        },
        "required": [
          "value",
          "customerId"
        ]
      }
    }
  }
}
