{
  "openapi": "3.1.1",
  "info": {
    "title": "Asstio Public API",
    "description": "Tenant business data in Asstio (orders, invoices, customers, products, stock, documents, activities and reports) over a stable, versioned REST API. Send `Authorization: Bearer <token>` on every call. Authentication, pagination, conventions and the MCP server are described in the guide: https://www.asstio.com/api, with the full reference as text at https://www.asstio.com/llms-api.txt. Inside v1, changes are additive only.",
    "version": "v1"
  },
  "servers": [
    {
      "url": "https://api.asstio.com"
    }
  ],
  "paths": {
    "/api/v1/warehouse-stock": {
      "get": {
        "tags": [
          "WarehouseStockApi"
        ],
        "description": "Read-only keys: allowed.",
        "parameters": [
          {
            "name": "productId",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "warehouseId",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "locationId",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "pageSize",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PageResponseOfWarehouseStockRowDto"
                }
              }
            }
          },
          "400": {
            "description": "The request could not be bound: malformed JSON, a missing body, or a parameter of the wrong type.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid Bearer token. Every token rejection has code \"unauthorized\" and this message.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Server error. The body is not specified."
          },
          "429": {
            "description": "API keys only: the key lookup budget is exhausted for a moment. Retry after the Retry-After delay.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying. A hint, not a promise.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/vendor-prices": {
      "get": {
        "tags": [
          "VendorPricesApi"
        ],
        "description": "Read-only keys: allowed.",
        "parameters": [
          {
            "name": "productId",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "supplierId",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "currencyCode",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "pageSize",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PageResponseOfVendorPriceDto"
                }
              }
            }
          },
          "400": {
            "description": "The request could not be bound: malformed JSON, a missing body, or a parameter of the wrong type.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid Bearer token. Every token rejection has code \"unauthorized\" and this message.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Server error. The body is not specified."
          },
          "429": {
            "description": "API keys only: the key lookup budget is exhausted for a moment. Retry after the Retry-After delay.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying. A hint, not a promise.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/time-report-lines": {
      "get": {
        "tags": [
          "TimeReportLinesApi"
        ],
        "description": "Read-only keys: allowed.",
        "parameters": [
          {
            "name": "orderId",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "customerId",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "personId",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "from",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "to",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "billableOnly",
            "in": "query",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "openOnly",
            "in": "query",
            "schema": {
              "type": "boolean"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/TimeReportLineDto"
                  }
                }
              }
            }
          },
          "400": {
            "description": "The request could not be bound: malformed JSON, a missing body, or a parameter of the wrong type.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid Bearer token. Every token rejection has code \"unauthorized\" and this message.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Server error. The body is not specified."
          },
          "429": {
            "description": "API keys only: the key lookup budget is exhausted for a moment. Retry after the Retry-After delay.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying. A hint, not a promise.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/tenant-settings/company-profile": {
      "get": {
        "tags": [
          "TenantSettingsApi"
        ],
        "description": "Read-only keys: allowed.",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CompanyProfileDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid Bearer token. Every token rejection has code \"unauthorized\" and this message.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Server error. The body is not specified."
          },
          "429": {
            "description": "API keys only: the key lookup budget is exhausted for a moment. Retry after the Retry-After delay.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying. A hint, not a promise.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      },
      "patch": {
        "tags": [
          "TenantSettingsApi"
        ],
        "summary": "Updates the company details sent in the body; fields left out are not touched, and an empty string clears a field. Needs the onboarding_company permission. The response lists the fields that changed, those that were already correct, and those that could not be saved.",
        "description": "Read-only keys: 403 with an ErrorEnvelope, code \"forbidden\".",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "oneOf": [
                  {
                    "type": "null"
                  },
                  {
                    "$ref": "#/components/schemas/CompanyProfileUpdateDto"
                  }
                ]
              }
            },
            "text/json": {
              "schema": {
                "oneOf": [
                  {
                    "type": "null"
                  },
                  {
                    "$ref": "#/components/schemas/CompanyProfileUpdateDto"
                  }
                ]
              }
            },
            "application/*+json": {
              "schema": {
                "oneOf": [
                  {
                    "type": "null"
                  },
                  {
                    "$ref": "#/components/schemas/CompanyProfileUpdateDto"
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CompanyProfileChangeResultDto"
                }
              }
            }
          },
          "400": {
            "description": "A field failed validation; nothing was stored. Body: { \"error\": \"…\" }. A request that cannot be bound (malformed JSON, a missing body, a parameter of the wrong type) gets ValidationProblemDetails as application/problem+json instead.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorMessageBody"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "The user lacks the onboarding_company permission. Body: { \"error\": \"…\" }.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorMessageBody"
                }
              }
            }
          },
          "500": {
            "description": "The write failed or was only partly applied. The lists are read back from the settings and say what was actually stored. Retrying is safe.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CompanyProfileWriteFailedDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid Bearer token. Every token rejection has code \"unauthorized\" and this message.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "429": {
            "description": "API keys only: the key lookup budget is exhausted for a moment. Retry after the Retry-After delay.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying. A hint, not a promise.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "415": {
            "description": "The Content-Type is not one the body can be read from; send application/json.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/tenant-settings/vat-configuration": {
      "get": {
        "tags": [
          "TenantSettingsApi"
        ],
        "description": "Read-only keys: allowed.",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VatConfigurationDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid Bearer token. Every token rejection has code \"unauthorized\" and this message.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Server error. The body is not specified."
          },
          "429": {
            "description": "API keys only: the key lookup budget is exhausted for a moment. Retry after the Retry-After delay.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying. A hint, not a promise.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/sales-orders/{id}/lines": {
      "get": {
        "tags": [
          "SalesOrderLinesApi"
        ],
        "description": "Read-only keys: allowed.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/SalesOrderLineDto"
                  }
                }
              }
            }
          },
          "404": {
            "description": "not_found: no sales order with this id in the tenant.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid Bearer token. Every token rejection has code \"unauthorized\" and this message.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Server error. The body is not specified."
          },
          "429": {
            "description": "API keys only: the key lookup budget is exhausted for a moment. Retry after the Retry-After delay.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying. A hint, not a promise.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "SalesOrderLinesApi"
        ],
        "description": "Read-only keys: 403 with an ErrorEnvelope, code \"forbidden\".",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SalesOrderLineAddDto"
              }
            },
            "text/json": {
              "schema": {
                "$ref": "#/components/schemas/SalesOrderLineAddDto"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/SalesOrderLineAddDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/IdResultDto"
                }
              }
            }
          },
          "400": {
            "description": "bad_request: the line was refused, for example on an invoiced or credited order; the message says why. A request that cannot be bound (malformed JSON, a missing body, a parameter of the wrong type) gets ValidationProblemDetails as application/problem+json instead.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "forbidden: the user lacks the price or quantity permission this change needs.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid Bearer token. Every token rejection has code \"unauthorized\" and this message.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Server error. The body is not specified."
          },
          "429": {
            "description": "API keys only: the key lookup budget is exhausted for a moment. Retry after the Retry-After delay.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying. A hint, not a promise.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "415": {
            "description": "The Content-Type is not one the body can be read from; send application/json.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/sales-orders/{id}/lines/{lineId}": {
      "patch": {
        "tags": [
          "SalesOrderLinesApi"
        ],
        "description": "Read-only keys: 403 with an ErrorEnvelope, code \"forbidden\".",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "lineId",
            "in": "path",
            "required": true,
            "schema": {
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SalesOrderLinePatchDto"
              }
            },
            "text/json": {
              "schema": {
                "$ref": "#/components/schemas/SalesOrderLinePatchDto"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/SalesOrderLinePatchDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "204": {
            "description": "No Content"
          },
          "400": {
            "description": "bad_request: the change was refused, for example on an invoiced or credited order; the message says why. A request that cannot be bound (malformed JSON, a missing body, a parameter of the wrong type) gets ValidationProblemDetails as application/problem+json instead.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "forbidden: the user lacks the price or quantity permission this change needs.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid Bearer token. Every token rejection has code \"unauthorized\" and this message.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Server error. The body is not specified."
          },
          "429": {
            "description": "API keys only: the key lookup budget is exhausted for a moment. Retry after the Retry-After delay.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying. A hint, not a promise.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "415": {
            "description": "The Content-Type is not one the body can be read from; send application/json.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "SalesOrderLinesApi"
        ],
        "description": "Read-only keys: 403 with an ErrorEnvelope, code \"forbidden\".",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "lineId",
            "in": "path",
            "required": true,
            "schema": {
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "No Content"
          },
          "400": {
            "description": "bad_request: the line cannot be deleted, for example on an invoiced or credited order; the message says why.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "forbidden: the user lacks the permission this change needs.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid Bearer token. Every token rejection has code \"unauthorized\" and this message.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Server error. The body is not specified."
          },
          "429": {
            "description": "API keys only: the key lookup budget is exhausted for a moment. Retry after the Retry-After delay.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying. A hint, not a promise.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/sales-orders": {
      "get": {
        "tags": [
          "SalesOrdersApi"
        ],
        "summary": "Sales order headers, newest order date first.",
        "description": "Read-only keys: allowed.",
        "parameters": [
          {
            "name": "customerId",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "customerName",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "currency",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "statusId",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "statusKind",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "orderDateFrom",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "orderDateTo",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "deliveryDateFrom",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "deliveryDateTo",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "invoiceDateFrom",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "invoiceDateTo",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "totalMin",
            "in": "query",
            "schema": {
              "type": "number",
              "format": "double"
            }
          },
          {
            "name": "totalMax",
            "in": "query",
            "schema": {
              "type": "number",
              "format": "double"
            }
          },
          {
            "name": "q",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "email",
            "in": "query",
            "description": "An e-mail address on the order itself (any active row, also the invoice address). Exact match after trimming and lower-casing; never a prefix. Must contain '@', at most 254 characters. Without statusKind, every status is searched.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "shopOrderNumber",
            "in": "query",
            "description": "The order number the buyer's webshop showed them, or the platform's own order id. Exact match, case ignored; only orders a known webshop or payment importer created. Without statusKind, every status is searched.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "include",
            "in": "query",
            "description": "Comma-separated sub-resources to embed in every order: lines, fulfilment. Each embedded value is exactly that sub-resource's response. With include, the page size is at most 25 (default 25). Contact details and payment are never embedded.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "pageSize",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PageResponseOfSalesOrderDto"
                }
              }
            }
          },
          "400": {
            "description": "invalid_request: a supplied identifier filter is blank or invalid, or include is blank or names an unknown value. A request that cannot be bound (malformed JSON, a missing body, a parameter of the wrong type) gets ValidationProblemDetails as application/problem+json instead.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid Bearer token. Every token rejection has code \"unauthorized\" and this message.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Server error. The body is not specified."
          },
          "429": {
            "description": "API keys only: the key lookup budget is exhausted for a moment. Retry after the Retry-After delay.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying. A hint, not a promise.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "SalesOrdersApi"
        ],
        "description": "Read-only keys: 403 with an ErrorEnvelope, code \"forbidden\".",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SalesOrderCreateDto"
              }
            },
            "text/json": {
              "schema": {
                "$ref": "#/components/schemas/SalesOrderCreateDto"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/SalesOrderCreateDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SalesOrderCreatedDto"
                }
              }
            }
          },
          "400": {
            "description": "invalid_request: an unknown company, currency or VAT type id. A request that cannot be bound (malformed JSON, a missing body, a parameter of the wrong type) gets ValidationProblemDetails as application/problem+json instead.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid Bearer token. Every token rejection has code \"unauthorized\" and this message.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Server error. The body is not specified."
          },
          "429": {
            "description": "API keys only: the key lookup budget is exhausted for a moment. Retry after the Retry-After delay.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying. A hint, not a promise.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "A read-only API key on a write operation (code \"forbidden\").",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "415": {
            "description": "The Content-Type is not one the body can be read from; send application/json.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/sales-orders/{id}": {
      "get": {
        "tags": [
          "SalesOrdersApi"
        ],
        "description": "Read-only keys: allowed.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SalesOrderDetailDto"
                }
              }
            }
          },
          "404": {
            "description": "not_found: no sales order with this id in the tenant.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid Bearer token. Every token rejection has code \"unauthorized\" and this message.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Server error. The body is not specified."
          },
          "429": {
            "description": "API keys only: the key lookup budget is exhausted for a moment. Retry after the Retry-After delay.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying. A hint, not a promise.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      },
      "patch": {
        "tags": [
          "SalesOrdersApi"
        ],
        "description": "Read-only keys: 403 with an ErrorEnvelope, code \"forbidden\".",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SalesOrderPatchDto"
              }
            },
            "text/json": {
              "schema": {
                "$ref": "#/components/schemas/SalesOrderPatchDto"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/SalesOrderPatchDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SalesOrderPatchResultDto"
                }
              }
            }
          },
          "400": {
            "description": "invalid_request: the change was refused; the message says why. A request that cannot be bound (malformed JSON, a missing body, a parameter of the wrong type) gets ValidationProblemDetails as application/problem+json instead.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid Bearer token. Every token rejection has code \"unauthorized\" and this message.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Server error. The body is not specified."
          },
          "429": {
            "description": "API keys only: the key lookup budget is exhausted for a moment. Retry after the Retry-After delay.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying. A hint, not a promise.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "A read-only API key on a write operation (code \"forbidden\").",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "415": {
            "description": "The Content-Type is not one the body can be read from; send application/json.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/sales-orders/{id}/contact": {
      "get": {
        "tags": [
          "SalesOrdersApi"
        ],
        "summary": "The order's own active e-mail addresses, phone numbers and postal addresses, as stored. Never the customer's.",
        "description": "Read-only keys: allowed.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SalesOrderContactDto"
                }
              }
            }
          },
          "400": {
            "description": "invalid_request: id is not a whole number (digits only, at most 2147483647).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "404": {
            "description": "not_found: no sales order with this id in the tenant (an invoice or purchase-order id is not one).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid Bearer token. Every token rejection has code \"unauthorized\" and this message.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Server error. The body is not specified."
          },
          "429": {
            "description": "API keys only: the key lookup budget is exhausted for a moment. Retry after the Retry-After delay.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying. A hint, not a promise.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/sales-orders/{id}/fulfilment": {
      "get": {
        "tags": [
          "SalesOrdersApi"
        ],
        "summary": "The order at the warehouse and with the carrier, as last observed: one entry per warehouse order, and every outbound parcel.",
        "description": "Read-only keys: allowed.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SalesOrderFulfilmentDto"
                }
              }
            }
          },
          "400": {
            "description": "invalid_request: id is not a whole number (digits only, at most 2147483647).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "404": {
            "description": "not_found: no sales order with this id in the tenant (an invoice or purchase-order id is not one).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid Bearer token. Every token rejection has code \"unauthorized\" and this message.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Server error. The body is not specified."
          },
          "429": {
            "description": "API keys only: the key lookup budget is exhausted for a moment. Retry after the Retry-After delay.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying. A hint, not a promise.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/sales-orders/{id}/payment": {
      "get": {
        "tags": [
          "SalesOrdersApi"
        ],
        "summary": "The order's payments as the payment providers report them, cached for up to 60 seconds. Needs the payment_manage permission, for an API key too.",
        "description": "Read-only keys: allowed.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SalesOrderPaymentsDto"
                }
              }
            }
          },
          "400": {
            "description": "invalid_request: id is not a whole number (digits only, at most 2147483647).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "forbidden: the caller lacks the payment_manage permission.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "404": {
            "description": "not_found: no sales order with this id in the tenant (an invoice or purchase-order id is not one).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "503": {
            "description": "unavailable: the order or its payment links could not be read within the request's 20-second limit. Retry later.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid Bearer token. Every token rejection has code \"unauthorized\" and this message.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Server error. The body is not specified."
          },
          "429": {
            "description": "API keys only: the key lookup budget is exhausted for a moment. Retry after the Retry-After delay.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying. A hint, not a promise.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/sales-invoices": {
      "get": {
        "tags": [
          "SalesInvoicesApi"
        ],
        "description": "Read-only keys: allowed.",
        "parameters": [
          {
            "name": "customerId",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "customerName",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "currency",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "statusId",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "statusKind",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "documentType",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "invoiceDateFrom",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "invoiceDateTo",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "dueDateFrom",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "dueDateTo",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "totalMin",
            "in": "query",
            "schema": {
              "type": "number",
              "format": "double"
            }
          },
          {
            "name": "totalMax",
            "in": "query",
            "schema": {
              "type": "number",
              "format": "double"
            }
          },
          {
            "name": "q",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "pageSize",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PageResponseOfSalesInvoiceDto"
                }
              }
            }
          },
          "400": {
            "description": "The request could not be bound: malformed JSON, a missing body, or a parameter of the wrong type.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid Bearer token. Every token rejection has code \"unauthorized\" and this message.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Server error. The body is not specified."
          },
          "429": {
            "description": "API keys only: the key lookup budget is exhausted for a moment. Retry after the Retry-After delay.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying. A hint, not a promise.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/sales-invoice-lines": {
      "post": {
        "tags": [
          "SalesInvoiceLinesApi"
        ],
        "description": "Read-only keys: allowed.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SearchRequest"
              }
            },
            "text/json": {
              "schema": {
                "$ref": "#/components/schemas/SearchRequest"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/SearchRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PageResponseOfSalesInvoiceLineDto"
                }
              }
            }
          },
          "400": {
            "description": "The request could not be bound: malformed JSON, a missing body, or a parameter of the wrong type.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid Bearer token. Every token rejection has code \"unauthorized\" and this message.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Server error. The body is not specified."
          },
          "429": {
            "description": "API keys only: the key lookup budget is exhausted for a moment. Retry after the Retry-After delay.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying. A hint, not a promise.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "415": {
            "description": "The Content-Type is not one the body can be read from; send application/json.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/reports": {
      "get": {
        "tags": [
          "ReportsApi"
        ],
        "summary": "Lists the reports in a catalog. Default `surface=mcp`: the MCP catalog, open to any authenticated user. `surface=report` lists the report-builder catalog and needs the nav_reports permission (403 otherwise).",
        "description": "Read-only keys: allowed.",
        "parameters": [
          {
            "name": "surface",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/ReportSummaryDto"
                  }
                }
              }
            }
          },
          "403": {
            "description": "surface=report without the nav_reports permission. The body is the plain-text message \"Missing nav_reports permission.\"",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              },
              "application/json": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid Bearer token. Every token rejection has code \"unauthorized\" and this message.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Server error. The body is not specified."
          },
          "429": {
            "description": "API keys only: the key lookup budget is exhausted for a moment. Retry after the Retry-After delay.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying. A hint, not a promise.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/reports/{name}": {
      "get": {
        "tags": [
          "ReportsApi"
        ],
        "summary": "Describes one report's columns. Default `surface=mcp`; `surface=report` needs the nav_reports permission (403 otherwise).",
        "description": "Read-only keys: allowed.",
        "parameters": [
          {
            "name": "name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "surface",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ReportDescribeDto"
                }
              }
            }
          },
          "403": {
            "description": "surface=report without the nav_reports permission. The body is the plain-text message \"Missing nav_reports permission.\"",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              },
              "application/json": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "No report with this name in the catalog.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid Bearer token. Every token rejection has code \"unauthorized\" and this message.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Server error. The body is not specified."
          },
          "429": {
            "description": "API keys only: the key lookup budget is exhausted for a moment. Retry after the Retry-After delay.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying. A hint, not a promise.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/reports/{name}/query": {
      "post": {
        "tags": [
          "ReportsApi"
        ],
        "summary": "Returns one page of rows. Default `surface=mcp`; `surface=report` needs the nav_reports permission (403 otherwise).",
        "description": "Read-only keys: allowed.",
        "parameters": [
          {
            "name": "name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "surface",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ReportQueryRequestDto"
              }
            },
            "text/json": {
              "schema": {
                "$ref": "#/components/schemas/ReportQueryRequestDto"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/ReportQueryRequestDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ReportQueryResultDto"
                }
              }
            }
          },
          "400": {
            "description": "The query was rejected (for example an unknown column or a bad filter); the body is the plain-text reason. A request that cannot be bound (malformed JSON, a missing body, a parameter of the wrong type) gets ValidationProblemDetails as application/problem+json instead.",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              },
              "application/json": {
                "schema": {
                  "type": "string"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "surface=report without the nav_reports permission. The body is the plain-text message \"Missing nav_reports permission.\"",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              },
              "application/json": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "No report with this name in the catalog.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "500": {
            "description": "The query failed in the database; the body is the plain-text reason.",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              },
              "application/json": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid Bearer token. Every token rejection has code \"unauthorized\" and this message.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "429": {
            "description": "API keys only: the key lookup budget is exhausted for a moment. Retry after the Retry-After delay.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying. A hint, not a promise.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "415": {
            "description": "The Content-Type is not one the body can be read from; send application/json.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/reports/{name}/count": {
      "post": {
        "tags": [
          "ReportsApi"
        ],
        "summary": "Counts the rows the same filter body matches. Default `surface=mcp`; `surface=report` needs the nav_reports permission (403 otherwise).",
        "description": "Read-only keys: allowed.",
        "parameters": [
          {
            "name": "name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "surface",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ReportQueryRequestDto"
              }
            },
            "text/json": {
              "schema": {
                "$ref": "#/components/schemas/ReportQueryRequestDto"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/ReportQueryRequestDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ReportCountResultDto"
                }
              }
            }
          },
          "400": {
            "description": "The query was rejected (for example an unknown column or a bad filter); the body is the plain-text reason. A request that cannot be bound (malformed JSON, a missing body, a parameter of the wrong type) gets ValidationProblemDetails as application/problem+json instead.",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              },
              "application/json": {
                "schema": {
                  "type": "string"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "surface=report without the nav_reports permission. The body is the plain-text message \"Missing nav_reports permission.\"",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              },
              "application/json": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "No report with this name in the catalog.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "500": {
            "description": "The query failed in the database; the body is the plain-text reason.",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              },
              "application/json": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid Bearer token. Every token rejection has code \"unauthorized\" and this message.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "429": {
            "description": "API keys only: the key lookup budget is exhausted for a moment. Retry after the Retry-After delay.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying. A hint, not a promise.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "415": {
            "description": "The Content-Type is not one the body can be read from; send application/json.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/reports/{name}/aggregate": {
      "post": {
        "tags": [
          "ReportsApi"
        ],
        "summary": "Groups and aggregates rows; an empty groupBy gives the grand total. Default `surface=mcp`; `surface=report` needs the nav_reports permission (403 otherwise).",
        "description": "Read-only keys: allowed.",
        "parameters": [
          {
            "name": "name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "surface",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ReportAggregateRequestDto"
              }
            },
            "text/json": {
              "schema": {
                "$ref": "#/components/schemas/ReportAggregateRequestDto"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/ReportAggregateRequestDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ReportQueryResultDto"
                }
              }
            }
          },
          "400": {
            "description": "The query was rejected (for example an unknown column or a bad filter); the body is the plain-text reason. A request that cannot be bound (malformed JSON, a missing body, a parameter of the wrong type) gets ValidationProblemDetails as application/problem+json instead.",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              },
              "application/json": {
                "schema": {
                  "type": "string"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "surface=report without the nav_reports permission. The body is the plain-text message \"Missing nav_reports permission.\"",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              },
              "application/json": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "No report with this name in the catalog.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "500": {
            "description": "The query failed in the database; the body is the plain-text reason.",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              },
              "application/json": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid Bearer token. Every token rejection has code \"unauthorized\" and this message.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "429": {
            "description": "API keys only: the key lookup budget is exhausted for a moment. Retry after the Retry-After delay.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying. A hint, not a promise.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "415": {
            "description": "The Content-Type is not one the body can be read from; send application/json.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/reports/{name}/export": {
      "post": {
        "tags": [
          "ReportsApi"
        ],
        "summary": "Downloads every matching row, up to 100,000, as XLSX (default) or CSV (`format=csv`). Default `surface=report`, which needs the nav_reports permission (403 otherwise); pass `surface=mcp` to export from the same catalog you listed.",
        "description": "Read-only keys: allowed.",
        "parameters": [
          {
            "name": "name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "surface",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "format",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ReportQueryRequestDto"
              }
            },
            "text/json": {
              "schema": {
                "$ref": "#/components/schemas/ReportQueryRequestDto"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/ReportQueryRequestDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "headers": {
              "Content-Disposition": {
                "description": "attachment; filename=\"<report>_<yyyy-MM-dd>.xlsx\" (or .csv).",
                "schema": {
                  "type": "string"
                }
              },
              "X-Report-Row-Count": {
                "description": "The number of rows in the file.",
                "schema": {
                  "type": "string"
                }
              },
              "X-Report-Truncated": {
                "description": "\"true\" when the file stopped at the export row cap; absent otherwise.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "text/csv": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "400": {
            "description": "An unknown format, or the query was rejected; the body is the plain-text reason. A request that cannot be bound (malformed JSON, a missing body, a parameter of the wrong type) gets ValidationProblemDetails as application/problem+json instead.",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              },
              "application/json": {
                "schema": {
                  "type": "string"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "surface=report without the nav_reports permission. The body is the plain-text message \"Missing nav_reports permission.\"",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              },
              "application/json": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "No report with this name in the catalog.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "500": {
            "description": "The export failed in the database; the body is the plain-text reason.",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              },
              "application/json": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid Bearer token. Every token rejection has code \"unauthorized\" and this message.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "429": {
            "description": "API keys only: the key lookup budget is exhausted for a moment. Retry after the Retry-After delay.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying. A hint, not a promise.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "415": {
            "description": "The Content-Type is not one the body can be read from; send application/json.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/reports/{name}/aggregate/export": {
      "post": {
        "tags": [
          "ReportsApi"
        ],
        "summary": "Downloads every group the aggregate matches as XLSX (default) or CSV (`format=csv`). Default `surface=report`, which needs the nav_reports permission (403 otherwise); pass `surface=mcp` to export from the same catalog you listed.",
        "description": "Read-only keys: allowed.",
        "parameters": [
          {
            "name": "name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "surface",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "format",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ReportAggregateRequestDto"
              }
            },
            "text/json": {
              "schema": {
                "$ref": "#/components/schemas/ReportAggregateRequestDto"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/ReportAggregateRequestDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "headers": {
              "Content-Disposition": {
                "description": "attachment; filename=\"<report>_<yyyy-MM-dd>.xlsx\" (or .csv).",
                "schema": {
                  "type": "string"
                }
              },
              "X-Report-Row-Count": {
                "description": "The number of rows in the file.",
                "schema": {
                  "type": "string"
                }
              },
              "X-Report-Truncated": {
                "description": "\"true\" when the file stopped at the export row cap; absent otherwise.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "text/csv": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "400": {
            "description": "An unknown format, or the query was rejected; the body is the plain-text reason. A request that cannot be bound (malformed JSON, a missing body, a parameter of the wrong type) gets ValidationProblemDetails as application/problem+json instead.",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              },
              "application/json": {
                "schema": {
                  "type": "string"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "surface=report without the nav_reports permission. The body is the plain-text message \"Missing nav_reports permission.\"",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              },
              "application/json": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "No report with this name in the catalog.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "500": {
            "description": "The export failed in the database; the body is the plain-text reason.",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              },
              "application/json": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid Bearer token. Every token rejection has code \"unauthorized\" and this message.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "429": {
            "description": "API keys only: the key lookup budget is exhausted for a moment. Retry after the Retry-After delay.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying. A hint, not a promise.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "415": {
            "description": "The Content-Type is not one the body can be read from; send application/json.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/purchase-proposals/batches": {
      "post": {
        "tags": [
          "PurchaseProposalsApi"
        ],
        "summary": "Stores a batch of proposed purchase lines for buyer review (201), or returns the existing one when the\n    same externalBatchId arrives again with the same content (200). Needs purchase_proposal_ingest.",
        "description": "Read-only keys: 403 with an ErrorEnvelope, code \"forbidden\".",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ProposalBatchIngestRequestDto"
              }
            },
            "text/json": {
              "schema": {
                "$ref": "#/components/schemas/ProposalBatchIngestRequestDto"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/ProposalBatchIngestRequestDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "A new batch; its lines are stored and classified.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProposalBatchIngestResultDto"
                }
              }
            }
          },
          "200": {
            "description": "The same externalBatchId with the same content: the existing batch, unchanged.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProposalBatchIngestResultDto"
                }
              }
            }
          },
          "400": {
            "description": "invalid_request: the body breaks a rule (source, externalBatchId, mode, 1–5,000 lines with unique lineNo, quantity, a 3-letter currency, an ISO date, field lengths). A request that cannot be bound (malformed JSON, a missing body, a parameter of the wrong type) gets ValidationProblemDetails as application/problem+json instead.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "forbidden: the caller lacks purchase_proposal_ingest.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "409": {
            "description": "batch_conflict: a batch with this externalBatchId and other content exists; version_conflict: buyers kept changing lines this batch shares a product and vendor with — retry the identical request. Nothing was written.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "413": {
            "description": "payload_too_large: the body is larger than 5 MB.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid Bearer token. Every token rejection has code \"unauthorized\" and this message.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Server error. The body is not specified."
          },
          "429": {
            "description": "API keys only: the key lookup budget is exhausted for a moment. Retry after the Retry-After delay.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying. A hint, not a promise.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "415": {
            "description": "The Content-Type is not one the body can be read from; send application/json.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      },
      "get": {
        "tags": [
          "PurchaseProposalsApi"
        ],
        "summary": "Proposal batches, newest first (received time, then id). Status and counts are derived from the lines.",
        "description": "Read-only keys: allowed.",
        "parameters": [
          {
            "name": "source",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "receivedFrom",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "receivedTo",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "externalBatchId",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "companyId",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "pageSize",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PageResponseOfProposalBatchDto"
                }
              }
            }
          },
          "400": {
            "description": "invalid_request: status is not open or done, a supplied source or externalBatchId is blank or invalid, or companyId is not positive. A request that cannot be bound (malformed JSON, a missing body, a parameter of the wrong type) gets ValidationProblemDetails as application/problem+json instead.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "forbidden: the caller lacks the purchase_proposal_view permission.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid Bearer token. Every token rejection has code \"unauthorized\" and this message.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Server error. The body is not specified."
          },
          "429": {
            "description": "API keys only: the key lookup budget is exhausted for a moment. Retry after the Retry-After delay.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying. A hint, not a promise.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/purchase-proposals/batches/{id}": {
      "get": {
        "tags": [
          "PurchaseProposalsApi"
        ],
        "description": "Read-only keys: allowed.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProposalBatchDto"
                }
              }
            }
          },
          "400": {
            "description": "invalid_request: id is not a positive whole number (digits only).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "forbidden: the caller lacks the purchase_proposal_view permission.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "404": {
            "description": "not_found: no proposal batch with this id in the tenant.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid Bearer token. Every token rejection has code \"unauthorized\" and this message.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Server error. The body is not specified."
          },
          "429": {
            "description": "API keys only: the key lookup budget is exhausted for a moment. Retry after the Retry-After delay.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying. A hint, not a promise.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/purchase-proposals/lines": {
      "get": {
        "tags": [
          "PurchaseProposalsApi"
        ],
        "summary": "Proposal lines, by batch (newest first), then line number.",
        "description": "Read-only keys: allowed.",
        "parameters": [
          {
            "name": "batchId",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int64"
            }
          },
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "band",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "companyId",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "pageSize",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PageResponseOfProposalLineDto"
                }
              }
            }
          },
          "400": {
            "description": "invalid_request: an unknown status or band, or a batchId or companyId that is not positive. A request that cannot be bound (malformed JSON, a missing body, a parameter of the wrong type) gets ValidationProblemDetails as application/problem+json instead.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "forbidden: the caller lacks the purchase_proposal_view permission.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid Bearer token. Every token rejection has code \"unauthorized\" and this message.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Server error. The body is not specified."
          },
          "429": {
            "description": "API keys only: the key lookup budget is exhausted for a moment. Retry after the Retry-After delay.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying. A hint, not a promise.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/purchase-proposals/lines/{id}": {
      "get": {
        "tags": [
          "PurchaseProposalsApi"
        ],
        "summary": "One line with its decision history.",
        "description": "Read-only keys: allowed.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProposalLineDetailDto"
                }
              }
            }
          },
          "400": {
            "description": "invalid_request: id is not a positive whole number (digits only).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "forbidden: the caller lacks the purchase_proposal_view permission.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "404": {
            "description": "not_found: no proposal line with this id in the tenant.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid Bearer token. Every token rejection has code \"unauthorized\" and this message.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Server error. The body is not specified."
          },
          "429": {
            "description": "API keys only: the key lookup budget is exhausted for a moment. Retry after the Retry-After delay.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying. A hint, not a promise.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/purchase-proposals/source-aliases": {
      "put": {
        "tags": [
          "PurchaseProposalsApi"
        ],
        "summary": "Maps the source's vendor codes to suppliers (and order groups). Validated as a whole: one bad row refuses\n    the request. Every saved code re-checks the open lines that carry it. Needs purchase_proposal_ingest.",
        "description": "Read-only keys: 403 with an ErrorEnvelope, code \"forbidden\".",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "oneOf": [
                  {
                    "type": "null"
                  },
                  {
                    "type": "array",
                    "items": {
                      "$ref": "#/components/schemas/ProposalSourceAliasDto"
                    }
                  }
                ]
              }
            },
            "text/json": {
              "schema": {
                "oneOf": [
                  {
                    "type": "null"
                  },
                  {
                    "type": "array",
                    "items": {
                      "$ref": "#/components/schemas/ProposalSourceAliasDto"
                    }
                  }
                ]
              }
            },
            "application/*+json": {
              "schema": {
                "oneOf": [
                  {
                    "type": "null"
                  },
                  {
                    "type": "array",
                    "items": {
                      "$ref": "#/components/schemas/ProposalSourceAliasDto"
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProposalSourceAliasResultDto"
                }
              }
            }
          },
          "400": {
            "description": "invalid_request: rowErrors names each refused row (index and reason); nothing was written. A request that cannot be bound (malformed JSON, a missing body, a parameter of the wrong type) gets ValidationProblemDetails as application/problem+json instead.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelopeWithRows"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "forbidden: the caller lacks purchase_proposal_ingest.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "409": {
            "description": "version_conflict: buyers kept changing the lines with these codes; nothing was written — retry the request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "413": {
            "description": "payload_too_large: the body is larger than 5 MB.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid Bearer token. Every token rejection has code \"unauthorized\" and this message.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Server error. The body is not specified."
          },
          "429": {
            "description": "API keys only: the key lookup budget is exhausted for a moment. Retry after the Retry-After delay.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying. A hint, not a promise.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "415": {
            "description": "The Content-Type is not one the body can be read from; send application/json.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/purchase-orders": {
      "get": {
        "tags": [
          "PurchaseOrdersApi"
        ],
        "description": "Read-only keys: allowed.",
        "parameters": [
          {
            "name": "vendorId",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "vendorName",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "currency",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "statusId",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "statusKind",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "orderDateFrom",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "orderDateTo",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "deliveryDateFrom",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "deliveryDateTo",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "totalExVatMin",
            "in": "query",
            "schema": {
              "type": "number",
              "format": "double"
            }
          },
          {
            "name": "totalExVatMax",
            "in": "query",
            "schema": {
              "type": "number",
              "format": "double"
            }
          },
          {
            "name": "openToInvoiceMin",
            "in": "query",
            "schema": {
              "type": "number",
              "format": "double"
            }
          },
          {
            "name": "openToInvoiceMax",
            "in": "query",
            "schema": {
              "type": "number",
              "format": "double"
            }
          },
          {
            "name": "q",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "pageSize",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PageResponseOfPurchaseOrderDto"
                }
              }
            }
          },
          "400": {
            "description": "The request could not be bound: malformed JSON, a missing body, or a parameter of the wrong type.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid Bearer token. Every token rejection has code \"unauthorized\" and this message.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Server error. The body is not specified."
          },
          "429": {
            "description": "API keys only: the key lookup budget is exhausted for a moment. Retry after the Retry-After delay.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying. A hint, not a promise.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/purchase-invoice-matches/{invoiceId}": {
      "get": {
        "tags": [
          "PurchaseInvoiceMatchesApi"
        ],
        "description": "Read-only keys: allowed.",
        "parameters": [
          {
            "name": "invoiceId",
            "in": "path",
            "required": true,
            "schema": {
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PurchaseInvoiceMatchResponseDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid Bearer token. Every token rejection has code \"unauthorized\" and this message.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Server error. The body is not specified."
          },
          "429": {
            "description": "API keys only: the key lookup budget is exhausted for a moment. Retry after the Retry-After delay.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying. A hint, not a promise.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/purchase-invoice-matches/{invoiceId}/confirm": {
      "post": {
        "tags": [
          "PurchaseInvoiceMatchesApi"
        ],
        "description": "Read-only keys: 403 with an ErrorEnvelope, code \"forbidden\".",
        "parameters": [
          {
            "name": "invoiceId",
            "in": "path",
            "required": true,
            "schema": {
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PurchaseInvoiceConfirmMatchesRequestDto"
              }
            },
            "text/json": {
              "schema": {
                "$ref": "#/components/schemas/PurchaseInvoiceConfirmMatchesRequestDto"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/PurchaseInvoiceConfirmMatchesRequestDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PurchaseInvoiceConfirmMatchesResponseDto"
                }
              }
            }
          },
          "400": {
            "description": "The request could not be bound: malformed JSON, a missing body, or a parameter of the wrong type.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid Bearer token. Every token rejection has code \"unauthorized\" and this message.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Server error. The body is not specified."
          },
          "429": {
            "description": "API keys only: the key lookup budget is exhausted for a moment. Retry after the Retry-After delay.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying. A hint, not a promise.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "A read-only API key on a write operation (code \"forbidden\").",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "415": {
            "description": "The Content-Type is not one the body can be read from; send application/json.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/purchase-invoice-matches/{invoiceId}/match-whole-order": {
      "post": {
        "tags": [
          "PurchaseInvoiceMatchesApi"
        ],
        "description": "Read-only keys: 403 with an ErrorEnvelope, code \"forbidden\".",
        "parameters": [
          {
            "name": "invoiceId",
            "in": "path",
            "required": true,
            "schema": {
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PurchaseInvoiceMatchWholeOrderRequestDto"
              }
            },
            "text/json": {
              "schema": {
                "$ref": "#/components/schemas/PurchaseInvoiceMatchWholeOrderRequestDto"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/PurchaseInvoiceMatchWholeOrderRequestDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PurchaseInvoiceConfirmMatchesResponseDto"
                }
              }
            }
          },
          "400": {
            "description": "The request could not be bound: malformed JSON, a missing body, or a parameter of the wrong type.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid Bearer token. Every token rejection has code \"unauthorized\" and this message.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Server error. The body is not specified."
          },
          "429": {
            "description": "API keys only: the key lookup budget is exhausted for a moment. Retry after the Retry-After delay.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying. A hint, not a promise.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "A read-only API key on a write operation (code \"forbidden\").",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "415": {
            "description": "The Content-Type is not one the body can be read from; send application/json.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/product-codes": {
      "get": {
        "tags": [
          "ProductCodesApi"
        ],
        "summary": "Codes of up to 200 products. Ordered (productId, isMain desc, timeAdded, id). Ids that name no product\n    return no rows. A non-blank cursor that does not decode is 400.",
        "description": "Read-only keys: allowed.",
        "parameters": [
          {
            "name": "productIds",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "type",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "scope",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "pageSize",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PageResponseOfProductCodeDto"
                }
              }
            }
          },
          "400": {
            "description": "invalid_request: productIds missing, blank or not 1–200 positive whole numbers; type not gtin or local; scope not main or all; status not active or all; a cursor that does not decode.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid Bearer token. Every token rejection has code \"unauthorized\" and this message.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Server error. The body is not specified."
          },
          "429": {
            "description": "API keys only: the key lookup budget is exhausted for a moment. Retry after the Retry-After delay.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying. A hint, not a promise.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/product-codes/find": {
      "get": {
        "tags": [
          "ProductCodesApi"
        ],
        "summary": "Products by code. type=any searches the GTIN namespace (when the input parses as a GTIN, or as each\n    candidate of an ambiguous one) and the local namespace independently; each hit names its namespace. Ordered\n    (gtin before local, productId, id).",
        "description": "Read-only keys: allowed.",
        "parameters": [
          {
            "name": "code",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "type",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "pageSize",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PageResponseOfCodeMatchDto"
                }
              }
            }
          },
          "400": {
            "description": "invalid_request: code missing or blank; type not gtin, local or any; status not active or all; a cursor that does not decode; or a code that does not parse — details.reason and details.parse. For type=any the reason is the local parse's, when both the GTIN and the local parse fail.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid Bearer token. Every token rejection has code \"unauthorized\" and this message.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Server error. The body is not specified."
          },
          "429": {
            "description": "API keys only: the key lookup budget is exhausted for a moment. Retry after the Retry-After delay.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying. A hint, not a promise.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/product-codes/validate": {
      "post": {
        "tags": [
          "ProductCodesApi"
        ],
        "summary": "Parses a code without saving it. Always 200: the outcome says valid, repaired, ambiguous or invalid.",
        "description": "Read-only keys: allowed.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ProductCodeValidateDto"
              }
            },
            "text/json": {
              "schema": {
                "$ref": "#/components/schemas/ProductCodeValidateDto"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/ProductCodeValidateDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ParseResultDto"
                }
              }
            }
          },
          "400": {
            "description": "invalid_request: the body cannot be read as JSON.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid Bearer token. Every token rejection has code \"unauthorized\" and this message.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Server error. The body is not specified."
          },
          "429": {
            "description": "API keys only: the key lookup budget is exhausted for a moment. Retry after the Retry-After delay.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying. A hint, not a promise.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "415": {
            "description": "The Content-Type is not one the body can be read from; send application/json.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/products/{productId}/codes": {
      "post": {
        "tags": [
          "ProductCodesApi"
        ],
        "description": "Read-only keys: 403 with an ErrorEnvelope, code \"forbidden\".",
        "parameters": [
          {
            "name": "productId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ProductCodeAddDto"
              }
            },
            "text/json": {
              "schema": {
                "$ref": "#/components/schemas/ProductCodeAddDto"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/ProductCodeAddDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProductCodeWriteResponseDto"
                }
              }
            }
          },
          "200": {
            "description": "The same code (type and key) is already on the product: the existing row (options ignored), or a retired row reactivated.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProductCodeWriteResponseDto"
                }
              }
            }
          },
          "400": {
            "description": "invalid_request: details.reason names why (an open set): a parse reason such as check_digit, too_short or ambiguous (details.parse holds the parse), duplicate_code (details.candidates ≤ 20, details.total), main_product, note_required, note_too_long, invalid_quantity, invalid_relation, invalid_status, invalid_on_duplicate, move_not_allowed, move_from_required, is_main_false, retired_cannot_be_main, already_on_product, unsupported_type, invalid_choice or concurrent_change.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "forbidden: the caller lacks the import_products permission.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "404": {
            "description": "not_found: no product with this id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid Bearer token. Every token rejection has code \"unauthorized\" and this message.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Server error. The body is not specified."
          },
          "429": {
            "description": "API keys only: the key lookup budget is exhausted for a moment. Retry after the Retry-After delay.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying. A hint, not a promise.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "415": {
            "description": "The Content-Type is not one the body can be read from; send application/json.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/products/{productId}/codes/{codeId}/replace": {
      "post": {
        "tags": [
          "ProductCodesApi"
        ],
        "description": "Read-only keys: 403 with an ErrorEnvelope, code \"forbidden\".",
        "parameters": [
          {
            "name": "productId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "codeId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ProductCodeReplaceDto"
              }
            },
            "text/json": {
              "schema": {
                "$ref": "#/components/schemas/ProductCodeReplaceDto"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/ProductCodeReplaceDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProductCodeWriteResponseDto"
                }
              }
            }
          },
          "400": {
            "description": "invalid_request: details.reason names why (an open set): a parse reason such as check_digit, too_short or ambiguous (details.parse holds the parse), duplicate_code (details.candidates ≤ 20, details.total), main_product, note_required, note_too_long, invalid_quantity, invalid_relation, invalid_status, invalid_on_duplicate, move_not_allowed, move_from_required, is_main_false, retired_cannot_be_main, already_on_product, unsupported_type, invalid_choice or concurrent_change.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "forbidden: the caller lacks the import_products permission.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "404": {
            "description": "not_found: no product with this id, or the code is not on it.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid Bearer token. Every token rejection has code \"unauthorized\" and this message.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Server error. The body is not specified."
          },
          "429": {
            "description": "API keys only: the key lookup budget is exhausted for a moment. Retry after the Retry-After delay.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying. A hint, not a promise.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "415": {
            "description": "The Content-Type is not one the body can be read from; send application/json.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/products/{productId}/codes/{codeId}": {
      "patch": {
        "tags": [
          "ProductCodesApi"
        ],
        "description": "Read-only keys: 403 with an ErrorEnvelope, code \"forbidden\".",
        "parameters": [
          {
            "name": "productId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "codeId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ProductCodePatchDto"
              }
            },
            "text/json": {
              "schema": {
                "$ref": "#/components/schemas/ProductCodePatchDto"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/ProductCodePatchDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProductCodeDto"
                }
              }
            }
          },
          "400": {
            "description": "invalid_request: details.reason names why (an open set): a parse reason such as check_digit, too_short or ambiguous (details.parse holds the parse), duplicate_code (details.candidates ≤ 20, details.total), main_product, note_required, note_too_long, invalid_quantity, invalid_relation, invalid_status, invalid_on_duplicate, move_not_allowed, move_from_required, is_main_false, retired_cannot_be_main, already_on_product, unsupported_type, invalid_choice or concurrent_change.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "forbidden: the caller lacks the import_products permission.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "404": {
            "description": "not_found: no product with this id, or the code is not on it.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid Bearer token. Every token rejection has code \"unauthorized\" and this message.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Server error. The body is not specified."
          },
          "429": {
            "description": "API keys only: the key lookup budget is exhausted for a moment. Retry after the Retry-After delay.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying. A hint, not a promise.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "415": {
            "description": "The Content-Type is not one the body can be read from; send application/json.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "ProductCodesApi"
        ],
        "description": "Read-only keys: 403 with an ErrorEnvelope, code \"forbidden\".",
        "parameters": [
          {
            "name": "productId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "codeId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "No Content"
          },
          "400": {
            "description": "invalid_request: an id that is not a whole number.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "forbidden: the caller lacks the import_products permission.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "404": {
            "description": "not_found: no product with this id, or the code is not on it.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid Bearer token. Every token rejection has code \"unauthorized\" and this message.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Server error. The body is not specified."
          },
          "429": {
            "description": "API keys only: the key lookup budget is exhausted for a moment. Retry after the Retry-After delay.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying. A hint, not a promise.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/products/find": {
      "get": {
        "tags": [
          "ProductFindApi"
        ],
        "description": "Read-only keys: allowed.",
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/ProductFindDto"
                  }
                }
              }
            }
          },
          "400": {
            "description": "The request could not be bound: malformed JSON, a missing body, or a parameter of the wrong type.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid Bearer token. Every token rejection has code \"unauthorized\" and this message.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Server error. The body is not specified."
          },
          "429": {
            "description": "API keys only: the key lookup budget is exhausted for a moment. Retry after the Retry-After delay.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying. A hint, not a promise.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/products/fields": {
      "get": {
        "tags": [
          "ProductBulkApi"
        ],
        "description": "Read-only keys: allowed.",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/ProductFieldDto"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid Bearer token. Every token rejection has code \"unauthorized\" and this message.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Server error. The body is not specified."
          },
          "429": {
            "description": "API keys only: the key lookup budget is exhausted for a moment. Retry after the Retry-After delay.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying. A hint, not a promise.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/products/texts": {
      "get": {
        "tags": [
          "ProductBulkApi"
        ],
        "description": "Read-only keys: allowed.",
        "parameters": [
          {
            "name": "fields",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "langs",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "q",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "categoryId",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "productNumbers",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "includeVariants",
            "in": "query",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "includeInactive",
            "in": "query",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "pageSize",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PageResponseOfProductTextsDto"
                }
              }
            }
          },
          "400": {
            "description": "invalid_request: an unknown field or language, or too many product numbers; the message says why. A request that cannot be bound (malformed JSON, a missing body, a parameter of the wrong type) gets ValidationProblemDetails as application/problem+json instead.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid Bearer token. Every token rejection has code \"unauthorized\" and this message.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Server error. The body is not specified."
          },
          "429": {
            "description": "API keys only: the key lookup budget is exhausted for a moment. Retry after the Retry-After delay.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying. A hint, not a promise.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/products/{productId}/texts/value": {
      "get": {
        "tags": [
          "ProductBulkApi"
        ],
        "description": "Read-only keys: allowed.",
        "parameters": [
          {
            "name": "productId",
            "in": "path",
            "required": true,
            "schema": {
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "field",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "lang",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "offset",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProductTextChunkDto"
                }
              }
            }
          },
          "400": {
            "description": "invalid_request: the field cannot be read here, or the language or offset is invalid; the message says why. A request that cannot be bound (malformed JSON, a missing body, a parameter of the wrong type) gets ValidationProblemDetails as application/problem+json instead.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationProblemDetails"
                }
              }
            }
          },
          "404": {
            "description": "not_found: no such product, or the field has no value on it.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid Bearer token. Every token rejection has code \"unauthorized\" and this message.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Server error. The body is not specified."
          },
          "429": {
            "description": "API keys only: the key lookup budget is exhausted for a moment. Retry after the Retry-After delay.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying. A hint, not a promise.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/products/values": {
      "get": {
        "tags": [
          "ProductBulkApi"
        ],
        "description": "Read-only keys: allowed.",
        "parameters": [
          {
            "name": "fields",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "langs",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "q",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "categoryId",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "productNumbers",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "includeVariants",
            "in": "query",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "includeInactive",
            "in": "query",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "pageSize",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PageResponseOfProductValuesDto"
                }
              }
            }
          },
          "400": {
            "description": "invalid_request: an unknown field or language, or too many product numbers; the message says why. A request that cannot be bound (malformed JSON, a missing body, a parameter of the wrong type) gets ValidationProblemDetails as application/problem+json instead.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid Bearer token. Every token rejection has code \"unauthorized\" and this message.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Server error. The body is not specified."
          },
          "429": {
            "description": "API keys only: the key lookup budget is exhausted for a moment. Retry after the Retry-After delay.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying. A hint, not a promise.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/products/categories": {
      "get": {
        "tags": [
          "ProductBulkApi"
        ],
        "description": "Read-only keys: allowed.",
        "parameters": [
          {
            "name": "rootId",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "q",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "activeOnly",
            "in": "query",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "pageSize",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PageResponseOfProductCategoryDto"
                }
              }
            }
          },
          "400": {
            "description": "invalid_request: rootId is not a top-level category; the message says why. A request that cannot be bound (malformed JSON, a missing body, a parameter of the wrong type) gets ValidationProblemDetails as application/problem+json instead.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid Bearer token. Every token rejection has code \"unauthorized\" and this message.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Server error. The body is not specified."
          },
          "429": {
            "description": "API keys only: the key lookup budget is exhausted for a moment. Retry after the Retry-After delay.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying. A hint, not a promise.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/products/search": {
      "get": {
        "tags": [
          "ProductBulkApi"
        ],
        "description": "Read-only keys: allowed.",
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "categoryId",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "active",
            "in": "query",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "variantRole",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "pageSize",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PageResponseOfProductSearchRowDto"
                }
              }
            }
          },
          "400": {
            "description": "invalid_request: an unknown variantRole or categoryId; the message says why. A request that cannot be bound (malformed JSON, a missing body, a parameter of the wrong type) gets ValidationProblemDetails as application/problem+json instead.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid Bearer token. Every token rejection has code \"unauthorized\" and this message.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Server error. The body is not specified."
          },
          "429": {
            "description": "API keys only: the key lookup budget is exhausted for a moment. Retry after the Retry-After delay.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying. A hint, not a promise.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/products/detail": {
      "get": {
        "tags": [
          "ProductBulkApi"
        ],
        "description": "Read-only keys: allowed.",
        "parameters": [
          {
            "name": "productId",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "productNumber",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "langs",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProductDetailDto"
                }
              }
            }
          },
          "400": {
            "description": "invalid_request: neither or both of productId and productNumber, an unknown language, or a product number shared by several products (AMBIGUOUS_PRODUCT_NUMBER); the message says why. A request that cannot be bound (malformed JSON, a missing body, a parameter of the wrong type) gets ValidationProblemDetails as application/problem+json instead.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationProblemDetails"
                }
              }
            }
          },
          "404": {
            "description": "not_found: no product with this id or product number.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid Bearer token. Every token rejection has code \"unauthorized\" and this message.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Server error. The body is not specified."
          },
          "429": {
            "description": "API keys only: the key lookup budget is exhausted for a moment. Retry after the Retry-After delay.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying. A hint, not a promise.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/products/{productId}/values/value": {
      "get": {
        "tags": [
          "ProductBulkApi"
        ],
        "description": "Read-only keys: allowed.",
        "parameters": [
          {
            "name": "productId",
            "in": "path",
            "required": true,
            "schema": {
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "field",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "lang",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "offset",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProductTextChunkDto"
                }
              }
            }
          },
          "400": {
            "description": "invalid_request: an unknown field, or the language or offset is invalid; the message says why. A request that cannot be bound (malformed JSON, a missing body, a parameter of the wrong type) gets ValidationProblemDetails as application/problem+json instead.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationProblemDetails"
                }
              }
            }
          },
          "404": {
            "description": "not_found: no such product, or the field has no value on it.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid Bearer token. Every token rejection has code \"unauthorized\" and this message.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Server error. The body is not specified."
          },
          "429": {
            "description": "API keys only: the key lookup budget is exhausted for a moment. Retry after the Retry-After delay.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying. A hint, not a promise.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/products/bulk-update/preview": {
      "post": {
        "tags": [
          "ProductBulkApi"
        ],
        "description": "Read-only keys: allowed.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ProductBulkUpdateRequestDto"
              }
            },
            "text/json": {
              "schema": {
                "$ref": "#/components/schemas/ProductBulkUpdateRequestDto"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/ProductBulkUpdateRequestDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProductBulkResultDto"
                }
              }
            }
          },
          "400": {
            "description": "invalid_request: the request as a whole is unusable; the message says why. Per-item problems are reported in the 200 body. A request that cannot be bound (malformed JSON, a missing body, a parameter of the wrong type) gets ValidationProblemDetails as application/problem+json instead.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "forbidden: the user lacks the import_products permission.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid Bearer token. Every token rejection has code \"unauthorized\" and this message.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Server error. The body is not specified."
          },
          "429": {
            "description": "API keys only: the key lookup budget is exhausted for a moment. Retry after the Retry-After delay.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying. A hint, not a promise.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "415": {
            "description": "The Content-Type is not one the body can be read from; send application/json.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/products/bulk-update": {
      "post": {
        "tags": [
          "ProductBulkApi"
        ],
        "description": "Read-only keys: 403 with an ErrorEnvelope, code \"forbidden\".",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ProductBulkUpdateRequestDto"
              }
            },
            "text/json": {
              "schema": {
                "$ref": "#/components/schemas/ProductBulkUpdateRequestDto"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/ProductBulkUpdateRequestDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProductBulkResultDto"
                }
              }
            }
          },
          "400": {
            "description": "invalid_request: the request as a whole is unusable; the message says why. Per-item problems are reported in the 200 body. A request that cannot be bound (malformed JSON, a missing body, a parameter of the wrong type) gets ValidationProblemDetails as application/problem+json instead.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "forbidden: the user lacks the import_products permission.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid Bearer token. Every token rejection has code \"unauthorized\" and this message.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Server error. The body is not specified."
          },
          "429": {
            "description": "API keys only: the key lookup budget is exhausted for a moment. Retry after the Retry-After delay.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying. A hint, not a promise.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "415": {
            "description": "The Content-Type is not one the body can be read from; send application/json.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/open-order-lines": {
      "get": {
        "tags": [
          "OpenOrderLinesApi"
        ],
        "description": "Read-only keys: allowed.",
        "parameters": [
          {
            "name": "customerId",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "productId",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "warehouseId",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "includeFullyDelivered",
            "in": "query",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "pageSize",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PageResponseOfOpenOrderLineDto"
                }
              }
            }
          },
          "400": {
            "description": "The request could not be bound: malformed JSON, a missing body, or a parameter of the wrong type.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid Bearer token. Every token rejection has code \"unauthorized\" and this message.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Server error. The body is not specified."
          },
          "429": {
            "description": "API keys only: the key lookup budget is exhausted for a moment. Retry after the Retry-After delay.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying. A hint, not a promise.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/kanban-boards": {
      "get": {
        "tags": [
          "KanbanBoardsApi"
        ],
        "description": "Read-only keys: allowed.",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/KanbanBoardDto"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid Bearer token. Every token rejection has code \"unauthorized\" and this message.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Server error. The body is not specified."
          },
          "429": {
            "description": "API keys only: the key lookup budget is exhausted for a moment. Retry after the Retry-After delay.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying. A hint, not a promise.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "KanbanBoardsApi"
        ],
        "description": "Read-only keys: 403 with an ErrorEnvelope, code \"forbidden\".",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/KanbanBoardSaveDto"
              }
            },
            "text/json": {
              "schema": {
                "$ref": "#/components/schemas/KanbanBoardSaveDto"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/KanbanBoardSaveDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/IdResultDto"
                }
              }
            }
          },
          "400": {
            "description": "bad_request: the board could not be saved; the message says why. A request that cannot be bound (malformed JSON, a missing body, a parameter of the wrong type) gets ValidationProblemDetails as application/problem+json instead.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid Bearer token. Every token rejection has code \"unauthorized\" and this message.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Server error. The body is not specified."
          },
          "429": {
            "description": "API keys only: the key lookup budget is exhausted for a moment. Retry after the Retry-After delay.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying. A hint, not a promise.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "A read-only API key on a write operation (code \"forbidden\").",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "415": {
            "description": "The Content-Type is not one the body can be read from; send application/json.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/kanban-boards/{id}": {
      "get": {
        "tags": [
          "KanbanBoardsApi"
        ],
        "description": "Read-only keys: allowed.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/KanbanBoardDto"
                }
              }
            }
          },
          "404": {
            "description": "No board with this id.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid Bearer token. Every token rejection has code \"unauthorized\" and this message.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Server error. The body is not specified."
          },
          "429": {
            "description": "API keys only: the key lookup budget is exhausted for a moment. Retry after the Retry-After delay.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying. A hint, not a promise.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      },
      "put": {
        "tags": [
          "KanbanBoardsApi"
        ],
        "description": "Read-only keys: 403 with an ErrorEnvelope, code \"forbidden\".",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/KanbanBoardSaveDto"
              }
            },
            "text/json": {
              "schema": {
                "$ref": "#/components/schemas/KanbanBoardSaveDto"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/KanbanBoardSaveDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/IdResultDto"
                }
              }
            }
          },
          "400": {
            "description": "bad_request: no board with this id, or the board could not be saved; the message says why. A request that cannot be bound (malformed JSON, a missing body, a parameter of the wrong type) gets ValidationProblemDetails as application/problem+json instead.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid Bearer token. Every token rejection has code \"unauthorized\" and this message.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Server error. The body is not specified."
          },
          "429": {
            "description": "API keys only: the key lookup budget is exhausted for a moment. Retry after the Retry-After delay.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying. A hint, not a promise.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "A read-only API key on a write operation (code \"forbidden\").",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "415": {
            "description": "The Content-Type is not one the body can be read from; send application/json.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "KanbanBoardsApi"
        ],
        "description": "Read-only keys: 403 with an ErrorEnvelope, code \"forbidden\".",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "No Content"
          },
          "404": {
            "description": "No board with this id.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid Bearer token. Every token rejection has code \"unauthorized\" and this message.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Server error. The body is not specified."
          },
          "429": {
            "description": "API keys only: the key lookup budget is exhausted for a moment. Retry after the Retry-After delay.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying. A hint, not a promise.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "A read-only API key on a write operation (code \"forbidden\").",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/kanban-cards": {
      "post": {
        "tags": [
          "KanbanCardsApi"
        ],
        "description": "Read-only keys: 403 with an ErrorEnvelope, code \"forbidden\".",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/KanbanCardAddDto"
              }
            },
            "text/json": {
              "schema": {
                "$ref": "#/components/schemas/KanbanCardAddDto"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/KanbanCardAddDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/IdResultDto"
                }
              }
            }
          },
          "400": {
            "description": "bad_request: an unknown board or column, or no column given on a board without a default column; the message says why. A request that cannot be bound (malformed JSON, a missing body, a parameter of the wrong type) gets ValidationProblemDetails as application/problem+json instead.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid Bearer token. Every token rejection has code \"unauthorized\" and this message.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Server error. The body is not specified."
          },
          "429": {
            "description": "API keys only: the key lookup budget is exhausted for a moment. Retry after the Retry-After delay.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying. A hint, not a promise.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "A read-only API key on a write operation (code \"forbidden\").",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "415": {
            "description": "The Content-Type is not one the body can be read from; send application/json.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/kanban-cards/move": {
      "post": {
        "tags": [
          "KanbanCardsApi"
        ],
        "description": "Read-only keys: 403 with an ErrorEnvelope, code \"forbidden\".",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/KanbanCardMoveDto"
              }
            },
            "text/json": {
              "schema": {
                "$ref": "#/components/schemas/KanbanCardMoveDto"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/KanbanCardMoveDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "204": {
            "description": "No Content"
          },
          "400": {
            "description": "bad_request: an unknown board or column; the message says why. A request that cannot be bound (malformed JSON, a missing body, a parameter of the wrong type) gets ValidationProblemDetails as application/problem+json instead.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid Bearer token. Every token rejection has code \"unauthorized\" and this message.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Server error. The body is not specified."
          },
          "429": {
            "description": "API keys only: the key lookup budget is exhausted for a moment. Retry after the Retry-After delay.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying. A hint, not a promise.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "A read-only API key on a write operation (code \"forbidden\").",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "415": {
            "description": "The Content-Type is not one the body can be read from; send application/json.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/kanban-cards/finish": {
      "post": {
        "tags": [
          "KanbanCardsApi"
        ],
        "description": "Read-only keys: 403 with an ErrorEnvelope, code \"forbidden\".",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/KanbanCardFinishDto"
              }
            },
            "text/json": {
              "schema": {
                "$ref": "#/components/schemas/KanbanCardFinishDto"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/KanbanCardFinishDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "204": {
            "description": "No Content"
          },
          "400": {
            "description": "bad_request: an unknown board, or a board without a finished column; the message says why. A request that cannot be bound (malformed JSON, a missing body, a parameter of the wrong type) gets ValidationProblemDetails as application/problem+json instead.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid Bearer token. Every token rejection has code \"unauthorized\" and this message.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Server error. The body is not specified."
          },
          "429": {
            "description": "API keys only: the key lookup budget is exhausted for a moment. Retry after the Retry-After delay.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying. A hint, not a promise.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "A read-only API key on a write operation (code \"forbidden\").",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "415": {
            "description": "The Content-Type is not one the body can be read from; send application/json.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/documents/search": {
      "get": {
        "tags": [
          "DocumentsApi"
        ],
        "description": "Read-only keys: allowed.",
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "maxResults",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/DocumentSearchHitDto"
                  }
                }
              }
            }
          },
          "400": {
            "description": "The request could not be bound: malformed JSON, a missing body, or a parameter of the wrong type.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid Bearer token. Every token rejection has code \"unauthorized\" and this message.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Server error. The body is not specified."
          },
          "429": {
            "description": "API keys only: the key lookup budget is exhausted for a moment. Retry after the Retry-After delay.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying. A hint, not a promise.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/documents/{documentId}": {
      "get": {
        "tags": [
          "DocumentsApi"
        ],
        "description": "Read-only keys: allowed.",
        "parameters": [
          {
            "name": "documentId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DocumentContentDto"
                }
              }
            }
          },
          "404": {
            "description": "not_found: no such document for this user.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid Bearer token. Every token rejection has code \"unauthorized\" and this message.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Server error. The body is not specified."
          },
          "429": {
            "description": "API keys only: the key lookup budget is exhausted for a moment. Retry after the Retry-After delay.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying. A hint, not a promise.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/customers": {
      "get": {
        "tags": [
          "CustomersApi"
        ],
        "description": "Read-only keys: allowed.",
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "inactive",
            "in": "query",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "pageSize",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PageResponseOfCustomerDto"
                }
              }
            }
          },
          "400": {
            "description": "The request could not be bound: malformed JSON, a missing body, or a parameter of the wrong type.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid Bearer token. Every token rejection has code \"unauthorized\" and this message.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Server error. The body is not specified."
          },
          "429": {
            "description": "API keys only: the key lookup budget is exhausted for a moment. Retry after the Retry-After delay.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying. A hint, not a promise.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "CustomersApi"
        ],
        "description": "Read-only keys: 403 with an ErrorEnvelope, code \"forbidden\".",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CustomerCreateDto"
              }
            },
            "text/json": {
              "schema": {
                "$ref": "#/components/schemas/CustomerCreateDto"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/CustomerCreateDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CustomerCreatedDto"
                }
              }
            }
          },
          "400": {
            "description": "invalid_request: a missing name, an unknown currency or country, or a tenant without a customer number series. A request that cannot be bound (malformed JSON, a missing body, a parameter of the wrong type) gets ValidationProblemDetails as application/problem+json instead.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid Bearer token. Every token rejection has code \"unauthorized\" and this message.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Server error. The body is not specified."
          },
          "429": {
            "description": "API keys only: the key lookup budget is exhausted for a moment. Retry after the Retry-After delay.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying. A hint, not a promise.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "A read-only API key on a write operation (code \"forbidden\").",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "415": {
            "description": "The Content-Type is not one the body can be read from; send application/json.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/customers/{customerId}": {
      "get": {
        "tags": [
          "CustomersApi"
        ],
        "description": "Read-only keys: allowed.",
        "parameters": [
          {
            "name": "customerId",
            "in": "path",
            "required": true,
            "schema": {
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CustomerDetailDto"
                }
              }
            }
          },
          "404": {
            "description": "not_found: no customer with this id in the tenant.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid Bearer token. Every token rejection has code \"unauthorized\" and this message.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Server error. The body is not specified."
          },
          "429": {
            "description": "API keys only: the key lookup budget is exhausted for a moment. Retry after the Retry-After delay.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying. A hint, not a promise.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      },
      "patch": {
        "tags": [
          "CustomersApi"
        ],
        "description": "Read-only keys: 403 with an ErrorEnvelope, code \"forbidden\".",
        "parameters": [
          {
            "name": "customerId",
            "in": "path",
            "required": true,
            "schema": {
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CustomerPatchDto"
              }
            },
            "text/json": {
              "schema": {
                "$ref": "#/components/schemas/CustomerPatchDto"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/CustomerPatchDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CustomerPatchResultDto"
                }
              }
            }
          },
          "400": {
            "description": "invalid_request: the change was refused; the message says why. A request that cannot be bound (malformed JSON, a missing body, a parameter of the wrong type) gets ValidationProblemDetails as application/problem+json instead.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid Bearer token. Every token rejection has code \"unauthorized\" and this message.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Server error. The body is not specified."
          },
          "429": {
            "description": "API keys only: the key lookup budget is exhausted for a moment. Retry after the Retry-After delay.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying. A hint, not a promise.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "A read-only API key on a write operation (code \"forbidden\").",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "415": {
            "description": "The Content-Type is not one the body can be read from; send application/json.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/customers/lookups": {
      "get": {
        "tags": [
          "CustomersApi"
        ],
        "description": "Read-only keys: allowed.",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CustomerLookupsDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid Bearer token. Every token rejection has code \"unauthorized\" and this message.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Server error. The body is not specified."
          },
          "429": {
            "description": "API keys only: the key lookup budget is exhausted for a moment. Retry after the Retry-After delay.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying. A hint, not a promise.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/customers/{customerId}/addresses": {
      "post": {
        "tags": [
          "CustomersApi"
        ],
        "description": "Read-only keys: 403 with an ErrorEnvelope, code \"forbidden\".",
        "parameters": [
          {
            "name": "customerId",
            "in": "path",
            "required": true,
            "schema": {
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "addressTypeId",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CustomerAddressWriteDto"
              }
            },
            "text/json": {
              "schema": {
                "$ref": "#/components/schemas/CustomerAddressWriteDto"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/CustomerAddressWriteDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CustomerAddressDto"
                }
              }
            }
          },
          "400": {
            "description": "invalid_request: the address was refused; the message says why. A request that cannot be bound (malformed JSON, a missing body, a parameter of the wrong type) gets ValidationProblemDetails as application/problem+json instead.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid Bearer token. Every token rejection has code \"unauthorized\" and this message.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Server error. The body is not specified."
          },
          "429": {
            "description": "API keys only: the key lookup budget is exhausted for a moment. Retry after the Retry-After delay.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying. A hint, not a promise.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "A read-only API key on a write operation (code \"forbidden\").",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "415": {
            "description": "The Content-Type is not one the body can be read from; send application/json.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/brands": {
      "get": {
        "tags": [
          "BrandsApi"
        ],
        "summary": "Brands, sorted by lower-cased name, then id.",
        "description": "Read-only keys: allowed.",
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "description": "Case-insensitive contains on name and key.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "status",
            "in": "query",
            "description": "active (default), archived or any.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "key",
            "in": "query",
            "description": "Exact. Blank is refused.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "extId",
            "in": "query",
            "description": "Exact, after trimming. Blank is refused.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "pageSize",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "warning",
            "in": "query",
            "description": "any (at least one warning) or one code: ARCHIVED_ASSIGNED. Judged against the whole tenant, applied before sorting and paging. Blank or unknown is refused.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PageResponseOfBrandListItemDto"
                }
              }
            }
          },
          "400": {
            "description": "invalid_request: a blank or invalid filter, or an unknown status.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid Bearer token. Every token rejection has code \"unauthorized\" and this message.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Server error. The body is not specified."
          },
          "429": {
            "description": "API keys only: the key lookup budget is exhausted for a moment. Retry after the Retry-After delay.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying. A hint, not a promise.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "BrandsApi"
        ],
        "summary": "Creates a brand. The key is minted from the name when left out.",
        "description": "Read-only keys: 403 with an ErrorEnvelope, code \"forbidden\".",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/BrandCreateDto"
              }
            },
            "text/json": {
              "schema": {
                "$ref": "#/components/schemas/BrandCreateDto"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/BrandCreateDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BrandDto"
                }
              }
            }
          },
          "400": {
            "description": "invalid_request: a missing, too long or malformed field, an unknown role, or an archived party.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "forbidden: the caller lacks the edit_brands permission.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "404": {
            "description": "not_found: a role names a party that is not in the tenant.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "409": {
            "description": "conflict: name, key or extId is taken; details { field, existingId }. Only extId means the same record.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid Bearer token. Every token rejection has code \"unauthorized\" and this message.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Server error. The body is not specified."
          },
          "429": {
            "description": "API keys only: the key lookup budget is exhausted for a moment. Retry after the Retry-After delay.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying. A hint, not a promise.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "415": {
            "description": "The Content-Type is not one the body can be read from; send application/json.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/brands/warning-summary": {
      "get": {
        "tags": [
          "BrandsApi"
        ],
        "summary": "How many brands have warnings, over the whole tenant: total (each brand once) and per code. Not paged.",
        "description": "Read-only keys: allowed.",
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "description": "any (default, unlike the list: ARCHIVED_ASSIGNED is only on archived brands), active or archived.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CatalogWarningSummaryDto"
                }
              }
            }
          },
          "400": {
            "description": "invalid_request: an unknown status.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid Bearer token. Every token rejection has code \"unauthorized\" and this message.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Server error. The body is not specified."
          },
          "429": {
            "description": "API keys only: the key lookup budget is exhausted for a moment. Retry after the Retry-After delay.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying. A hint, not a promise.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/brands/{id}": {
      "get": {
        "tags": [
          "BrandsApi"
        ],
        "summary": "One brand with its texts, role defaults, logo and warnings.",
        "description": "Read-only keys: allowed.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BrandDto"
                }
              }
            }
          },
          "400": {
            "description": "invalid_request: id is not a whole number (digits only, at most 2147483647).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "404": {
            "description": "not_found: no brand with this id in the tenant.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid Bearer token. Every token rejection has code \"unauthorized\" and this message.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Server error. The body is not specified."
          },
          "429": {
            "description": "API keys only: the key lookup budget is exhausted for a moment. Retry after the Retry-After delay.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying. A hint, not a promise.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      },
      "patch": {
        "tags": [
          "BrandsApi"
        ],
        "summary": "Changes a brand. Requires version. A rename never changes the key. A PATCH that changes nothing keeps the version.",
        "description": "Read-only keys: 403 with an ErrorEnvelope, code \"forbidden\".",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/BrandPatchDto"
              }
            },
            "text/json": {
              "schema": {
                "$ref": "#/components/schemas/BrandPatchDto"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/BrandPatchDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BrandDto"
                }
              }
            }
          },
          "400": {
            "description": "invalid_request: a bad id, a missing version, an invalid field, an unknown role or an archived party.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "forbidden: the caller lacks the edit_brands permission.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "404": {
            "description": "not_found: no brand with this id in the tenant, or a role names a party that is not.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "409": {
            "description": "version_conflict (details { currentVersion }) or conflict (details { field, existingId }).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid Bearer token. Every token rejection has code \"unauthorized\" and this message.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Server error. The body is not specified."
          },
          "429": {
            "description": "API keys only: the key lookup budget is exhausted for a moment. Retry after the Retry-After delay.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying. A hint, not a promise.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "415": {
            "description": "The Content-Type is not one the body can be read from; send application/json.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "BrandsApi"
        ],
        "summary": "Deletes a brand no product names, with its texts, role defaults and logo. With a logo it also needs the media editor\n    right and media_publish. Otherwise 409 in_use: archive it instead.",
        "description": "Read-only keys: 403 with an ErrorEnvelope, code \"forbidden\".",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "version",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "No Content"
          },
          "400": {
            "description": "invalid_request: a bad id or a missing version.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "forbidden: the caller lacks edit_brands, or (for a brand with a logo) the media rights.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "404": {
            "description": "not_found: no brand with this id in the tenant.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "409": {
            "description": "version_conflict (details { currentVersion }) or in_use (details { brandCount, productCount }).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid Bearer token. Every token rejection has code \"unauthorized\" and this message.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Server error. The body is not specified."
          },
          "429": {
            "description": "API keys only: the key lookup budget is exhausted for a moment. Retry after the Retry-After delay.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying. A hint, not a promise.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/parties": {
      "get": {
        "tags": [
          "PartiesApi"
        ],
        "summary": "Parties, sorted by lower-cased legal name, then id. No contact coordinates in list items.",
        "description": "Read-only keys: allowed.",
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "description": "Case-insensitive contains on legalName and tradeName.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "status",
            "in": "query",
            "description": "active (default), archived or any.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "extId",
            "in": "query",
            "description": "Exact, after trimming. Blank is refused.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "countryCode",
            "in": "query",
            "description": "Exact ISO 3166-1 alpha-2, case-insensitive. Blank is refused.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "usedWithBrandId",
            "in": "query",
            "description": "Parties suggested for this brand: its defaults, then parties explicitly assigned to products whose resolved brand it is, most used first. A suggestion, never a restriction.",
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "pageSize",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "warning",
            "in": "query",
            "description": "any (at least one warning) or one code: POSTAL_ADDRESS_INCOMPLETE, ELECTRONIC_ADDRESS_MISSING, POSSIBLE_DUPLICATE or ARCHIVED_ASSIGNED. Judged against the whole tenant, applied before sorting and paging. Blank or unknown is refused.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PageResponseOfPartyListItemDto"
                }
              }
            }
          },
          "400": {
            "description": "invalid_request: a blank or invalid filter, or an unknown status.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid Bearer token. Every token rejection has code \"unauthorized\" and this message.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Server error. The body is not specified."
          },
          "429": {
            "description": "API keys only: the key lookup budget is exhausted for a moment. Retry after the Retry-After delay.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying. A hint, not a promise.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "PartiesApi"
        ],
        "summary": "Creates a party. legalName and countryCode are required; incomplete contact data is allowed and reported as warnings.",
        "description": "Read-only keys: 403 with an ErrorEnvelope, code \"forbidden\".",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PartyCreateDto"
              }
            },
            "text/json": {
              "schema": {
                "$ref": "#/components/schemas/PartyCreateDto"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/PartyCreateDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PartyDto"
                }
              }
            }
          },
          "400": {
            "description": "invalid_request: a missing, too long or malformed field; the message names it.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "forbidden: the caller lacks the edit_brands permission.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "409": {
            "description": "conflict: extId is taken; details { field, existingId } — the same record.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid Bearer token. Every token rejection has code \"unauthorized\" and this message.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Server error. The body is not specified."
          },
          "429": {
            "description": "API keys only: the key lookup budget is exhausted for a moment. Retry after the Retry-After delay.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying. A hint, not a promise.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "415": {
            "description": "The Content-Type is not one the body can be read from; send application/json.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/parties/warning-summary": {
      "get": {
        "tags": [
          "PartiesApi"
        ],
        "summary": "How many parties have warnings, over the whole tenant: total (each party once) and per code. Not paged.",
        "description": "Read-only keys: allowed.",
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "description": "any (default, unlike the list: ARCHIVED_ASSIGNED is only on archived parties), active or archived.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CatalogWarningSummaryDto"
                }
              }
            }
          },
          "400": {
            "description": "invalid_request: an unknown status.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid Bearer token. Every token rejection has code \"unauthorized\" and this message.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Server error. The body is not specified."
          },
          "429": {
            "description": "API keys only: the key lookup budget is exhausted for a moment. Retry after the Retry-After delay.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying. A hint, not a promise.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/parties/{id}": {
      "get": {
        "tags": [
          "PartiesApi"
        ],
        "summary": "One party with its address, contacts, usage and warnings.",
        "description": "Read-only keys: allowed.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PartyDto"
                }
              }
            }
          },
          "400": {
            "description": "invalid_request: id is not a whole number (digits only, at most 2147483647).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "404": {
            "description": "not_found: no party with this id in the tenant.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid Bearer token. Every token rejection has code \"unauthorized\" and this message.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Server error. The body is not specified."
          },
          "429": {
            "description": "API keys only: the key lookup budget is exhausted for a moment. Retry after the Retry-After delay.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying. A hint, not a promise.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      },
      "patch": {
        "tags": [
          "PartiesApi"
        ],
        "summary": "Changes a party. Requires version; null leaves a field, \"\" clears an optional one. A PATCH that changes nothing keeps the version.",
        "description": "Read-only keys: 403 with an ErrorEnvelope, code \"forbidden\".",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PartyPatchDto"
              }
            },
            "text/json": {
              "schema": {
                "$ref": "#/components/schemas/PartyPatchDto"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/PartyPatchDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PartyDto"
                }
              }
            }
          },
          "400": {
            "description": "invalid_request: a bad id, a missing version, or an invalid field.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "forbidden: the caller lacks the edit_brands permission.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "404": {
            "description": "not_found: no party with this id in the tenant.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "409": {
            "description": "version_conflict (details { currentVersion }) or conflict on extId (details { field, existingId }).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid Bearer token. Every token rejection has code \"unauthorized\" and this message.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Server error. The body is not specified."
          },
          "429": {
            "description": "API keys only: the key lookup budget is exhausted for a moment. Retry after the Retry-After delay.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying. A hint, not a promise.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "415": {
            "description": "The Content-Type is not one the body can be read from; send application/json.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "PartiesApi"
        ],
        "summary": "Deletes a party nothing references. Otherwise 409 in_use: archive it instead.",
        "description": "Read-only keys: 403 with an ErrorEnvelope, code \"forbidden\".",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "version",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "No Content"
          },
          "400": {
            "description": "invalid_request: a bad id or a missing version.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "forbidden: the caller lacks the edit_brands permission.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "404": {
            "description": "not_found: no party with this id in the tenant.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "409": {
            "description": "version_conflict (details { currentVersion }) or in_use (details { brandCount, productCount }).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid Bearer token. Every token rejection has code \"unauthorized\" and this message.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Server error. The body is not specified."
          },
          "429": {
            "description": "API keys only: the key lookup budget is exhausted for a moment. Retry after the Retry-After delay.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying. A hint, not a promise.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/products/{id}/brand": {
      "get": {
        "tags": [
          "ProductBrandApi"
        ],
        "summary": "The product's brand and responsible parties: what it stores and what resolves, with sources and completeness warnings.",
        "description": "Read-only keys: allowed.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProductBrandDto"
                }
              }
            }
          },
          "400": {
            "description": "invalid_request: id is not a whole number (digits only, at most 2147483647).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "404": {
            "description": "not_found: no product with this id in the tenant.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid Bearer token. Every token rejection has code \"unauthorized\" and this message.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Server error. The body is not specified."
          },
          "429": {
            "description": "API keys only: the key lookup budget is exhausted for a moment. Retry after the Retry-After delay.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying. A hint, not a promise.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/activities": {
      "get": {
        "tags": [
          "ActivitiesApi"
        ],
        "description": "Read-only keys: allowed.",
        "parameters": [
          {
            "name": "isProject",
            "in": "query",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "companyId",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "personId",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "activityTypeId",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "parentId",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "dateFrom",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "dateTo",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "customer",
            "in": "query",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "vendor",
            "in": "query",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "q",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "tagItemIds",
            "in": "query",
            "schema": {
              "type": "array",
              "items": {
                "type": "integer",
                "format": "int32"
              }
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "pageSize",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PageResponseOfActivityDto"
                }
              }
            }
          },
          "400": {
            "description": "The request could not be bound: malformed JSON, a missing body, or a parameter of the wrong type.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid Bearer token. Every token rejection has code \"unauthorized\" and this message.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Server error. The body is not specified."
          },
          "429": {
            "description": "API keys only: the key lookup budget is exhausted for a moment. Retry after the Retry-After delay.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying. A hint, not a promise.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "ActivitiesApi"
        ],
        "description": "Read-only keys: 403 with an ErrorEnvelope, code \"forbidden\".",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ActivitySaveDto"
              }
            },
            "text/json": {
              "schema": {
                "$ref": "#/components/schemas/ActivitySaveDto"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/ActivitySaveDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/IdResultDto"
                }
              }
            }
          },
          "400": {
            "description": "bad_request: the activity could not be saved; the message says why. A request that cannot be bound (malformed JSON, a missing body, a parameter of the wrong type) gets ValidationProblemDetails as application/problem+json instead.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid Bearer token. Every token rejection has code \"unauthorized\" and this message.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Server error. The body is not specified."
          },
          "429": {
            "description": "API keys only: the key lookup budget is exhausted for a moment. Retry after the Retry-After delay.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying. A hint, not a promise.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "A read-only API key on a write operation (code \"forbidden\").",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "415": {
            "description": "The Content-Type is not one the body can be read from; send application/json.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/activities/{id}": {
      "get": {
        "tags": [
          "ActivitiesApi"
        ],
        "description": "Read-only keys: allowed.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "isProject",
            "in": "query",
            "schema": {
              "type": "boolean"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ActivityDetailDto"
                }
              }
            }
          },
          "400": {
            "description": "The request could not be bound: malformed JSON, a missing body, or a parameter of the wrong type.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationProblemDetails"
                }
              }
            }
          },
          "404": {
            "description": "No activity with this id, or it could not be read.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid Bearer token. Every token rejection has code \"unauthorized\" and this message.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Server error. The body is not specified."
          },
          "429": {
            "description": "API keys only: the key lookup budget is exhausted for a moment. Retry after the Retry-After delay.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying. A hint, not a promise.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/activities/{id}/complete": {
      "post": {
        "tags": [
          "ActivitiesApi"
        ],
        "description": "Read-only keys: 403 with an ErrorEnvelope, code \"forbidden\".",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ActivityCompleteDto"
              }
            },
            "text/json": {
              "schema": {
                "$ref": "#/components/schemas/ActivityCompleteDto"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/ActivityCompleteDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "204": {
            "description": "No Content"
          },
          "400": {
            "description": "The request could not be bound: malformed JSON, a missing body, or a parameter of the wrong type.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationProblemDetails"
                }
              }
            }
          },
          "404": {
            "description": "No activity with this id.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid Bearer token. Every token rejection has code \"unauthorized\" and this message.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Server error. The body is not specified."
          },
          "429": {
            "description": "API keys only: the key lookup budget is exhausted for a moment. Retry after the Retry-After delay.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying. A hint, not a promise.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "A read-only API key on a write operation (code \"forbidden\").",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "415": {
            "description": "The Content-Type is not one the body can be read from; send application/json.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/activity-people": {
      "get": {
        "tags": [
          "ActivityPeopleApi"
        ],
        "description": "Read-only keys: allowed.",
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/ActivityPersonDto"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid Bearer token. Every token rejection has code \"unauthorized\" and this message.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Server error. The body is not specified."
          },
          "429": {
            "description": "API keys only: the key lookup budget is exhausted for a moment. Retry after the Retry-After delay.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying. A hint, not a promise.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/activity-tags": {
      "get": {
        "tags": [
          "ActivityTagsApi"
        ],
        "description": "Read-only keys: allowed.",
        "parameters": [
          {
            "name": "activityTypeId",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/ActivityTagDto"
                  }
                }
              }
            }
          },
          "400": {
            "description": "The request could not be bound: malformed JSON, a missing body, or a parameter of the wrong type.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid Bearer token. Every token rejection has code \"unauthorized\" and this message.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Server error. The body is not specified."
          },
          "429": {
            "description": "API keys only: the key lookup budget is exhausted for a moment. Retry after the Retry-After delay.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying. A hint, not a promise.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/activities/{id}/timeline": {
      "get": {
        "tags": [
          "ActivityTimelineApi"
        ],
        "description": "Read-only keys: allowed.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "pageSize",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PageResponseOfActivityTimelineEntryDto"
                }
              }
            }
          },
          "400": {
            "description": "The request could not be bound: malformed JSON, a missing body, or a parameter of the wrong type.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid Bearer token. Every token rejection has code \"unauthorized\" and this message.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Server error. The body is not specified."
          },
          "429": {
            "description": "API keys only: the key lookup budget is exhausted for a moment. Retry after the Retry-After delay.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying. A hint, not a promise.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/activities/{id}/comments": {
      "post": {
        "tags": [
          "ActivityTimelineApi"
        ],
        "description": "Read-only keys: 403 with an ErrorEnvelope, code \"forbidden\".",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ActivityCommentSaveDto"
              }
            },
            "text/json": {
              "schema": {
                "$ref": "#/components/schemas/ActivityCommentSaveDto"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/ActivityCommentSaveDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ActivityTimelineEntryDto"
                }
              }
            }
          },
          "400": {
            "description": "bad_request: the comment was refused; the message says why. A request that cannot be bound (malformed JSON, a missing body, a parameter of the wrong type) gets ValidationProblemDetails as application/problem+json instead.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid Bearer token. Every token rejection has code \"unauthorized\" and this message.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Server error. The body is not specified."
          },
          "429": {
            "description": "API keys only: the key lookup budget is exhausted for a moment. Retry after the Retry-After delay.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying. A hint, not a promise.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "A read-only API key on a write operation (code \"forbidden\").",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "415": {
            "description": "The Content-Type is not one the body can be read from; send application/json.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/activities/comments/{logId}": {
      "put": {
        "tags": [
          "ActivityTimelineApi"
        ],
        "description": "Read-only keys: 403 with an ErrorEnvelope, code \"forbidden\".",
        "parameters": [
          {
            "name": "logId",
            "in": "path",
            "required": true,
            "schema": {
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ActivityCommentSaveDto"
              }
            },
            "text/json": {
              "schema": {
                "$ref": "#/components/schemas/ActivityCommentSaveDto"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/ActivityCommentSaveDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "204": {
            "description": "No Content"
          },
          "400": {
            "description": "bad_request: the comment was refused; the message says why. A request that cannot be bound (malformed JSON, a missing body, a parameter of the wrong type) gets ValidationProblemDetails as application/problem+json instead.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationProblemDetails"
                }
              }
            }
          },
          "404": {
            "description": "No such comment.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid Bearer token. Every token rejection has code \"unauthorized\" and this message.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Server error. The body is not specified."
          },
          "429": {
            "description": "API keys only: the key lookup budget is exhausted for a moment. Retry after the Retry-After delay.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying. A hint, not a promise.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "A read-only API key on a write operation (code \"forbidden\").",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "415": {
            "description": "The Content-Type is not one the body can be read from; send application/json.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "ActivityTimelineApi"
        ],
        "description": "Read-only keys: 403 with an ErrorEnvelope, code \"forbidden\".",
        "parameters": [
          {
            "name": "logId",
            "in": "path",
            "required": true,
            "schema": {
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "No Content"
          },
          "404": {
            "description": "No such comment.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid Bearer token. Every token rejection has code \"unauthorized\" and this message.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Server error. The body is not specified."
          },
          "429": {
            "description": "API keys only: the key lookup budget is exhausted for a moment. Retry after the Retry-After delay.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying. A hint, not a promise.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "A read-only API key on a write operation (code \"forbidden\").",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/activity-types": {
      "get": {
        "tags": [
          "ActivityTypesApi"
        ],
        "description": "Read-only keys: allowed.",
        "parameters": [
          {
            "name": "isProject",
            "in": "query",
            "schema": {
              "type": "boolean"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/ActivityTypeDto"
                  }
                }
              }
            }
          },
          "400": {
            "description": "The request could not be bound: malformed JSON, a missing body, or a parameter of the wrong type.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid Bearer token. Every token rejection has code \"unauthorized\" and this message.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Server error. The body is not specified."
          },
          "429": {
            "description": "API keys only: the key lookup budget is exhausted for a moment. Retry after the Retry-After delay.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying. A hint, not a promise.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "ActivityCommentSaveDto": {
        "required": [
          "bodyMd"
        ],
        "type": "object",
        "properties": {
          "bodyMd": {
            "type": "string"
          }
        }
      },
      "ActivityCompanyLinkDto": {
        "required": [
          "id",
          "companyId"
        ],
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "format": "int32"
          },
          "companyId": {
            "type": "integer",
            "format": "int32"
          },
          "companyName": {
            "type": [
              "null",
              "string"
            ]
          },
          "personId": {
            "type": [
              "null",
              "integer"
            ],
            "format": "int32"
          },
          "personName": {
            "type": [
              "null",
              "string"
            ]
          }
        }
      },
      "ActivityCompleteDto": {
        "type": "object",
        "properties": {
          "complete": {
            "type": "boolean"
          }
        }
      },
      "ActivityDetailDto": {
        "required": [
          "id"
        ],
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "format": "int32"
          },
          "isProject": {
            "type": "boolean"
          },
          "activityTypeId": {
            "type": "integer",
            "format": "int32"
          },
          "activityType": {
            "type": [
              "null",
              "string"
            ]
          },
          "date": {
            "type": [
              "null",
              "string"
            ],
            "format": "date-time"
          },
          "dateEnd": {
            "type": [
              "null",
              "string"
            ],
            "format": "date-time"
          },
          "description": {
            "type": [
              "null",
              "string"
            ]
          },
          "notes": {
            "type": [
              "null",
              "string"
            ]
          },
          "complete": {
            "type": "boolean"
          },
          "personId": {
            "type": [
              "null",
              "integer"
            ],
            "format": "int32"
          },
          "personName": {
            "type": [
              "null",
              "string"
            ]
          },
          "parentId": {
            "type": [
              "null",
              "integer"
            ],
            "format": "int32"
          },
          "parentName": {
            "type": [
              "null",
              "string"
            ]
          },
          "createdAt": {
            "type": [
              "null",
              "string"
            ],
            "format": "date-time"
          },
          "value": {
            "type": [
              "null",
              "number"
            ],
            "format": "double"
          },
          "decisionDate": {
            "type": [
              "null",
              "string"
            ],
            "format": "date-time"
          },
          "percentId": {
            "type": [
              "null",
              "integer"
            ],
            "format": "int32"
          },
          "companyLinks": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ActivityCompanyLinkDto"
            }
          },
          "people": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ActivityPersonDto"
            }
          },
          "tagItems": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AssignedActivityTagDto"
            }
          },
          "fieldValues": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ActivityFieldValueDto"
            }
          },
          "productLinks": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ActivityProductLinkDto"
            }
          },
          "timeline": {
            "type": [
              "null",
              "array"
            ],
            "items": {
              "$ref": "#/components/schemas/ActivityTimelineEntryDto"
            },
            "description": "Populated by the MCP get_activity tool only (latest 20 entries); null on the REST detail endpoint."
          }
        }
      },
      "ActivityDto": {
        "required": [
          "id"
        ],
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "format": "int32"
          },
          "isProject": {
            "type": "boolean"
          },
          "activityTypeId": {
            "type": "integer",
            "format": "int32"
          },
          "activityType": {
            "type": [
              "null",
              "string"
            ]
          },
          "date": {
            "type": [
              "null",
              "string"
            ],
            "format": "date-time"
          },
          "dateEnd": {
            "type": [
              "null",
              "string"
            ],
            "format": "date-time"
          },
          "description": {
            "type": [
              "null",
              "string"
            ]
          },
          "complete": {
            "type": "boolean"
          },
          "personId": {
            "type": [
              "null",
              "integer"
            ],
            "format": "int32"
          },
          "personName": {
            "type": [
              "null",
              "string"
            ]
          },
          "value": {
            "type": [
              "null",
              "number"
            ],
            "format": "double"
          },
          "decisionDate": {
            "type": [
              "null",
              "string"
            ],
            "format": "date-time"
          },
          "percentId": {
            "type": [
              "null",
              "integer"
            ],
            "format": "int32"
          },
          "companyLinks": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ActivityCompanyLinkDto"
            }
          },
          "tagItems": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AssignedActivityTagDto"
            }
          }
        }
      },
      "ActivityFieldValueDto": {
        "required": [
          "name"
        ],
        "type": "object",
        "properties": {
          "name": {
            "type": "string"
          },
          "stringValue": {
            "type": [
              "null",
              "string"
            ]
          },
          "decimalValue": {
            "type": [
              "null",
              "number"
            ],
            "format": "double"
          }
        }
      },
      "ActivityPersonDto": {
        "required": [
          "id"
        ],
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "format": "int32"
          },
          "firstname": {
            "type": [
              "null",
              "string"
            ]
          },
          "surname": {
            "type": [
              "null",
              "string"
            ]
          },
          "fullName": {
            "type": [
              "null",
              "string"
            ]
          }
        }
      },
      "ActivityProductLinkDto": {
        "required": [
          "productId"
        ],
        "type": "object",
        "properties": {
          "productId": {
            "type": "integer",
            "format": "int32"
          },
          "productNumber": {
            "type": [
              "null",
              "string"
            ]
          },
          "productName": {
            "type": [
              "null",
              "string"
            ]
          }
        }
      },
      "ActivitySaveCompanyLinkDto": {
        "required": [
          "companyId"
        ],
        "type": "object",
        "properties": {
          "companyId": {
            "type": "integer",
            "format": "int32"
          },
          "personId": {
            "type": [
              "null",
              "integer"
            ],
            "format": "int32"
          }
        }
      },
      "ActivitySaveDto": {
        "required": [
          "activityTypeId"
        ],
        "type": "object",
        "properties": {
          "id": {
            "type": [
              "null",
              "integer"
            ],
            "description": "Omit (or 0) to create; set to update. Update is a FULL REPLACE.",
            "format": "int32"
          },
          "isProject": {
            "type": "boolean"
          },
          "activityTypeId": {
            "type": "integer",
            "format": "int32"
          },
          "date": {
            "type": [
              "null",
              "string"
            ],
            "format": "date-time"
          },
          "dateEnd": {
            "type": [
              "null",
              "string"
            ],
            "format": "date-time"
          },
          "description": {
            "type": [
              "null",
              "string"
            ]
          },
          "notes": {
            "type": [
              "null",
              "string"
            ]
          },
          "complete": {
            "type": "boolean"
          },
          "personId": {
            "type": [
              "null",
              "integer"
            ],
            "format": "int32"
          },
          "peopleIds": {
            "type": [
              "null",
              "array"
            ],
            "items": {
              "type": "integer",
              "format": "int32"
            }
          },
          "companyLinks": {
            "type": [
              "null",
              "array"
            ],
            "items": {
              "$ref": "#/components/schemas/ActivitySaveCompanyLinkDto"
            }
          },
          "tagItemIds": {
            "type": [
              "null",
              "array"
            ],
            "items": {
              "type": "integer",
              "format": "int32"
            }
          },
          "fieldValues": {
            "type": [
              "null",
              "array"
            ],
            "items": {
              "$ref": "#/components/schemas/ActivityFieldValueDto"
            }
          },
          "productIds": {
            "type": [
              "null",
              "array"
            ],
            "items": {
              "type": "integer",
              "format": "int32"
            }
          },
          "value": {
            "type": [
              "null",
              "number"
            ],
            "format": "double"
          },
          "decisionDate": {
            "type": [
              "null",
              "string"
            ],
            "format": "date-time"
          },
          "percentId": {
            "type": [
              "null",
              "integer"
            ],
            "format": "int32"
          },
          "parentId": {
            "type": [
              "null",
              "integer"
            ],
            "description": "Parent activity id for hierarchy. null/0 detaches. Activities only (not projects). Self-parent or a cycle is rejected with 400.",
            "format": "int32"
          }
        }
      },
      "ActivityTagDto": {
        "required": [
          "id"
        ],
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "format": "int32"
          },
          "name": {
            "type": [
              "null",
              "string"
            ]
          },
          "multiple": {
            "type": "boolean"
          },
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ActivityTagItemDto"
            }
          }
        }
      },
      "ActivityTagItemDto": {
        "required": [
          "id"
        ],
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "format": "int32"
          },
          "name": {
            "type": [
              "null",
              "string"
            ]
          },
          "activityTagId": {
            "type": "integer",
            "format": "int32"
          },
          "sort": {
            "type": "integer",
            "format": "int16"
          },
          "decimalValue": {
            "type": [
              "null",
              "number"
            ],
            "format": "double"
          }
        }
      },
      "ActivityTimelineEntryDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "format": "int32"
          },
          "kind": {
            "type": "integer",
            "description": "0 = comment, 1 = system event.",
            "format": "int32"
          },
          "eventType": {
            "type": [
              "null",
              "integer"
            ],
            "description": "1 moved, 2 completed, 3 uncompleted, 4 person added, 5 person removed, 6 tag added, 7 tag removed.",
            "format": "int32"
          },
          "personId": {
            "type": [
              "null",
              "integer"
            ],
            "format": "int32"
          },
          "personName": {
            "type": [
              "null",
              "string"
            ]
          },
          "bodyMd": {
            "type": [
              "null",
              "string"
            ]
          },
          "eventData": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "$ref": "#/components/schemas/ActivityTimelineEventDataDto"
              }
            ]
          },
          "createdUtc": {
            "type": "string",
            "format": "date-time"
          },
          "editedUtc": {
            "type": [
              "null",
              "string"
            ],
            "format": "date-time"
          },
          "isOwn": {
            "type": "boolean",
            "description": "True when the entry is a comment authored by the calling user (may edit/delete)."
          }
        }
      },
      "ActivityTimelineEventDataDto": {
        "type": "object",
        "properties": {
          "fromColumn": {
            "type": [
              "null",
              "string"
            ]
          },
          "toColumn": {
            "type": [
              "null",
              "string"
            ]
          },
          "tagName": {
            "type": [
              "null",
              "string"
            ]
          },
          "itemName": {
            "type": [
              "null",
              "string"
            ]
          },
          "personName": {
            "type": [
              "null",
              "string"
            ]
          }
        }
      },
      "ActivityTypeDto": {
        "required": [
          "id"
        ],
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "format": "int32"
          },
          "name": {
            "type": [
              "null",
              "string"
            ]
          },
          "sort": {
            "type": "integer",
            "format": "int16"
          },
          "isProject": {
            "type": "boolean"
          },
          "allowCustomer": {
            "type": "boolean"
          },
          "allowVendor": {
            "type": "boolean"
          },
          "allowProduct": {
            "type": "boolean"
          },
          "fields": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ActivityTypeFieldDto"
            }
          }
        }
      },
      "ActivityTypeFieldDto": {
        "required": [
          "id",
          "name"
        ],
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "format": "int32"
          },
          "name": {
            "type": "string"
          },
          "fieldType": {
            "type": "string"
          },
          "sort": {
            "type": "integer",
            "format": "int32"
          }
        }
      },
      "AssignedActivityTagDto": {
        "required": [
          "tagItemId"
        ],
        "type": "object",
        "properties": {
          "tagItemId": {
            "type": "integer",
            "format": "int32"
          },
          "tagItemName": {
            "type": [
              "null",
              "string"
            ]
          },
          "tagId": {
            "type": "integer",
            "format": "int32"
          },
          "tagName": {
            "type": [
              "null",
              "string"
            ]
          },
          "decimalValue": {
            "type": "number",
            "format": "double"
          }
        }
      },
      "BrandCreateDto": {
        "type": "object",
        "properties": {
          "name": {
            "type": [
              "null",
              "string"
            ]
          },
          "key": {
            "type": [
              "null",
              "string"
            ]
          },
          "extId": {
            "type": [
              "null",
              "string"
            ]
          },
          "websiteUrl": {
            "type": [
              "null",
              "string"
            ]
          },
          "status": {
            "type": [
              "null",
              "string"
            ]
          },
          "texts": {
            "type": [
              "null",
              "array"
            ],
            "items": {
              "$ref": "#/components/schemas/BrandTextWriteDto"
            }
          },
          "roles": {
            "type": [
              "null",
              "object"
            ],
            "additionalProperties": {
              "type": [
                "null",
                "integer"
              ],
              "format": "int32"
            }
          }
        },
        "description": "`name` is required. `key` is minted from the name when left out. `roles`: role → party id."
      },
      "BrandDto": {
        "required": [
          "id",
          "key",
          "name",
          "status",
          "assignedProductCount",
          "version",
          "createdAt",
          "updatedAt"
        ],
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "format": "int32"
          },
          "key": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "status": {
            "type": "string"
          },
          "logo": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "$ref": "#/components/schemas/BrandLogoDto"
              }
            ]
          },
          "assignedProductCount": {
            "type": "integer",
            "format": "int32"
          },
          "extId": {
            "type": [
              "null",
              "string"
            ]
          },
          "websiteUrl": {
            "type": [
              "null",
              "string"
            ]
          },
          "texts": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/BrandTextDto"
            }
          },
          "roles": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/BrandRoleDto"
            },
            "description": "The brand's default party per role. A role without a default is absent."
          },
          "warnings": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "ARCHIVED_ASSIGNED (an open set). Never blocking."
          },
          "version": {
            "type": "integer",
            "format": "int32"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "BrandListItemDto": {
        "required": [
          "id",
          "key",
          "name",
          "status",
          "assignedProductCount"
        ],
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "format": "int32"
          },
          "key": {
            "type": "string",
            "description": "A stable machine key ([a-z0-9-], unique per instance). Not a URL slug."
          },
          "name": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "description": "`active` or `archived` (an open set). An archived brand stays on the products that have it."
          },
          "logo": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "$ref": "#/components/schemas/BrandLogoDto"
              }
            ]
          },
          "assignedProductCount": {
            "type": "integer",
            "description": "Products that name this brand directly (rows in product_brand). Inheriting variants are not counted; a product deleted\n            since the last daily clean-up may be.",
            "format": "int32"
          },
          "warnings": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "ARCHIVED_ASSIGNED (an open set). Never blocking; an empty list never means \"compliant\"."
          }
        }
      },
      "BrandLogoDto": {
        "required": [
          "placementId",
          "assetId",
          "media"
        ],
        "type": "object",
        "properties": {
          "placementId": {
            "type": "integer",
            "format": "int64"
          },
          "assetId": {
            "type": "integer",
            "format": "int64"
          },
          "media": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "$ref": "#/components/schemas/JsonElement"
              }
            ]
          }
        },
        "description": "The brand's logo: its primary media placement (instance-wide). Media is the shared media\n            descriptor (the same JSON the media API and the storefront feed carry), null until the asset has a ready version."
      },
      "BrandPatchDto": {
        "type": "object",
        "properties": {
          "version": {
            "type": [
              "null",
              "integer"
            ],
            "format": "int32"
          },
          "name": {
            "type": [
              "null",
              "string"
            ]
          },
          "key": {
            "type": [
              "null",
              "string"
            ]
          },
          "extId": {
            "type": [
              "null",
              "string"
            ]
          },
          "websiteUrl": {
            "type": [
              "null",
              "string"
            ]
          },
          "status": {
            "type": [
              "null",
              "string"
            ]
          },
          "texts": {
            "type": [
              "null",
              "array"
            ],
            "items": {
              "$ref": "#/components/schemas/BrandTextWriteDto"
            }
          },
          "roles": {
            "type": [
              "null",
              "object"
            ],
            "additionalProperties": {
              "type": [
                "null",
                "integer"
              ],
              "format": "int32"
            }
          }
        },
        "description": "A field left out (or null) is unchanged; \"\" clears `extId` or `websiteUrl`. `texts` are upserts per\n            language; `roles` as `{ \"manufacturer\": partyId | null }`, where null removes the default. `version` is required."
      },
      "BrandRefDto": {
        "required": [
          "id",
          "key",
          "name"
        ],
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "format": "int32"
          },
          "key": {
            "type": "string"
          },
          "name": {
            "type": "string"
          }
        }
      },
      "BrandRoleDto": {
        "required": [
          "role",
          "party"
        ],
        "type": "object",
        "properties": {
          "role": {
            "type": "string"
          },
          "party": {
            "$ref": "#/components/schemas/PartySummaryDto"
          }
        }
      },
      "BrandTextDto": {
        "required": [
          "language",
          "description"
        ],
        "type": "object",
        "properties": {
          "language": {
            "type": "string"
          },
          "description": {
            "type": "string"
          }
        }
      },
      "BrandTextWriteDto": {
        "type": "object",
        "properties": {
          "language": {
            "type": [
              "null",
              "string"
            ]
          },
          "description": {
            "type": [
              "null",
              "string"
            ]
          }
        },
        "description": "A text per language (a culture such as `sv-se`). In a PATCH, `description: null` removes that language."
      },
      "CatalogWarningCountDto": {
        "required": [
          "code",
          "count"
        ],
        "type": "object",
        "properties": {
          "code": {
            "type": "string"
          },
          "count": {
            "type": "integer",
            "format": "int32"
          }
        }
      },
      "CatalogWarningSummaryDto": {
        "required": [
          "total"
        ],
        "type": "object",
        "properties": {
          "total": {
            "type": "integer",
            "description": "Records with at least one warning; a record with two warnings counts once.",
            "format": "int32"
          },
          "byCode": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CatalogWarningCountDto"
            },
            "description": "Per code, only codes with a count above zero, in the order the records list them. Codes are an open set."
          }
        },
        "description": "GET /api/v1/parties/warning-summary and /api/v1/brands/warning-summary (list-warnings spec 2026-10-04 §5.3): the records\n            with at least one warning, over the whole tenant in the requested status (default any)."
      },
      "CodeCandidateDto": {
        "required": [
          "value",
          "matchKey",
          "format"
        ],
        "type": "object",
        "properties": {
          "value": {
            "type": "string"
          },
          "matchKey": {
            "type": "string"
          },
          "format": {
            "type": "integer",
            "format": "int32"
          }
        }
      },
      "CodeMatchDto": {
        "required": [
          "namespace",
          "productId",
          "productInactive",
          "code"
        ],
        "type": "object",
        "properties": {
          "namespace": {
            "type": "string",
            "description": "gtin or local: the namespace the input matched in."
          },
          "productId": {
            "type": "integer",
            "format": "int32"
          },
          "productNumber": {
            "type": [
              "null",
              "string"
            ]
          },
          "productName": {
            "type": [
              "null",
              "string"
            ]
          },
          "productInactive": {
            "type": "boolean"
          },
          "code": {
            "$ref": "#/components/schemas/ProductCodeDto"
          }
        },
        "description": "One hit of `GET product-codes/find`."
      },
      "CodeWarningDto": {
        "required": [
          "code",
          "message"
        ],
        "type": "object",
        "properties": {
          "code": {
            "type": "string"
          },
          "message": {
            "type": "string"
          }
        }
      },
      "CompanyProfileChangeResultDto": {
        "required": [
          "changed",
          "unchanged",
          "failed"
        ],
        "type": "object",
        "properties": {
          "changed": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CompanyProfileFieldChangeDto"
            },
            "description": "Fields whose stored value differs after the write."
          },
          "unchanged": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Fields the caller sent that already held that value, so nothing was written."
          },
          "failed": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Fields the caller sent whose write was attempted and whose stored value did not\n            move. Never folded into string[] CompanyProfileChangeResultDto.Unchanged: that would report a failure as \"already\n            correct\"."
          }
        },
        "description": "What the update did, as the server observed it. This is what the assistant narrates\n             afterwards, which is why it is re-read from the settings rather than echoed from the request.\n\n             The three lists are deliberately distinct. \"The value was already what you asked for\" and\n             \"we wrote it and it did not move\" are different answers, and only the first one means the\n             assistant should tell the customer their details are already right."
      },
      "CompanyProfileDto": {
        "required": [
          "rawSettings"
        ],
        "type": "object",
        "properties": {
          "companyName": {
            "type": [
              "null",
              "string"
            ]
          },
          "orgNo": {
            "type": [
              "null",
              "string"
            ]
          },
          "vatNo": {
            "type": [
              "null",
              "string"
            ]
          },
          "street": {
            "type": [
              "null",
              "string"
            ]
          },
          "addressLine2": {
            "type": [
              "null",
              "string"
            ]
          },
          "zipCode": {
            "type": [
              "null",
              "string"
            ]
          },
          "city": {
            "type": [
              "null",
              "string"
            ]
          },
          "country": {
            "type": [
              "null",
              "string"
            ]
          },
          "contactPerson": {
            "type": [
              "null",
              "string"
            ]
          },
          "email": {
            "type": [
              "null",
              "string"
            ]
          },
          "phone": {
            "type": [
              "null",
              "string"
            ]
          },
          "website": {
            "type": [
              "null",
              "string"
            ]
          },
          "fSkattText": {
            "type": [
              "null",
              "string"
            ]
          },
          "bankgiro": {
            "type": [
              "null",
              "string"
            ]
          },
          "plusgiro": {
            "type": [
              "null",
              "string"
            ]
          },
          "iban": {
            "type": [
              "null",
              "string"
            ]
          },
          "swift": {
            "type": [
              "null",
              "string"
            ]
          },
          "bankAccountsJson": {
            "type": [
              "null",
              "string"
            ],
            "description": "Raw per-currency bank-account JSON (setting `inexchangebankaccounts`)."
          },
          "swishNumber": {
            "type": [
              "null",
              "string"
            ]
          },
          "swishQrEnabled": {
            "type": "boolean"
          },
          "rawSettings": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "description": "Every underlying setting key with its resolved value, for callers that need the raw form."
          }
        },
        "description": "The tenant's company profile as shown under Komma igång › Företagsuppgifter (identity, address,\ncontact, payment, Swish). Values are the resolved setting values (user → global → default);\nnull means the key is not set on this tenant."
      },
      "CompanyProfileFieldChangeDto": {
        "required": [
          "field"
        ],
        "type": "object",
        "properties": {
          "field": {
            "type": "string"
          },
          "from": {
            "type": [
              "null",
              "string"
            ]
          },
          "to": {
            "type": [
              "null",
              "string"
            ]
          }
        },
        "description": "One field the server actually changed, with the values it read before and after the\n            write — not the values the caller sent."
      },
      "CompanyProfileUpdateDto": {
        "type": "object",
        "properties": {
          "companyName": {
            "type": [
              "null",
              "string"
            ]
          },
          "orgNo": {
            "type": [
              "null",
              "string"
            ]
          },
          "vatNo": {
            "type": [
              "null",
              "string"
            ]
          },
          "street": {
            "type": [
              "null",
              "string"
            ]
          },
          "addressLine2": {
            "type": [
              "null",
              "string"
            ]
          },
          "zip": {
            "type": [
              "null",
              "string"
            ]
          },
          "city": {
            "type": [
              "null",
              "string"
            ]
          },
          "country": {
            "type": [
              "null",
              "string"
            ]
          },
          "email": {
            "type": [
              "null",
              "string"
            ]
          },
          "phone": {
            "type": [
              "null",
              "string"
            ]
          },
          "website": {
            "type": [
              "null",
              "string"
            ]
          },
          "fskattText": {
            "type": [
              "null",
              "string"
            ]
          }
        },
        "description": "The fields `PATCH api/v1/tenant-settings/company-profile` will write. Every property is\nnullable and only the non-null ones are touched, so a caller changing the city sends the city.\n\nThe bank fields are deliberately absent. Bankgiro, plusgiro, IBAN, SWIFT, the\nper-currency inexchangebankaccounts list and the Swish number are printed on customer\ninvoices and steer which ledger account incoming money lands in, so a write path to them is a\npayment-redirection path — reachable by anything that can get text in front of the assistant,\nincluding a file the customer was sent by someone else. They are not accepted-and-ignored here;\nthey have no property, therefore no code path. A body naming them changes nothing. Changing them\nstays a deliberate act on the Inställningar page."
      },
      "CompanyProfileWriteFailedDto": {
        "required": [
          "error",
          "changed",
          "unchanged",
          "failed"
        ],
        "type": "object",
        "properties": {
          "error": {
            "type": "string",
            "description": "The Swedish sentence the assistant relays: nothing was saved, or only part was."
          },
          "changed": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CompanyProfileFieldChangeDto"
            },
            "description": "Fields whose stored value differs after the write — read back, not claimed."
          },
          "unchanged": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Fields the caller sent that already held that value."
          },
          "failed": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Fields the caller sent whose write was attempted and did not land."
          }
        },
        "description": "The body of the 500 the update answers when the settings write itself threw. It is a\n             real type rather than an ad-hoc object because the MCP tool hands this body straight to the\n             model, which relays it to the customer.\n\n             string CompanyProfileWriteFailedDto.Error is chosen from the read-back, not from the fact that something threw:\n             the commit can land and the connection drop on the way back, and a body that says \"could not be\n             saved\" beside a list of saved fields states something it cannot stand behind. The write is\n             idempotent, so retrying after either message is safe."
      },
      "CustomerAddressDto": {
        "required": [
          "id"
        ],
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "format": "int32"
          },
          "addressTypeId": {
            "type": "integer",
            "format": "int32"
          },
          "addressTypeName": {
            "type": [
              "null",
              "string"
            ]
          },
          "co": {
            "type": [
              "null",
              "string"
            ]
          },
          "name": {
            "type": [
              "null",
              "string"
            ]
          },
          "street": {
            "type": [
              "null",
              "string"
            ]
          },
          "street2": {
            "type": [
              "null",
              "string"
            ]
          },
          "postalCode": {
            "type": [
              "null",
              "string"
            ]
          },
          "city": {
            "type": [
              "null",
              "string"
            ]
          },
          "countryId": {
            "type": [
              "null",
              "integer"
            ],
            "format": "int32"
          }
        }
      },
      "CustomerAddressTypeOptionDto": {
        "required": [
          "id"
        ],
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "format": "int32"
          },
          "name": {
            "type": [
              "null",
              "string"
            ]
          },
          "isInvoiceAddress": {
            "type": "boolean"
          },
          "isDeliveryAddress": {
            "type": "boolean"
          }
        }
      },
      "CustomerAddressWriteDto": {
        "type": "object",
        "properties": {
          "co": {
            "type": [
              "null",
              "string"
            ],
            "description": "c/o line — e.g. the law firm administering a bankruptcy estate."
          },
          "name": {
            "type": [
              "null",
              "string"
            ],
            "description": "Addressee. Omit to use the customer's name."
          },
          "street": {
            "type": [
              "null",
              "string"
            ],
            "description": "Street or box, e.g. \"Box 27707\"."
          },
          "street2": {
            "type": [
              "null",
              "string"
            ]
          },
          "postalCode": {
            "type": [
              "null",
              "string"
            ]
          },
          "city": {
            "type": [
              "null",
              "string"
            ]
          },
          "countryId": {
            "type": [
              "null",
              "integer"
            ],
            "description": "Country id. Alternative: CountryName.",
            "format": "int32"
          },
          "countryName": {
            "type": [
              "null",
              "string"
            ],
            "description": "Country by name, e.g. \"Sverige\" — resolved case-insensitively; must\n            match exactly one country."
          }
        },
        "description": "An address to write. The address TYPE is not on this record — the caller\n            picks invoice vs delivery by which slot it goes in (or by AddressTypeId on the\n            standalone address endpoint)."
      },
      "CustomerCreatedDto": {
        "required": [
          "id"
        ],
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "format": "int32"
          },
          "contactNumber": {
            "type": [
              "null",
              "integer"
            ],
            "description": "The DB-assigned kundnummer.",
            "format": "int64"
          },
          "name": {
            "type": [
              "null",
              "string"
            ]
          },
          "applied": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Field names from the create payload that were written to the master\n            record. A field you passed that is missing here was NOT applied — check it."
          },
          "invoiceAddressId": {
            "type": [
              "null",
              "integer"
            ],
            "format": "int32"
          },
          "deliveryAddressId": {
            "type": [
              "null",
              "integer"
            ],
            "format": "int32"
          }
        }
      },
      "CustomerCreateDto": {
        "required": [
          "name"
        ],
        "type": "object",
        "properties": {
          "name": {
            "type": "string"
          },
          "orgno": {
            "type": [
              "null",
              "string"
            ],
            "description": "Organisation number. A bankruptcy estate keeps the debtor's org.nr, so\n            duplicates against an existing company are allowed and not deduplicated."
          },
          "vatno": {
            "type": [
              "null",
              "string"
            ],
            "description": "VAT/momsregistreringsnummer, e.g. SE556705279901."
          },
          "paymentTermId": {
            "type": [
              "null",
              "integer"
            ],
            "format": "int32"
          },
          "deliveryTermId": {
            "type": [
              "null",
              "integer"
            ],
            "format": "int32"
          },
          "currencyId": {
            "type": [
              "null",
              "integer"
            ],
            "description": "Currency id. Alternative: CurrencyIso.",
            "format": "int32"
          },
          "currencyIso": {
            "type": [
              "null",
              "string"
            ],
            "description": "Currency by ISO code, e.g. SEK — resolved case-insensitively."
          },
          "priceListId": {
            "type": [
              "null",
              "integer"
            ],
            "format": "int32"
          },
          "accVatTypeId": {
            "type": [
              "null",
              "integer"
            ],
            "description": "Momstyp id. Omit to leave unset, which makes orders fall back to the\n            tenant default.",
            "format": "int32"
          },
          "orderDiscount": {
            "type": [
              "null",
              "number"
            ],
            "format": "double"
          },
          "invoiceEmail": {
            "type": [
              "null",
              "string"
            ],
            "description": "Invoice e-mail. Requires the tenant to already have a Faktura/Invoice\n            e-mail address type in use."
          },
          "gln": {
            "type": [
              "null",
              "string"
            ],
            "description": "GLN — e-invoice routing address."
          },
          "invoiceTransport": {
            "type": [
              "null",
              "string"
            ],
            "description": "Allowed invoice transports, ';'-joined subset of\n            {Alla, E-faktura, E-post, Papper}."
          },
          "creditLimit": {
            "type": [
              "null",
              "number"
            ],
            "format": "double"
          },
          "creditBlock": {
            "type": [
              "null",
              "boolean"
            ]
          },
          "invoiceAddress": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "$ref": "#/components/schemas/CustomerAddressWriteDto"
              }
            ]
          },
          "deliveryAddress": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "$ref": "#/components/schemas/CustomerAddressWriteDto"
              }
            ]
          }
        },
        "description": "Create a customer. Only Name is required; every other field is applied in\n            the same call (create → master patch → addresses) so a caller needs one round-trip\n            rather than four. The response reports which fields were actually applied.\n            Ids for terms/currency/momstyp come from `GET api/v1/customers/lookups` —\n            currency and country may also be given by ISO code / name and are resolved here."
      },
      "CustomerDetailDto": {
        "required": [
          "id"
        ],
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "format": "int32"
          },
          "contactNumber": {
            "type": [
              "null",
              "integer"
            ],
            "format": "int32"
          },
          "name": {
            "type": [
              "null",
              "string"
            ]
          },
          "orgno": {
            "type": [
              "null",
              "string"
            ]
          },
          "creditLimit": {
            "type": [
              "null",
              "number"
            ],
            "format": "double"
          },
          "overdueOrderSum": {
            "type": [
              "null",
              "number"
            ],
            "format": "double"
          },
          "creditStop": {
            "type": [
              "null",
              "boolean"
            ]
          },
          "paymentTermId": {
            "type": [
              "null",
              "integer"
            ],
            "format": "int32"
          },
          "paymentTermName": {
            "type": [
              "null",
              "string"
            ]
          },
          "deliveryTermId": {
            "type": [
              "null",
              "integer"
            ],
            "format": "int32"
          },
          "deliveryTermName": {
            "type": [
              "null",
              "string"
            ]
          },
          "priceListId": {
            "type": [
              "null",
              "integer"
            ],
            "format": "int32"
          },
          "priceListName": {
            "type": [
              "null",
              "string"
            ]
          },
          "currencyId": {
            "type": [
              "null",
              "integer"
            ],
            "format": "int32"
          },
          "currencyIsoCode": {
            "type": [
              "null",
              "string"
            ]
          },
          "vatTypeId": {
            "type": [
              "null",
              "integer"
            ],
            "format": "int32"
          },
          "vatTypeName": {
            "type": [
              "null",
              "string"
            ]
          },
          "inactive": {
            "type": [
              "null",
              "boolean"
            ]
          },
          "orderCount": {
            "type": [
              "null",
              "integer"
            ],
            "format": "int32"
          }
        }
      },
      "CustomerDto": {
        "required": [
          "id"
        ],
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "format": "int32"
          },
          "contactNumber": {
            "type": [
              "null",
              "integer"
            ],
            "format": "int32"
          },
          "name": {
            "type": [
              "null",
              "string"
            ]
          },
          "orgno": {
            "type": [
              "null",
              "string"
            ]
          },
          "currencyIsoCode": {
            "type": [
              "null",
              "string"
            ]
          },
          "inactive": {
            "type": [
              "null",
              "boolean"
            ]
          },
          "openOrderCount": {
            "type": [
              "null",
              "integer"
            ],
            "format": "int32"
          }
        }
      },
      "CustomerLookupOptionDto": {
        "required": [
          "id"
        ],
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "format": "int32"
          },
          "name": {
            "type": [
              "null",
              "string"
            ]
          },
          "code": {
            "type": [
              "null",
              "string"
            ],
            "description": "ISO code for currencies; null for everything else."
          }
        }
      },
      "CustomerLookupsDto": {
        "type": "object",
        "properties": {
          "paymentTerms": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CustomerLookupOptionDto"
            }
          },
          "deliveryTerms": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CustomerLookupOptionDto"
            }
          },
          "currencies": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CustomerLookupOptionDto"
            }
          },
          "priceLists": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CustomerLookupOptionDto"
            }
          },
          "vatTypes": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CustomerLookupOptionDto"
            }
          },
          "addressTypes": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CustomerAddressTypeOptionDto"
            }
          },
          "countries": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CustomerLookupOptionDto"
            }
          }
        },
        "description": "Every id a customer write needs, in one call — there is no other way for a\n            caller to learn these tenant-specific ids."
      },
      "CustomerPatchDto": {
        "type": "object",
        "properties": {
          "name": {
            "type": [
              "null",
              "string"
            ]
          },
          "orgno": {
            "type": [
              "null",
              "string"
            ]
          },
          "vatno": {
            "type": [
              "null",
              "string"
            ]
          },
          "paymentTermId": {
            "type": [
              "null",
              "integer"
            ],
            "format": "int32"
          },
          "deliveryTermId": {
            "type": [
              "null",
              "integer"
            ],
            "format": "int32"
          },
          "currencyId": {
            "type": [
              "null",
              "integer"
            ],
            "format": "int32"
          },
          "currencyIso": {
            "type": [
              "null",
              "string"
            ]
          },
          "priceListId": {
            "type": [
              "null",
              "integer"
            ],
            "format": "int32"
          },
          "accVatTypeId": {
            "type": [
              "null",
              "integer"
            ],
            "format": "int32"
          },
          "orderDiscount": {
            "type": [
              "null",
              "number"
            ],
            "format": "double"
          },
          "invoiceEmail": {
            "type": [
              "null",
              "string"
            ]
          },
          "gln": {
            "type": [
              "null",
              "string"
            ]
          },
          "invoiceTransport": {
            "type": [
              "null",
              "string"
            ]
          },
          "creditLimit": {
            "type": [
              "null",
              "number"
            ],
            "format": "double"
          },
          "creditBlock": {
            "type": [
              "null",
              "boolean"
            ]
          },
          "inactive": {
            "type": [
              "null",
              "boolean"
            ]
          }
        },
        "description": "Partial customer update: null means \"leave the field as it is\", and an\n            empty string clears the text fields that support clearing (InvoiceEmail, Vatno,\n            Gln, InvoiceTransport). Name and Orgno cannot be cleared, only replaced."
      },
      "CustomerPatchResultDto": {
        "required": [
          "changed"
        ],
        "type": "object",
        "properties": {
          "changed": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        },
        "description": "The names of the fields the patch changed."
      },
      "DocumentContentDto": {
        "required": [
          "documentId"
        ],
        "type": "object",
        "properties": {
          "found": {
            "type": "boolean"
          },
          "documentId": {
            "type": "string"
          },
          "documentName": {
            "type": [
              "null",
              "string"
            ]
          },
          "mimeType": {
            "type": [
              "null",
              "string"
            ]
          },
          "folderPath": {
            "type": [
              "null",
              "string"
            ]
          },
          "content": {
            "type": [
              "null",
              "string"
            ]
          },
          "truncated": {
            "type": "boolean"
          }
        },
        "description": "Full extracted text of one document (capped server-side)."
      },
      "DocumentSearchHitDto": {
        "required": [
          "documentId",
          "documentName",
          "matchType"
        ],
        "type": "object",
        "properties": {
          "documentId": {
            "type": "string"
          },
          "documentName": {
            "type": "string"
          },
          "mimeType": {
            "type": [
              "null",
              "string"
            ]
          },
          "folderPath": {
            "type": [
              "null",
              "string"
            ]
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          },
          "snippet": {
            "type": [
              "null",
              "string"
            ]
          },
          "matchType": {
            "type": "string"
          }
        },
        "description": "One document search hit. `MatchType` = \"content\" | \"name\"."
      },
      "ErrorEnvelope": {
        "required": [
          "code",
          "message"
        ],
        "type": "object",
        "properties": {
          "code": {
            "type": "string"
          },
          "message": {
            "type": "string"
          },
          "traceId": {
            "type": [
              "null",
              "string"
            ]
          },
          "details": {
            "type": "object"
          }
        }
      },
      "ErrorEnvelopeWithRows": {
        "required": [
          "code",
          "message",
          "rowErrors"
        ],
        "type": "object",
        "properties": {
          "code": {
            "type": "string"
          },
          "message": {
            "type": "string"
          },
          "traceId": {
            "type": [
              "null",
              "string"
            ]
          },
          "rowErrors": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/RowErrorDto"
            }
          }
        },
        "description": "An ErrorEnvelope that also says which rows of a bulk request were refused (additive)."
      },
      "ErrorMessageBody": {
        "required": [
          "error"
        ],
        "type": "object",
        "properties": {
          "error": {
            "type": "string"
          }
        },
        "description": "A refusal with a human-readable reason in `error`."
      },
      "IdResultDto": {
        "required": [
          "id"
        ],
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "format": "int32"
          }
        },
        "description": "The id of the row the write created or saved."
      },
      "JoinableLookupDto": {
        "required": [
          "joinKey",
          "onColumn",
          "report",
          "columns"
        ],
        "type": "object",
        "properties": {
          "joinKey": {
            "type": "string"
          },
          "onColumn": {
            "type": "string"
          },
          "report": {
            "type": "string"
          },
          "columns": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ReportColumnDto"
            }
          }
        },
        "description": "A lookup report joinable onto a base column, with the columns it would add."
      },
      "JsonElement": { },
      "KanbanBoardColumnDto": {
        "required": [
          "tagItemId"
        ],
        "type": "object",
        "properties": {
          "tagItemId": {
            "type": "integer",
            "format": "int32"
          },
          "name": {
            "type": [
              "null",
              "string"
            ]
          },
          "sort": {
            "type": "integer",
            "format": "int16"
          },
          "isDefault": {
            "type": "boolean"
          },
          "isFinished": {
            "type": "boolean"
          }
        }
      },
      "KanbanBoardDto": {
        "required": [
          "id"
        ],
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "format": "int32"
          },
          "name": {
            "type": [
              "null",
              "string"
            ]
          },
          "description": {
            "type": [
              "null",
              "string"
            ]
          },
          "icon": {
            "type": [
              "null",
              "string"
            ]
          },
          "colorCode": {
            "type": [
              "null",
              "string"
            ]
          },
          "activityTypeId": {
            "type": "integer",
            "format": "int32"
          },
          "activityTypeName": {
            "type": [
              "null",
              "string"
            ]
          },
          "tagId": {
            "type": "integer",
            "format": "int32"
          },
          "tagName": {
            "type": [
              "null",
              "string"
            ]
          },
          "defaultColumn": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "$ref": "#/components/schemas/KanbanBoardColumnDto"
              }
            ]
          },
          "finishedColumn": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "$ref": "#/components/schemas/KanbanBoardColumnDto"
              }
            ]
          },
          "columns": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/KanbanBoardColumnDto"
            }
          },
          "wipLimits": {
            "type": [
              "null",
              "object"
            ],
            "additionalProperties": {
              "type": "integer",
              "format": "int32"
            },
            "description": "Per-column WIP limit keyed by column tag-item id. Soft limit — UI warning only."
          },
          "colorTagId": {
            "type": [
              "null",
              "integer"
            ],
            "description": "Tag-group (CrmActivityTag) id whose item colour drives the card top stripe. null = no stripe.",
            "format": "int32"
          }
        },
        "description": "A saved, shared-per-instance kanban board. Columns are derived live from the\n            tag's items — never stored. `defaultColumn`/`finishedColumn` are null when unset."
      },
      "KanbanBoardSaveDto": {
        "required": [
          "name",
          "activityTypeId",
          "activityTagId"
        ],
        "type": "object",
        "properties": {
          "name": {
            "type": "string"
          },
          "description": {
            "type": [
              "null",
              "string"
            ]
          },
          "icon": {
            "type": [
              "null",
              "string"
            ]
          },
          "colorCode": {
            "type": [
              "null",
              "string"
            ]
          },
          "activityTypeId": {
            "type": "integer",
            "format": "int32"
          },
          "activityTagId": {
            "type": "integer",
            "format": "int32"
          },
          "defaultTagItemId": {
            "type": [
              "null",
              "integer"
            ],
            "format": "int32"
          },
          "finishedTagItemId": {
            "type": [
              "null",
              "integer"
            ],
            "format": "int32"
          },
          "wipLimits": {
            "type": [
              "null",
              "object"
            ],
            "additionalProperties": {
              "type": "integer",
              "format": "int32"
            },
            "description": "Per-column WIP limit keyed by column tag-item id. Soft limit — UI warning only."
          },
          "colorTagId": {
            "type": [
              "null",
              "integer"
            ],
            "description": "Tag-group (CrmActivityTag) id whose item colour drives the card top stripe. null = no stripe.",
            "format": "int32"
          }
        },
        "description": "Create (id omitted/0) or full-replace update of a kanban board."
      },
      "KanbanCardAddDto": {
        "required": [
          "board",
          "description"
        ],
        "type": "object",
        "properties": {
          "board": {
            "type": "string"
          },
          "column": {
            "type": [
              "null",
              "string"
            ]
          },
          "description": {
            "type": "string"
          },
          "date": {
            "type": [
              "null",
              "string"
            ],
            "format": "date-time"
          },
          "personId": {
            "type": [
              "null",
              "integer"
            ],
            "format": "int32"
          }
        },
        "description": "Add a new activity as a card on a board. `Board`/`Column` accept an id\n            (as a string) OR a case-insensitive name. Omit `Column` to use the board's default column."
      },
      "KanbanCardFinishDto": {
        "required": [
          "board",
          "activityId"
        ],
        "type": "object",
        "properties": {
          "board": {
            "type": "string"
          },
          "activityId": {
            "type": "integer",
            "format": "int32"
          }
        }
      },
      "KanbanCardMoveDto": {
        "required": [
          "board",
          "activityId",
          "column"
        ],
        "type": "object",
        "properties": {
          "board": {
            "type": "string"
          },
          "activityId": {
            "type": "integer",
            "format": "int32"
          },
          "column": {
            "type": "string"
          }
        }
      },
      "MomsrapportRowDto": {
        "required": [
          "code"
        ],
        "type": "object",
        "properties": {
          "code": {
            "type": "string"
          },
          "accounts": {
            "type": [
              "null",
              "string"
            ]
          }
        },
        "description": "Momsdeklaration ruta → accounts (semicolon-separated account codes)."
      },
      "OpenOrderLineDto": {
        "required": [
          "orderId",
          "lineId"
        ],
        "type": "object",
        "properties": {
          "orderId": {
            "type": "integer",
            "format": "int32"
          },
          "orderName": {
            "type": [
              "null",
              "string"
            ]
          },
          "lineId": {
            "type": "integer",
            "format": "int32"
          },
          "productId": {
            "type": [
              "null",
              "integer"
            ],
            "format": "int32"
          },
          "productNumber": {
            "type": [
              "null",
              "string"
            ]
          },
          "description": {
            "type": [
              "null",
              "string"
            ]
          },
          "qtyOrdered": {
            "type": "number",
            "format": "double"
          },
          "qtyDelivered": {
            "type": "number",
            "format": "double"
          },
          "qtyLeftToDeliver": {
            "type": "number",
            "format": "double"
          },
          "dateOrder": {
            "type": [
              "null",
              "string"
            ],
            "format": "date-time"
          },
          "dateDelivery": {
            "type": [
              "null",
              "string"
            ],
            "format": "date-time"
          },
          "customerId": {
            "type": [
              "null",
              "integer"
            ],
            "format": "int32"
          },
          "customerName": {
            "type": [
              "null",
              "string"
            ]
          },
          "statusId": {
            "type": [
              "null",
              "integer"
            ],
            "format": "int32"
          },
          "statusName": {
            "type": [
              "null",
              "string"
            ]
          }
        }
      },
      "PageResponseOfActivityDto": {
        "required": [
          "items",
          "pageSizeApplied"
        ],
        "type": "object",
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ActivityDto"
            }
          },
          "nextCursor": {
            "type": [
              "null",
              "string"
            ]
          },
          "pageSizeApplied": {
            "type": "integer",
            "format": "int32"
          },
          "truncated": {
            "type": "boolean"
          }
        }
      },
      "PageResponseOfActivityTimelineEntryDto": {
        "required": [
          "items",
          "pageSizeApplied"
        ],
        "type": "object",
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ActivityTimelineEntryDto"
            }
          },
          "nextCursor": {
            "type": [
              "null",
              "string"
            ]
          },
          "pageSizeApplied": {
            "type": "integer",
            "format": "int32"
          },
          "truncated": {
            "type": "boolean"
          }
        }
      },
      "PageResponseOfBrandListItemDto": {
        "required": [
          "items",
          "pageSizeApplied"
        ],
        "type": "object",
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/BrandListItemDto"
            }
          },
          "nextCursor": {
            "type": [
              "null",
              "string"
            ]
          },
          "pageSizeApplied": {
            "type": "integer",
            "format": "int32"
          },
          "truncated": {
            "type": "boolean"
          }
        }
      },
      "PageResponseOfCodeMatchDto": {
        "required": [
          "items",
          "pageSizeApplied"
        ],
        "type": "object",
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CodeMatchDto"
            }
          },
          "nextCursor": {
            "type": [
              "null",
              "string"
            ]
          },
          "pageSizeApplied": {
            "type": "integer",
            "format": "int32"
          },
          "truncated": {
            "type": "boolean"
          }
        }
      },
      "PageResponseOfCustomerDto": {
        "required": [
          "items",
          "pageSizeApplied"
        ],
        "type": "object",
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CustomerDto"
            }
          },
          "nextCursor": {
            "type": [
              "null",
              "string"
            ]
          },
          "pageSizeApplied": {
            "type": "integer",
            "format": "int32"
          },
          "truncated": {
            "type": "boolean"
          }
        }
      },
      "PageResponseOfOpenOrderLineDto": {
        "required": [
          "items",
          "pageSizeApplied"
        ],
        "type": "object",
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/OpenOrderLineDto"
            }
          },
          "nextCursor": {
            "type": [
              "null",
              "string"
            ]
          },
          "pageSizeApplied": {
            "type": "integer",
            "format": "int32"
          },
          "truncated": {
            "type": "boolean"
          }
        }
      },
      "PageResponseOfPartyListItemDto": {
        "required": [
          "items",
          "pageSizeApplied"
        ],
        "type": "object",
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PartyListItemDto"
            }
          },
          "nextCursor": {
            "type": [
              "null",
              "string"
            ]
          },
          "pageSizeApplied": {
            "type": "integer",
            "format": "int32"
          },
          "truncated": {
            "type": "boolean"
          }
        }
      },
      "PageResponseOfProductCategoryDto": {
        "required": [
          "items",
          "pageSizeApplied"
        ],
        "type": "object",
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ProductCategoryDto"
            }
          },
          "nextCursor": {
            "type": [
              "null",
              "string"
            ]
          },
          "pageSizeApplied": {
            "type": "integer",
            "format": "int32"
          },
          "truncated": {
            "type": "boolean"
          }
        }
      },
      "PageResponseOfProductCodeDto": {
        "required": [
          "items",
          "pageSizeApplied"
        ],
        "type": "object",
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ProductCodeDto"
            }
          },
          "nextCursor": {
            "type": [
              "null",
              "string"
            ]
          },
          "pageSizeApplied": {
            "type": "integer",
            "format": "int32"
          },
          "truncated": {
            "type": "boolean"
          }
        }
      },
      "PageResponseOfProductSearchRowDto": {
        "required": [
          "items",
          "pageSizeApplied"
        ],
        "type": "object",
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ProductSearchRowDto"
            }
          },
          "nextCursor": {
            "type": [
              "null",
              "string"
            ]
          },
          "pageSizeApplied": {
            "type": "integer",
            "format": "int32"
          },
          "truncated": {
            "type": "boolean"
          }
        }
      },
      "PageResponseOfProductTextsDto": {
        "required": [
          "items",
          "pageSizeApplied"
        ],
        "type": "object",
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ProductTextsDto"
            }
          },
          "nextCursor": {
            "type": [
              "null",
              "string"
            ]
          },
          "pageSizeApplied": {
            "type": "integer",
            "format": "int32"
          },
          "truncated": {
            "type": "boolean"
          }
        }
      },
      "PageResponseOfProductValuesDto": {
        "required": [
          "items",
          "pageSizeApplied"
        ],
        "type": "object",
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ProductValuesDto"
            }
          },
          "nextCursor": {
            "type": [
              "null",
              "string"
            ]
          },
          "pageSizeApplied": {
            "type": "integer",
            "format": "int32"
          },
          "truncated": {
            "type": "boolean"
          }
        }
      },
      "PageResponseOfProposalBatchDto": {
        "required": [
          "items",
          "pageSizeApplied"
        ],
        "type": "object",
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ProposalBatchDto"
            }
          },
          "nextCursor": {
            "type": [
              "null",
              "string"
            ]
          },
          "pageSizeApplied": {
            "type": "integer",
            "format": "int32"
          },
          "truncated": {
            "type": "boolean"
          }
        }
      },
      "PageResponseOfProposalLineDto": {
        "required": [
          "items",
          "pageSizeApplied"
        ],
        "type": "object",
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ProposalLineDto"
            }
          },
          "nextCursor": {
            "type": [
              "null",
              "string"
            ]
          },
          "pageSizeApplied": {
            "type": "integer",
            "format": "int32"
          },
          "truncated": {
            "type": "boolean"
          }
        }
      },
      "PageResponseOfPurchaseOrderDto": {
        "required": [
          "items",
          "pageSizeApplied"
        ],
        "type": "object",
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PurchaseOrderDto"
            }
          },
          "nextCursor": {
            "type": [
              "null",
              "string"
            ]
          },
          "pageSizeApplied": {
            "type": "integer",
            "format": "int32"
          },
          "truncated": {
            "type": "boolean"
          }
        }
      },
      "PageResponseOfSalesInvoiceDto": {
        "required": [
          "items",
          "pageSizeApplied"
        ],
        "type": "object",
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SalesInvoiceDto"
            }
          },
          "nextCursor": {
            "type": [
              "null",
              "string"
            ]
          },
          "pageSizeApplied": {
            "type": "integer",
            "format": "int32"
          },
          "truncated": {
            "type": "boolean"
          }
        }
      },
      "PageResponseOfSalesInvoiceLineDto": {
        "required": [
          "items",
          "pageSizeApplied"
        ],
        "type": "object",
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SalesInvoiceLineDto"
            }
          },
          "nextCursor": {
            "type": [
              "null",
              "string"
            ]
          },
          "pageSizeApplied": {
            "type": "integer",
            "format": "int32"
          },
          "truncated": {
            "type": "boolean"
          }
        }
      },
      "PageResponseOfSalesOrderDto": {
        "required": [
          "items",
          "pageSizeApplied"
        ],
        "type": "object",
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SalesOrderDto"
            }
          },
          "nextCursor": {
            "type": [
              "null",
              "string"
            ]
          },
          "pageSizeApplied": {
            "type": "integer",
            "format": "int32"
          },
          "truncated": {
            "type": "boolean"
          }
        }
      },
      "PageResponseOfVendorPriceDto": {
        "required": [
          "items",
          "pageSizeApplied"
        ],
        "type": "object",
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/VendorPriceDto"
            }
          },
          "nextCursor": {
            "type": [
              "null",
              "string"
            ]
          },
          "pageSizeApplied": {
            "type": "integer",
            "format": "int32"
          },
          "truncated": {
            "type": "boolean"
          }
        }
      },
      "PageResponseOfWarehouseStockRowDto": {
        "required": [
          "items",
          "pageSizeApplied"
        ],
        "type": "object",
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WarehouseStockRowDto"
            }
          },
          "nextCursor": {
            "type": [
              "null",
              "string"
            ]
          },
          "pageSizeApplied": {
            "type": "integer",
            "format": "int32"
          },
          "truncated": {
            "type": "boolean"
          }
        }
      },
      "ParseResultDto": {
        "required": [
          "input",
          "mode",
          "outcome",
          "type",
          "eligibleByCode",
          "candidates",
          "warnings"
        ],
        "type": "object",
        "properties": {
          "input": {
            "type": "string"
          },
          "mode": {
            "type": "string",
            "description": "bare, ean_upc, bracketed_ai, scanner_ai or digital_link."
          },
          "outcome": {
            "type": "string",
            "description": "valid, repaired, ambiguous or invalid."
          },
          "type": {
            "type": "string"
          },
          "value": {
            "type": [
              "null",
              "string"
            ]
          },
          "matchKey": {
            "type": [
              "null",
              "string"
            ]
          },
          "format": {
            "type": [
              "null",
              "integer"
            ],
            "format": "int32"
          },
          "category": {
            "type": [
              "null",
              "string"
            ]
          },
          "eligibleByCode": {
            "type": "boolean",
            "description": "Whether format and category could be published; not the full §13.1 predicate."
          },
          "addon": {
            "type": [
              "null",
              "string"
            ]
          },
          "candidates": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CodeCandidateDto"
            },
            "description": "Set when ambiguous: send one candidate's matchKey back as `choice` with the same `code`."
          },
          "warnings": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CodeWarningDto"
            }
          },
          "reason": {
            "type": [
              "null",
              "string"
            ]
          },
          "message": {
            "type": [
              "null",
              "string"
            ],
            "description": "Swedish text for the reason."
          }
        },
        "description": "What the parser made of an input (spec §5.1)."
      },
      "PartyContactDto": {
        "required": [
          "id",
          "legalName",
          "countryCode",
          "status"
        ],
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "format": "int32"
          },
          "legalName": {
            "type": "string"
          },
          "tradeName": {
            "type": [
              "null",
              "string"
            ]
          },
          "street": {
            "type": [
              "null",
              "string"
            ]
          },
          "postalCode": {
            "type": [
              "null",
              "string"
            ]
          },
          "city": {
            "type": [
              "null",
              "string"
            ]
          },
          "region": {
            "type": [
              "null",
              "string"
            ]
          },
          "countryCode": {
            "type": "string"
          },
          "email": {
            "type": [
              "null",
              "string"
            ]
          },
          "contactUrl": {
            "type": [
              "null",
              "string"
            ]
          },
          "phone": {
            "type": [
              "null",
              "string"
            ]
          },
          "publishPhone": {
            "type": "boolean"
          },
          "status": {
            "type": "string"
          }
        },
        "description": "A resolved party with its address and contacts (the publication contact data the shop shows)."
      },
      "PartyCreateDto": {
        "type": "object",
        "properties": {
          "legalName": {
            "type": [
              "null",
              "string"
            ]
          },
          "tradeName": {
            "type": [
              "null",
              "string"
            ]
          },
          "street": {
            "type": [
              "null",
              "string"
            ]
          },
          "postalCode": {
            "type": [
              "null",
              "string"
            ]
          },
          "city": {
            "type": [
              "null",
              "string"
            ]
          },
          "region": {
            "type": [
              "null",
              "string"
            ]
          },
          "countryCode": {
            "type": [
              "null",
              "string"
            ]
          },
          "email": {
            "type": [
              "null",
              "string"
            ]
          },
          "contactUrl": {
            "type": [
              "null",
              "string"
            ]
          },
          "phone": {
            "type": [
              "null",
              "string"
            ]
          },
          "publishPhone": {
            "type": [
              "null",
              "boolean"
            ]
          },
          "registrationNo": {
            "type": [
              "null",
              "string"
            ]
          },
          "extId": {
            "type": [
              "null",
              "string"
            ]
          },
          "status": {
            "type": [
              "null",
              "string"
            ]
          }
        },
        "description": "`legalName` and `countryCode` are required; everything else is optional. Values are trimmed; blank is null."
      },
      "PartyDto": {
        "required": [
          "id",
          "legalName",
          "countryCode",
          "status",
          "usedBy",
          "version",
          "createdAt",
          "updatedAt"
        ],
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "format": "int32"
          },
          "legalName": {
            "type": "string"
          },
          "tradeName": {
            "type": [
              "null",
              "string"
            ]
          },
          "street": {
            "type": [
              "null",
              "string"
            ]
          },
          "postalCode": {
            "type": [
              "null",
              "string"
            ]
          },
          "city": {
            "type": [
              "null",
              "string"
            ]
          },
          "region": {
            "type": [
              "null",
              "string"
            ]
          },
          "countryCode": {
            "type": "string"
          },
          "email": {
            "type": [
              "null",
              "string"
            ]
          },
          "contactUrl": {
            "type": [
              "null",
              "string"
            ]
          },
          "phone": {
            "type": [
              "null",
              "string"
            ]
          },
          "publishPhone": {
            "type": "boolean"
          },
          "registrationNo": {
            "type": [
              "null",
              "string"
            ]
          },
          "extId": {
            "type": [
              "null",
              "string"
            ]
          },
          "status": {
            "type": "string"
          },
          "usedBy": {
            "$ref": "#/components/schemas/PartyUsedByDto"
          },
          "warnings": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "POSTAL_ADDRESS_INCOMPLETE, ELECTRONIC_ADDRESS_MISSING, POSSIBLE_DUPLICATE, ARCHIVED_ASSIGNED (an open set). Never blocking."
          },
          "version": {
            "type": "integer",
            "format": "int32"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          }
        },
        "description": "One party with its address and contacts. A party may be a natural person, so these are contact coordinates (conventions\n            rule 3). The name, address, e-mail and URL are published on product pages that resolve to the party; the phone only when\n            bool PartyDto.PublishPhone is set."
      },
      "PartyListItemDto": {
        "required": [
          "id",
          "legalName",
          "countryCode",
          "status"
        ],
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "format": "int32"
          },
          "legalName": {
            "type": "string"
          },
          "tradeName": {
            "type": [
              "null",
              "string"
            ]
          },
          "countryCode": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "description": "`active` or `archived` (an open set)."
          },
          "warnings": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "POSTAL_ADDRESS_INCOMPLETE, ELECTRONIC_ADDRESS_MISSING, POSSIBLE_DUPLICATE, ARCHIVED_ASSIGNED (an open set), judged against\n            the whole tenant (a duplicate's twin may be on another page or in another status). Never blocking; an empty list never means\n            \"compliant\"."
          }
        },
        "description": "A party in a list. No contact coordinates (conventions rule 3): read one party for its address and contacts."
      },
      "PartyPatchDto": {
        "type": "object",
        "properties": {
          "version": {
            "type": [
              "null",
              "integer"
            ],
            "format": "int32"
          },
          "legalName": {
            "type": [
              "null",
              "string"
            ]
          },
          "tradeName": {
            "type": [
              "null",
              "string"
            ]
          },
          "street": {
            "type": [
              "null",
              "string"
            ]
          },
          "postalCode": {
            "type": [
              "null",
              "string"
            ]
          },
          "city": {
            "type": [
              "null",
              "string"
            ]
          },
          "region": {
            "type": [
              "null",
              "string"
            ]
          },
          "countryCode": {
            "type": [
              "null",
              "string"
            ]
          },
          "email": {
            "type": [
              "null",
              "string"
            ]
          },
          "contactUrl": {
            "type": [
              "null",
              "string"
            ]
          },
          "phone": {
            "type": [
              "null",
              "string"
            ]
          },
          "publishPhone": {
            "type": [
              "null",
              "boolean"
            ]
          },
          "registrationNo": {
            "type": [
              "null",
              "string"
            ]
          },
          "extId": {
            "type": [
              "null",
              "string"
            ]
          },
          "status": {
            "type": [
              "null",
              "string"
            ]
          }
        },
        "description": "A field left out (or null) is unchanged; an empty string clears an optional field. `legalName` and\n            `countryCode` cannot be cleared. `version` is required: the version you read."
      },
      "PartySummaryDto": {
        "required": [
          "id",
          "legalName",
          "countryCode",
          "status"
        ],
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "format": "int32"
          },
          "legalName": {
            "type": "string"
          },
          "tradeName": {
            "type": [
              "null",
              "string"
            ]
          },
          "countryCode": {
            "type": "string"
          },
          "status": {
            "type": "string"
          }
        },
        "description": "A party where another object names it (a brand role). The same fields as a list item."
      },
      "PartyUsedByBrandDto": {
        "required": [
          "brandId",
          "name",
          "role"
        ],
        "type": "object",
        "properties": {
          "brandId": {
            "type": "integer",
            "format": "int32"
          },
          "name": {
            "type": "string"
          },
          "role": {
            "type": "string"
          }
        }
      },
      "PartyUsedByDto": {
        "required": [
          "brandCount",
          "productOverrideCount"
        ],
        "type": "object",
        "properties": {
          "brands": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PartyUsedByBrandDto"
            }
          },
          "brandCount": {
            "type": "integer",
            "format": "int32"
          },
          "productOverrideCount": {
            "type": "integer",
            "format": "int32"
          }
        },
        "description": "Direct rows only: the brands whose defaults name the party (first 50), and how many product overrides name it. Inherited\n            use is not counted. The override count may include a product deleted since the last daily clean-up."
      },
      "ProblemDetails": {
        "type": "object",
        "properties": {
          "type": {
            "type": [
              "null",
              "string"
            ]
          },
          "title": {
            "type": [
              "null",
              "string"
            ]
          },
          "status": {
            "type": [
              "null",
              "integer"
            ],
            "format": "int32"
          },
          "detail": {
            "type": [
              "null",
              "string"
            ]
          },
          "instance": {
            "type": [
              "null",
              "string"
            ]
          }
        }
      },
      "ProductAccountSettingDto": {
        "required": [
          "id",
          "productGroupId",
          "vatTypeId",
          "vatCodeId"
        ],
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "format": "int32"
          },
          "name": {
            "type": [
              "null",
              "string"
            ]
          },
          "productGroupId": {
            "type": "integer",
            "format": "int32"
          },
          "productGroupName": {
            "type": [
              "null",
              "string"
            ]
          },
          "vatTypeId": {
            "type": "integer",
            "format": "int32"
          },
          "vatTypeName": {
            "type": [
              "null",
              "string"
            ]
          },
          "vatCodeId": {
            "type": "integer",
            "description": "0 = legacy \"unspecified rate\" row.",
            "format": "int32"
          },
          "vatRate": {
            "type": [
              "null",
              "number"
            ],
            "format": "double"
          },
          "salesAccount": {
            "type": [
              "null",
              "string"
            ]
          },
          "purchaseAccount": {
            "type": [
              "null",
              "string"
            ]
          },
          "creditSalesAccount": {
            "type": [
              "null",
              "string"
            ]
          },
          "creditPurchaseAccount": {
            "type": [
              "null",
              "string"
            ]
          }
        },
        "description": "One produktgrupp × momstyp × momssats row: revenue/cost accounts (and credit variants)."
      },
      "ProductBrandDto": {
        "required": [
          "productId",
          "effectiveMainId",
          "stored",
          "resolved"
        ],
        "type": "object",
        "properties": {
          "productId": {
            "type": "integer",
            "format": "int32"
          },
          "effectiveMainId": {
            "type": "integer",
            "description": "The product itself for a main or standalone product (also when its main no longer exists).",
            "format": "int32"
          },
          "stored": {
            "$ref": "#/components/schemas/ProductBrandStoredDto"
          },
          "resolved": {
            "$ref": "#/components/schemas/ProductBrandResolvedDto"
          },
          "warnings": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "MANUFACTURER_MISSING, MANUFACTURER_CONTACT_INCOMPLETE, EU_RESPONSIBLE_MISSING, EU_RESPONSIBLE_OUTSIDE_EU,\n            EU_RESPONSIBLE_CONTACT_INCOMPLETE (an open set). Never blocking, and their absence never means \"compliant\"."
          }
        },
        "description": "GET /api/v1/products/{id}/brand (spec §5.3): what the product stores and what resolves, with sources. Data from the Documents\n            database, so a sub-resource (conventions rule 1)."
      },
      "ProductBrandResolvedDto": {
        "required": [
          "brand"
        ],
        "type": "object",
        "properties": {
          "brand": {
            "$ref": "#/components/schemas/ResolvedBrandDto"
          },
          "parties": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ResolvedPartyDto"
            }
          }
        },
        "description": "`parties` always has one entry per role."
      },
      "ProductBrandStoredDto": {
        "required": [
          "brand"
        ],
        "type": "object",
        "properties": {
          "brand": {
            "$ref": "#/components/schemas/StoredBrandDto"
          },
          "parties": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/StoredPartyDto"
            }
          }
        },
        "description": "`parties` lists only the roles the product stores (a value or none); a role that is absent inherits."
      },
      "ProductBulkChangeDto": {
        "required": [
          "field"
        ],
        "type": "object",
        "properties": {
          "field": {
            "type": "string"
          },
          "lang": {
            "type": [
              "null",
              "string"
            ]
          },
          "from": {
            "type": [
              "null",
              "string"
            ]
          },
          "to": {
            "type": [
              "null",
              "string"
            ]
          },
          "fromLength": {
            "type": [
              "null",
              "integer"
            ],
            "format": "int32"
          },
          "toLength": {
            "type": [
              "null",
              "integer"
            ],
            "format": "int32"
          },
          "diffOmitted": {
            "type": "boolean"
          }
        },
        "description": "`From`/`To` null means no row (or, with `DiffOmitted`, the diff budget was spent)."
      },
      "ProductBulkErrorDto": {
        "required": [
          "code",
          "message",
          "field",
          "lang"
        ],
        "type": "object",
        "properties": {
          "code": {
            "type": "string"
          },
          "message": {
            "type": "string"
          },
          "field": {
            "type": [
              "null",
              "string"
            ]
          },
          "lang": {
            "type": [
              "null",
              "string"
            ]
          }
        }
      },
      "ProductBulkItemDto": {
        "type": "object",
        "properties": {
          "productId": {
            "type": [
              "null",
              "integer"
            ],
            "format": "int32"
          },
          "productNumber": {
            "type": [
              "null",
              "string"
            ]
          },
          "set": {
            "type": [
              "null",
              "array"
            ],
            "items": {
              "$ref": "#/components/schemas/ProductBulkSetDto"
            }
          }
        }
      },
      "ProductBulkItemResultDto": {
        "required": [
          "status"
        ],
        "type": "object",
        "properties": {
          "productId": {
            "type": [
              "null",
              "integer"
            ],
            "format": "int32"
          },
          "productNumber": {
            "type": [
              "null",
              "string"
            ]
          },
          "status": {
            "type": "string",
            "description": "`planned`, `applied`, `unchanged` or `failed`."
          },
          "changes": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ProductBulkChangeDto"
            }
          },
          "warnings": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ProductBulkWarningDto"
            }
          },
          "error": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "$ref": "#/components/schemas/ProductBulkErrorDto"
              }
            ]
          }
        }
      },
      "ProductBulkResultDto": {
        "type": "object",
        "properties": {
          "applied": {
            "type": [
              "null",
              "integer"
            ],
            "description": "Update only.",
            "format": "int32"
          },
          "planned": {
            "type": [
              "null",
              "integer"
            ],
            "description": "Preview only.",
            "format": "int32"
          },
          "unchanged": {
            "type": "integer",
            "format": "int32"
          },
          "failed": {
            "type": "integer",
            "format": "int32"
          },
          "correlationId": {
            "type": [
              "null",
              "string"
            ]
          },
          "diffBudgetExhausted": {
            "type": "boolean"
          },
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ProductBulkItemResultDto"
            }
          }
        }
      },
      "ProductBulkSetDto": {
        "type": "object",
        "properties": {
          "field": {
            "type": [
              "null",
              "string"
            ]
          },
          "lang": {
            "type": [
              "null",
              "string"
            ]
          },
          "value": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "$ref": "#/components/schemas/ProductBulkValue"
              }
            ]
          },
          "op": {
            "type": [
              "null",
              "string"
            ]
          },
          "allowNew": {
            "type": [
              "null",
              "boolean"
            ]
          }
        },
        "description": "Roadmap §5.1. `value``\"\"` clears (D7), as does `op: \"clear\"` (then without a value).\n            `op`: set (default), add, remove (lists only), clear. `allowNew`: accept a value not yet in use (200/201)."
      },
      "ProductBulkUpdateRequestDto": {
        "type": "object",
        "properties": {
          "items": {
            "type": [
              "null",
              "array"
            ],
            "items": {
              "$ref": "#/components/schemas/ProductBulkItemDto"
            }
          }
        },
        "description": "Preview and update take the same body."
      },
      "ProductBulkValue": {
        "description": "Any JSON value: a string, number, boolean, array or object. The field's kind decides how it is read; see GET /api/v1/products/fields."
      },
      "ProductBulkWarningDto": {
        "required": [
          "code",
          "field",
          "lang"
        ],
        "type": "object",
        "properties": {
          "code": {
            "type": "string"
          },
          "field": {
            "type": [
              "null",
              "string"
            ]
          },
          "lang": {
            "type": [
              "null",
              "string"
            ]
          },
          "details": {
            "type": [
              "null",
              "string"
            ]
          }
        },
        "description": "Roadmap §5.4: string? ProductBulkWarningDto.Details is optional context (≤ 300, counted in the diff budget); null is omitted."
      },
      "ProductCategoriesSectionDto": {
        "required": [
          "status"
        ],
        "type": "object",
        "properties": {
          "memberships": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ProductCategoryMembershipDto"
            }
          },
          "status": {
            "type": "string"
          }
        }
      },
      "ProductCategoryDto": {
        "required": [
          "id",
          "name"
        ],
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "format": "int32"
          },
          "parentId": {
            "type": [
              "null",
              "integer"
            ],
            "format": "int32"
          },
          "rootId": {
            "type": [
              "null",
              "integer"
            ],
            "description": "The top-level category above it (itself for a root); null when its parent chain is a cycle.",
            "format": "int32"
          },
          "name": {
            "type": "string"
          },
          "path": {
            "type": [
              "null",
              "string"
            ],
            "description": "\"Root &gt; … &gt; Category\"; null for a cycle."
          },
          "active": {
            "type": "boolean",
            "description": "Its own flag."
          },
          "activeInTree": {
            "type": "boolean",
            "description": "It and every parent active: what a category write needs."
          },
          "productCount": {
            "type": "integer",
            "description": "Products linked to it directly.",
            "format": "int32"
          },
          "field": {
            "type": [
              "null",
              "string"
            ],
            "description": "The field that writes memberships here: category:&lt;RootId&gt;."
          }
        },
        "description": "list_product_categories (roadmap §6.2): one category of the tree."
      },
      "ProductCategoryMembershipDto": {
        "required": [
          "categoryId",
          "name"
        ],
        "type": "object",
        "properties": {
          "categoryId": {
            "type": "integer",
            "format": "int32"
          },
          "name": {
            "type": "string"
          },
          "rootId": {
            "type": [
              "null",
              "integer"
            ],
            "format": "int32"
          },
          "path": {
            "type": [
              "null",
              "string"
            ]
          },
          "activeInTree": {
            "type": "boolean"
          },
          "rootOnly": {
            "type": "boolean"
          },
          "field": {
            "type": [
              "null",
              "string"
            ],
            "description": "The category:&lt;RootId&gt; field that writes it."
          }
        },
        "description": "A stored direct membership. bool ProductCategoryMembershipDto.RootOnly: a link to a top-level category itself (no shop effect)."
      },
      "ProductCategoryRefDto": {
        "required": [
          "id",
          "name",
          "active"
        ],
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "format": "int32"
          },
          "name": {
            "type": "string"
          },
          "active": {
            "type": "boolean"
          }
        },
        "description": "A category inside a value: id, name, and whether it and every parent are active."
      },
      "ProductCodeAddDto": {
        "type": "object",
        "properties": {
          "code": {
            "type": [
              "null",
              "string"
            ]
          },
          "type": {
            "type": [
              "null",
              "string"
            ],
            "description": "gtin (default) or local. A failed GTIN is never saved as local by itself."
          },
          "choice": {
            "type": [
              "null",
              "string"
            ]
          },
          "isMain": {
            "type": [
              "null",
              "boolean"
            ]
          },
          "quantity": {
            "type": [
              "null",
              "integer"
            ],
            "format": "int32"
          },
          "relation": {
            "type": [
              "null",
              "string"
            ]
          },
          "note": {
            "type": [
              "null",
              "string"
            ]
          },
          "onDuplicate": {
            "type": [
              "null",
              "string"
            ],
            "description": "fail (default), keep (needs note) or move (needs moveFrom)."
          },
          "moveFrom": {
            "type": [
              "null",
              "array"
            ],
            "items": {
              "type": "integer",
              "format": "int32"
            }
          }
        }
      },
      "ProductCodeDto": {
        "required": [
          "id",
          "productId",
          "type",
          "value",
          "matchKey",
          "quantity",
          "relation",
          "source",
          "status",
          "isMain",
          "duplicateAccepted",
          "sharedWith",
          "publishable",
          "timeAdded",
          "timeUpdated"
        ],
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "format": "int32"
          },
          "productId": {
            "type": "integer",
            "format": "int32"
          },
          "type": {
            "type": "string",
            "description": "gtin or local in phase 1."
          },
          "value": {
            "type": "string",
            "description": "Canonical form. For a GTIN its length is the format."
          },
          "matchKey": {
            "type": "string",
            "description": "Normalised key: 14 digits for a GTIN; upper case without spaces for a local code."
          },
          "format": {
            "type": [
              "null",
              "integer"
            ],
            "description": "8, 12, 13 or 14 for a GTIN; null for a local code.",
            "format": "int32"
          },
          "category": {
            "type": [
              "null",
              "string"
            ],
            "description": "standard, isbn_issn, restricted, reserved, demo, refund or coupon (GTIN only)."
          },
          "quantity": {
            "type": "integer",
            "format": "int32"
          },
          "relation": {
            "type": "string",
            "description": "identifies or references."
          },
          "source": {
            "type": "string",
            "description": "Creation provenance: manual, api, mcp or import."
          },
          "status": {
            "type": "string",
            "description": "active or retired."
          },
          "isMain": {
            "type": "boolean"
          },
          "note": {
            "type": [
              "null",
              "string"
            ]
          },
          "duplicateAccepted": {
            "type": "boolean"
          },
          "sharedWith": {
            "type": "integer",
            "description": "How many other products hold the same type and key as an identifying code (any status).",
            "format": "int32"
          },
          "publishable": {
            "type": "boolean",
            "description": "Whether the code may be published (spec §13.1). Eligibility, not what a site shows now."
          },
          "withheldReason": {
            "type": [
              "null",
              "string"
            ],
            "description": "The first failing §13.1 condition: not_identifying_gtin, pack_code, category, variable_measure,\n            inactive_product, main_product or shared."
          },
          "timeAdded": {
            "type": "string",
            "format": "date-time"
          },
          "timeUpdated": {
            "type": "string",
            "format": "date-time"
          }
        },
        "description": "One code row of a product."
      },
      "ProductCodePatchDto": {
        "type": "object",
        "properties": {
          "isMain": {
            "type": [
              "null",
              "boolean"
            ]
          },
          "quantity": {
            "type": [
              "null",
              "integer"
            ],
            "format": "int32"
          },
          "relation": {
            "type": [
              "null",
              "string"
            ]
          },
          "status": {
            "type": [
              "null",
              "string"
            ]
          },
          "note": {
            "type": [
              "null",
              "string"
            ]
          },
          "onDuplicate": {
            "type": [
              "null",
              "string"
            ],
            "description": "fail (default) or keep."
          }
        },
        "description": "An absent (null) field is unchanged; `note: \"\"` clears the note; `isMain` accepts only true."
      },
      "ProductCodeReplaceDto": {
        "type": "object",
        "properties": {
          "code": {
            "type": [
              "null",
              "string"
            ]
          },
          "choice": {
            "type": [
              "null",
              "string"
            ]
          },
          "onDuplicate": {
            "type": [
              "null",
              "string"
            ]
          },
          "moveFrom": {
            "type": [
              "null",
              "array"
            ],
            "items": {
              "type": "integer",
              "format": "int32"
            }
          },
          "note": {
            "type": [
              "null",
              "string"
            ]
          },
          "quantity": {
            "type": [
              "null",
              "integer"
            ],
            "description": "Base units the new code stands for (at least 1); absent keeps the old row's quantity.",
            "format": "int32"
          }
        }
      },
      "ProductCodesSectionDto": {
        "required": [
          "status"
        ],
        "type": "object",
        "properties": {
          "mainGtin": {
            "type": [
              "null",
              "string"
            ]
          },
          "codes": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ProductCodeDto"
            }
          },
          "status": {
            "type": "string"
          }
        },
        "description": "GTIN spec §9: the product's active codes and its main GTIN."
      },
      "ProductCodeValidateDto": {
        "type": "object",
        "properties": {
          "code": {
            "type": [
              "null",
              "string"
            ]
          },
          "type": {
            "type": [
              "null",
              "string"
            ]
          }
        }
      },
      "ProductCodeWriteResponseDto": {
        "required": [
          "code",
          "parse"
        ],
        "type": "object",
        "properties": {
          "code": {
            "$ref": "#/components/schemas/ProductCodeDto"
          },
          "parse": {
            "$ref": "#/components/schemas/ParseResultDto"
          }
        }
      },
      "ProductCoreSectionDto": {
        "required": [
          "barcodeState",
          "status"
        ],
        "type": "object",
        "properties": {
          "name": {
            "type": [
              "null",
              "string"
            ]
          },
          "active": {
            "type": "boolean"
          },
          "vatCodeId": {
            "type": "integer",
            "format": "int32"
          },
          "vatCodeName": {
            "type": [
              "null",
              "string"
            ]
          },
          "vatRate": {
            "type": "number",
            "format": "double"
          },
          "barcode": {
            "type": [
              "null",
              "string"
            ],
            "description": "The neutral value of the tenant's barcode field; null when there is none or the mapping is not ok."
          },
          "barcodeState": {
            "type": "string",
            "description": "notConfigured, invalidConfig or ok (roadmap §4.2)."
          },
          "timeAdded": {
            "type": "string",
            "format": "date-time"
          },
          "status": {
            "type": "string"
          }
        }
      },
      "ProductDetailDto": {
        "required": [
          "productId",
          "productNumber",
          "core",
          "properties",
          "categories",
          "prices",
          "family",
          "links",
          "stock",
          "media",
          "storefront"
        ],
        "type": "object",
        "properties": {
          "productId": {
            "type": "integer",
            "format": "int32"
          },
          "productNumber": {
            "type": "string"
          },
          "core": {
            "$ref": "#/components/schemas/ProductCoreSectionDto"
          },
          "properties": {
            "$ref": "#/components/schemas/ProductPropertiesSectionDto"
          },
          "categories": {
            "$ref": "#/components/schemas/ProductCategoriesSectionDto"
          },
          "prices": {
            "$ref": "#/components/schemas/ProductSectionDto"
          },
          "family": {
            "$ref": "#/components/schemas/ProductFamilySectionDto"
          },
          "links": {
            "$ref": "#/components/schemas/ProductLinksSectionDto"
          },
          "stock": {
            "$ref": "#/components/schemas/ProductStockSectionDto"
          },
          "media": {
            "$ref": "#/components/schemas/ProductSectionDto"
          },
          "storefront": {
            "$ref": "#/components/schemas/ProductStorefrontSectionDto"
          },
          "codes": {
            "$ref": "#/components/schemas/ProductCodesSectionDto"
          }
        },
        "description": "get_product: everything about one product, in sections that each carry a status."
      },
      "ProductFamilyMemberDto": {
        "required": [
          "productId",
          "productNumber"
        ],
        "type": "object",
        "properties": {
          "productId": {
            "type": "integer",
            "format": "int32"
          },
          "productNumber": {
            "type": "string"
          },
          "name": {
            "type": [
              "null",
              "string"
            ]
          },
          "active": {
            "type": "boolean"
          },
          "options": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ProductOptionDto"
            }
          }
        }
      },
      "ProductFamilySectionDto": {
        "required": [
          "role",
          "status"
        ],
        "type": "object",
        "properties": {
          "role": {
            "type": "string",
            "description": "standalone, main or child (the worker's effective-main rule)."
          },
          "mainProductId": {
            "type": [
              "null",
              "integer"
            ],
            "format": "int32"
          },
          "mainProductNumber": {
            "type": [
              "null",
              "string"
            ]
          },
          "options": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ProductOptionDto"
            },
            "description": "A child's own option values."
          },
          "children": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ProductFamilyMemberDto"
            },
            "description": "The family's children (a main's own; for a child, its siblings and itself), at most 200."
          },
          "childCount": {
            "type": "integer",
            "format": "int32"
          },
          "status": {
            "type": "string"
          }
        }
      },
      "ProductFieldChoiceDto": {
        "required": [
          "value",
          "count"
        ],
        "type": "object",
        "properties": {
          "value": {
            "type": "string"
          },
          "count": {
            "type": [
              "null",
              "integer"
            ],
            "format": "int32"
          }
        },
        "description": "Count: products using the value (open choices); null for closed choices."
      },
      "ProductFieldChoicesDto": {
        "type": "object",
        "properties": {
          "closed": {
            "type": "boolean"
          },
          "values": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ProductFieldChoiceDto"
            }
          },
          "truncated": {
            "type": "boolean"
          }
        },
        "description": "Closed (226): the only accepted values. Open (200/201): the values in use, top 200 by use, as suggestions."
      },
      "ProductFieldDto": {
        "required": [
          "field",
          "name",
          "kind"
        ],
        "type": "object",
        "properties": {
          "field": {
            "type": "string",
            "description": "The advertised id: `product:name`, `ept:&lt;key&gt;` or `ept:&lt;id&gt;`."
          },
          "typeId": {
            "type": [
              "null",
              "integer"
            ],
            "description": "The EntityPropertyType id; null for `product:name`.",
            "format": "int32"
          },
          "name": {
            "type": "string"
          },
          "tab": {
            "type": [
              "null",
              "string"
            ]
          },
          "kind": {
            "type": "string",
            "description": "`text`, `html`, `multiline`, `bool`, `int`, `decimal`, `datetime`, `select`, `multiselect`, `reference` or `unknown`."
          },
          "maxLength": {
            "type": [
              "null",
              "integer"
            ],
            "format": "int32"
          },
          "acceptsLang": {
            "type": "boolean"
          },
          "duplicateKey": {
            "type": "boolean",
            "description": "More than one active type shares this type's key."
          },
          "usedBy": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ProductFieldUsageDto"
            }
          },
          "propertyType": {
            "type": [
              "null",
              "integer"
            ],
            "description": "EntityPropertyType.PropertyType; null for product:* fields.",
            "format": "int32"
          },
          "cardinality": {
            "type": "string",
            "description": "`single`, or `list` for type 201."
          },
          "writable": {
            "type": "boolean"
          },
          "readOnlyReason": {
            "type": [
              "null",
              "string"
            ],
            "description": "READ_ONLY_TYPE, REFERENCE, UNSUPPORTED_KIND, CREATE_ONLY, NOT_CONFIGURED or INVALID_CONFIG."
          },
          "storefrontSource": {
            "type": "boolean",
            "description": "The id also works as a storefront content source."
          },
          "choices": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "$ref": "#/components/schemas/ProductFieldChoicesDto"
              }
            ]
          },
          "canonical": {
            "type": [
              "null",
              "string"
            ],
            "description": "For an alias: the field it resolves to (product:barcode → ept:17)."
          },
          "aliasState": {
            "type": [
              "null",
              "string"
            ],
            "description": "product:barcode only: notConfigured, invalidConfig or ok."
          }
        },
        "description": "One writable product field (spec 2026-09-25 product bulk update §4.1)."
      },
      "ProductFieldUsageDto": {
        "required": [
          "siteId",
          "site",
          "version",
          "role",
          "language"
        ],
        "type": "object",
        "properties": {
          "siteId": {
            "type": "integer",
            "format": "int32"
          },
          "site": {
            "type": "string"
          },
          "version": {
            "type": "string"
          },
          "role": {
            "type": "string"
          },
          "language": {
            "type": [
              "null",
              "string"
            ]
          }
        },
        "description": "Where a storefront site reads a field: Version is `live` or `draft`,\n            Language null means the language-independent source."
      },
      "ProductFindDto": {
        "required": [
          "productId"
        ],
        "type": "object",
        "properties": {
          "productId": {
            "type": "integer",
            "format": "int32"
          },
          "productNumber": {
            "type": [
              "null",
              "string"
            ]
          },
          "description": {
            "type": [
              "null",
              "string"
            ]
          },
          "barcode": {
            "type": [
              "null",
              "string"
            ]
          },
          "isActive": {
            "type": [
              "null",
              "boolean"
            ]
          }
        }
      },
      "ProductGroupDto": {
        "required": [
          "id"
        ],
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "format": "int32"
          },
          "name": {
            "type": [
              "null",
              "string"
            ]
          },
          "defaultVatCodeId": {
            "type": "integer",
            "format": "int32"
          },
          "defaultVatRate": {
            "type": [
              "null",
              "number"
            ],
            "format": "double"
          },
          "isDefaultGroup": {
            "type": "boolean"
          }
        }
      },
      "ProductLinkDto": {
        "required": [
          "productId"
        ],
        "type": "object",
        "properties": {
          "kind": {
            "type": [
              "null",
              "string"
            ]
          },
          "productId": {
            "type": "integer",
            "format": "int32"
          },
          "productNumber": {
            "type": [
              "null",
              "string"
            ]
          },
          "productName": {
            "type": [
              "null",
              "string"
            ]
          },
          "quantity": {
            "type": "number",
            "format": "double"
          },
          "name": {
            "type": [
              "null",
              "string"
            ]
          },
          "key2": {
            "type": [
              "null",
              "string"
            ]
          },
          "key3": {
            "type": [
              "null",
              "string"
            ]
          }
        },
        "description": "An outgoing product link: string? ProductLinkDto.Kind is its Key1."
      },
      "ProductLinksSectionDto": {
        "required": [
          "status"
        ],
        "type": "object",
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ProductLinkDto"
            },
            "description": "Outgoing links other than variants, at most 200."
          },
          "count": {
            "type": "integer",
            "format": "int32"
          },
          "status": {
            "type": "string"
          }
        }
      },
      "ProductOptionDto": {
        "required": [
          "axis",
          "value"
        ],
        "type": "object",
        "properties": {
          "axis": {
            "type": "string"
          },
          "value": {
            "type": "string"
          }
        },
        "description": "One option of a variant: the variant link's Key2 (axis) and Key3 (value)."
      },
      "ProductPropertiesSectionDto": {
        "required": [
          "status"
        ],
        "type": "object",
        "properties": {
          "values": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ProductValueDto"
            }
          },
          "status": {
            "type": "string"
          }
        }
      },
      "ProductSearchRowDto": {
        "required": [
          "productId",
          "productNumber",
          "variantRole"
        ],
        "type": "object",
        "properties": {
          "productId": {
            "type": "integer",
            "format": "int32"
          },
          "productNumber": {
            "type": "string"
          },
          "name": {
            "type": [
              "null",
              "string"
            ]
          },
          "active": {
            "type": "boolean"
          },
          "variantRole": {
            "type": "string",
            "description": "standalone, main or child."
          },
          "mainProductId": {
            "type": [
              "null",
              "integer"
            ],
            "description": "A child's main product (the worker's effective main); null otherwise.",
            "format": "int32"
          },
          "barcode": {
            "type": [
              "null",
              "string"
            ],
            "description": "The neutral value of the tenant's barcode field; null when there is none or the mapping is not ok."
          },
          "matchedOn": {
            "type": [
              "null",
              "string"
            ],
            "description": "id, productNumber, barcode, productNumberPrefix, productNumberContains or name; null without q."
          }
        },
        "description": "search_products (roadmap §6.3): one compact row."
      },
      "ProductSectionDto": {
        "required": [
          "status"
        ],
        "type": "object",
        "properties": {
          "status": {
            "type": "string"
          }
        }
      },
      "ProductStockSectionDto": {
        "required": [
          "status"
        ],
        "type": "object",
        "properties": {
          "rows": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WarehouseStockRowDto"
            }
          },
          "rowCount": {
            "type": "integer",
            "format": "int32"
          },
          "qtyInStock": {
            "type": "number",
            "format": "double"
          },
          "qtyIncoming": {
            "type": "number",
            "format": "double"
          },
          "qtyOutgoing": {
            "type": "number",
            "format": "double"
          },
          "qtyDistributable": {
            "type": "number",
            "format": "double"
          },
          "status": {
            "type": "string"
          }
        },
        "description": "The get_warehouse_stock rows of this product (at most 100) and totals over all of them."
      },
      "ProductStorefrontBrandDto": {
        "required": [
          "siteId",
          "site",
          "version",
          "rootId"
        ],
        "type": "object",
        "properties": {
          "siteId": {
            "type": "integer",
            "format": "int32"
          },
          "site": {
            "type": "string"
          },
          "version": {
            "type": "string"
          },
          "rootId": {
            "type": "integer",
            "format": "int32"
          },
          "values": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "ProductStorefrontRootDto": {
        "required": [
          "rootId",
          "rootName",
          "field"
        ],
        "type": "object",
        "properties": {
          "rootId": {
            "type": "integer",
            "format": "int32"
          },
          "rootName": {
            "type": "string"
          },
          "field": {
            "type": "string"
          },
          "values": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ProductCategoryRefDto"
            }
          }
        }
      },
      "ProductStorefrontSectionDto": {
        "required": [
          "status"
        ],
        "type": "object",
        "properties": {
          "cardProductId": {
            "type": [
              "null",
              "integer"
            ],
            "description": "The product whose card a shop shows: a child's main, else the product itself; null when that product is inactive.",
            "format": "int32"
          },
          "categories": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ProductStorefrontRootDto"
            },
            "description": "The family's union of stored memberships strictly below each root."
          },
          "brands": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ProductStorefrontBrandDto"
            },
            "description": "Per site and version whose content mapping takes the brand from a category root."
          },
          "usageKnown": {
            "type": "boolean",
            "description": "False when the storefront usage could not be read; Brands is then empty."
          },
          "status": {
            "type": "string"
          }
        },
        "description": "Resolved, without site language or assortment rules: the card a shop shows and its family's category union (the card\n            and its active children, as the worker groups them). Status unsupported: the card product is inactive, so no shop shows a\n            card; CardProductId is then null and nothing is resolved."
      },
      "ProductTextChunkDto": {
        "required": [
          "value"
        ],
        "type": "object",
        "properties": {
          "value": {
            "type": "string"
          },
          "offset": {
            "type": "integer",
            "format": "int32"
          },
          "length": {
            "type": "integer",
            "format": "int32"
          },
          "nextOffset": {
            "type": [
              "null",
              "integer"
            ],
            "format": "int32"
          },
          "rowCount": {
            "type": "integer",
            "format": "int32"
          }
        }
      },
      "ProductTextsDto": {
        "required": [
          "productId",
          "productNumber"
        ],
        "type": "object",
        "properties": {
          "productId": {
            "type": "integer",
            "format": "int32"
          },
          "productNumber": {
            "type": "string"
          },
          "name": {
            "type": [
              "null",
              "string"
            ]
          },
          "inactive": {
            "type": "boolean"
          },
          "isVariantMain": {
            "type": "boolean"
          },
          "variantMainProductId": {
            "type": [
              "null",
              "integer"
            ],
            "format": "int32"
          },
          "effectiveMainProductId": {
            "type": [
              "null",
              "integer"
            ],
            "format": "int32"
          },
          "values": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ProductTextValueDto"
            }
          }
        }
      },
      "ProductTextValueDto": {
        "required": [
          "field"
        ],
        "type": "object",
        "properties": {
          "field": {
            "type": "string"
          },
          "lang": {
            "type": [
              "null",
              "string"
            ]
          },
          "value": {
            "type": [
              "null",
              "string"
            ],
            "description": "Null when the address has only inactive rows."
          },
          "length": {
            "type": [
              "null",
              "integer"
            ],
            "format": "int32"
          },
          "truncated": {
            "type": "boolean"
          },
          "rowCount": {
            "type": "integer",
            "format": "int32"
          },
          "inactiveRowCount": {
            "type": "integer",
            "format": "int32"
          }
        }
      },
      "ProductValueDto": {
        "required": [
          "field"
        ],
        "type": "object",
        "properties": {
          "field": {
            "type": "string"
          },
          "lang": {
            "type": [
              "null",
              "string"
            ]
          },
          "value": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "$ref": "#/components/schemas/JsonElement"
              }
            ]
          },
          "allValues": {
            "type": [
              "null",
              "array"
            ]
          },
          "length": {
            "type": [
              "null",
              "integer"
            ],
            "format": "int32"
          },
          "truncated": {
            "type": "boolean"
          },
          "rowCount": {
            "type": "integer",
            "format": "int32"
          },
          "inactiveRowCount": {
            "type": "integer",
            "format": "int32"
          },
          "omitted": {
            "type": "boolean",
            "description": "get_product only: the properties budget was spent, so the value is left out (read it with get_product_value)."
          },
          "unsupported": {
            "type": "boolean",
            "description": "get_product only: the type's kind is unknown, so its column is not known and no value is read (plan review #3)."
          }
        },
        "description": "One address (field + culture; lang null = the neutral row). JsonElement? ProductValueDto.Value is JSON in the kind's type: a\n            string for text kinds (cut at 4 000, bool ProductValueDto.Truncated), true/false, a number, a date string, an array of strings\n            for a multi-select, an array of ProductCategoryRefDto for category:&lt;rootId&gt;. Null with RowCount 0 = only\n            inactive rows; with RowCount ≥ 1 = a stored NULL. IReadOnlyList&lt;JsonElement&gt;? ProductValueDto.AllValues: every active row when a single-value address\n            has several (the first 10 rows). Arrays and text are cut at 4 000 characters (bool ProductValueDto.Truncated, also true when an\n            allValues row was cut). int? ProductValueDto.Length: the full display length of JsonElement? ProductValueDto.Value."
      },
      "ProductValuesDto": {
        "required": [
          "productId",
          "productNumber"
        ],
        "type": "object",
        "properties": {
          "productId": {
            "type": "integer",
            "format": "int32"
          },
          "productNumber": {
            "type": "string"
          },
          "name": {
            "type": [
              "null",
              "string"
            ]
          },
          "inactive": {
            "type": "boolean"
          },
          "isVariantMain": {
            "type": "boolean"
          },
          "variantMainProductId": {
            "type": [
              "null",
              "integer"
            ],
            "format": "int32"
          },
          "effectiveMainProductId": {
            "type": [
              "null",
              "integer"
            ],
            "format": "int32"
          },
          "values": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ProductValueDto"
            }
          }
        },
        "description": "list_product_values (roadmap §6.2): one product with the typed values of the chosen fields."
      },
      "ProposalBandCountsDto": {
        "type": "object",
        "properties": {
          "green": {
            "type": "integer",
            "format": "int32"
          },
          "amber": {
            "type": "integer",
            "format": "int32"
          },
          "red": {
            "type": "integer",
            "format": "int32"
          }
        },
        "description": "Lines per band. Rejected and superseded lines are not counted."
      },
      "ProposalBatchDto": {
        "required": [
          "id",
          "source",
          "mode",
          "externalBatchId",
          "receivedAt",
          "status",
          "lineCount",
          "bands",
          "vendorGroupCount"
        ],
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "format": "int64"
          },
          "source": {
            "type": "string"
          },
          "mode": {
            "type": "string"
          },
          "externalBatchId": {
            "type": "string"
          },
          "receivedAt": {
            "type": "string",
            "format": "date-time"
          },
          "status": {
            "type": "string",
            "description": "`open` while any line is proposed, approved or converting; `done` otherwise. Accept unknown values."
          },
          "lineCount": {
            "type": "integer",
            "description": "Every line of the batch, rejected and buyer-added lines included.",
            "format": "int32"
          },
          "bands": {
            "$ref": "#/components/schemas/ProposalBandCountsDto"
          },
          "vendorGroupCount": {
            "type": "integer",
            "description": "Distinct (vendor, order group) pairs among the counted lines; unresolved vendors count as one.",
            "format": "int32"
          },
          "oldestUndecidedAt": {
            "type": [
              "null",
              "string"
            ],
            "description": "When the batch arrived, while any line is still undecided (proposed); null otherwise.",
            "format": "date-time"
          }
        },
        "description": "A proposal batch with its derived status and counts."
      },
      "ProposalBatchIngestRequestDto": {
        "type": "object",
        "properties": {
          "source": {
            "type": [
              "null",
              "string"
            ],
            "description": "The source's name, `^[a-z0-9_-]{1,32}$`, e.g. `slim4`; `manual` is reserved."
          },
          "externalBatchId": {
            "type": [
              "null",
              "string"
            ],
            "description": "The source's own id for this batch, nonblank, at most 200 characters. Posting the same id again with\n            the same content returns the existing batch (200); with other content it is refused (409 batch_conflict)."
          },
          "mode": {
            "type": [
              "null",
              "string"
            ],
            "description": "Only `review`."
          },
          "lines": {
            "type": [
              "null",
              "array"
            ],
            "items": {
              "$ref": "#/components/schemas/ProposalIngestLineDto"
            },
            "description": "1 to 5,000 lines, each with a unique `lineNo`."
          }
        },
        "description": "A batch of proposed purchase lines from one source run or file (e.g. a Slim4 PO file). It lands in the\n            proposal inbox for a buyer to review; nothing is ordered automatically."
      },
      "ProposalBatchIngestResultDto": {
        "required": [
          "batchId",
          "lineCount",
          "bands"
        ],
        "type": "object",
        "properties": {
          "batchId": {
            "type": "integer",
            "format": "int64"
          },
          "lineCount": {
            "type": "integer",
            "format": "int32"
          },
          "bands": {
            "$ref": "#/components/schemas/ProposalBandCountsDto"
          }
        }
      },
      "ProposalDecisionDto": {
        "required": [
          "id",
          "action",
          "actorType",
          "at"
        ],
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "format": "int64"
          },
          "action": {
            "type": "string",
            "description": "edit | approve | unapprove | reject | unreject | add | supersede | remap | revalidated | reopen | convert | conversion_failed."
          },
          "changes": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "description": "For edits `{field: [before, after]}`; for approve the approval snapshot; for revalidated the diff.",
                "$ref": "#/components/schemas/JsonElement"
              }
            ]
          },
          "reasonCode": {
            "type": [
              "null",
              "string"
            ]
          },
          "note": {
            "type": [
              "null",
              "string"
            ]
          },
          "actorType": {
            "type": "string",
            "description": "person | system | service."
          },
          "actorId": {
            "type": [
              "null",
              "string"
            ]
          },
          "at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "description": "One recorded decision on a line (append-only)."
      },
      "ProposalIngestLineDto": {
        "type": "object",
        "properties": {
          "lineNo": {
            "type": [
              "null",
              "integer"
            ],
            "format": "int32"
          },
          "productCode": {
            "type": [
              "null",
              "string"
            ],
            "description": "Matched against the product number (trimmed, case ignored). At most 100 characters."
          },
          "ean": {
            "type": [
              "null",
              "string"
            ],
            "description": "Matched against the tenant's barcode exactly (leading zeros kept) when the product code does not match\n            exactly one product. At most 64 characters."
          },
          "vendorCode": {
            "type": [
              "null",
              "string"
            ],
            "description": "The source's vendor code, mapped to a supplier through the source aliases. At most 100 characters."
          },
          "vendorProductCode": {
            "type": [
              "null",
              "string"
            ],
            "description": "At most 200 characters."
          },
          "quantity": {
            "type": [
              "null",
              "number"
            ],
            "format": "double"
          },
          "price": {
            "type": [
              "null",
              "number"
            ],
            "format": "double"
          },
          "currency": {
            "type": [
              "null",
              "string"
            ],
            "description": "A 3-letter ISO code, or null."
          },
          "requestedDate": {
            "type": [
              "null",
              "string"
            ],
            "description": "`yyyy-MM-dd`, or null."
          },
          "locationCode": {
            "type": [
              "null",
              "string"
            ],
            "description": "Stored with the line; not resolved in this version. At most 64 characters."
          },
          "evidence": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "description": "Any JSON object kept with the line (the raw row; `priceBasis` for the price comparison).",
                "$ref": "#/components/schemas/JsonElement"
              }
            ]
          }
        },
        "description": "One proposed purchase line as the source sends it."
      },
      "ProposalLineDetailDto": {
        "type": "object",
        "properties": {
          "decisions": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ProposalDecisionDto"
            }
          },
          "id": {
            "type": "integer",
            "format": "int64"
          },
          "version": {
            "type": "integer",
            "description": "Changes on every write; internal edits must send it back.",
            "format": "int32"
          },
          "sourceLineNo": {
            "type": "integer",
            "format": "int32"
          },
          "source": {
            "type": "string",
            "description": "The batch's source, or `manual` for a line a buyer added."
          },
          "status": {
            "type": "string",
            "description": "proposed | approved | rejected | superseded | converting | converted. Accept unknown values."
          },
          "band": {
            "type": "string",
            "description": "green | amber | red."
          },
          "reasonCodes": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "exceptionCodes": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "productId": {
            "type": [
              "null",
              "integer"
            ],
            "format": "int32"
          },
          "productNumber": {
            "type": [
              "null",
              "string"
            ]
          },
          "productName": {
            "type": [
              "null",
              "string"
            ]
          },
          "sourceProductCode": {
            "type": [
              "null",
              "string"
            ],
            "description": "The product code as the source sent it; null for a line the source identified by EAN only (review M1)."
          },
          "ean": {
            "type": [
              "null",
              "string"
            ],
            "description": "The EAN as the source sent it (not the matched product's barcode)."
          },
          "vendorProductCode": {
            "type": [
              "null",
              "string"
            ]
          },
          "sourceVendorCode": {
            "type": [
              "null",
              "string"
            ],
            "description": "The vendor code as the source sent it; null for a buyer-added line."
          },
          "companyId": {
            "type": [
              "null",
              "integer"
            ],
            "format": "int32"
          },
          "vendorName": {
            "type": [
              "null",
              "string"
            ]
          },
          "groupId": {
            "type": [
              "null",
              "integer"
            ],
            "format": "int64"
          },
          "groupName": {
            "type": [
              "null",
              "string"
            ]
          },
          "sourceQty": {
            "type": "number",
            "format": "double"
          },
          "qty": {
            "type": "number",
            "format": "double"
          },
          "sourcePrice": {
            "type": [
              "null",
              "number"
            ],
            "format": "double"
          },
          "sourceCurrency": {
            "type": [
              "null",
              "string"
            ]
          },
          "listPrice": {
            "type": [
              "null",
              "number"
            ],
            "format": "double"
          },
          "listCurrencyIso": {
            "type": [
              "null",
              "string"
            ]
          },
          "price": {
            "type": [
              "null",
              "number"
            ],
            "description": "The effective price (the buyer's override, else the vendor list price), 4 decimals.",
            "format": "double"
          },
          "currencyIso": {
            "type": [
              "null",
              "string"
            ]
          },
          "rate": {
            "type": [
              "null",
              "number"
            ],
            "description": "SEK per one unit of string? ProposalLineDto.CurrencyIso; 1 for SEK.",
            "format": "double"
          },
          "priceComparison": {
            "$ref": "#/components/schemas/ProposalPriceComparisonDto"
          },
          "requestedDate": {
            "type": [
              "null",
              "string"
            ],
            "format": "date"
          },
          "hasPriceOverride": {
            "type": "boolean"
          },
          "hasVendorOverride": {
            "type": "boolean"
          },
          "approvedAt": {
            "type": [
              "null",
              "string"
            ],
            "format": "date-time"
          }
        },
        "description": "A line with its decision history, oldest first."
      },
      "ProposalLineDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "format": "int64"
          },
          "version": {
            "type": "integer",
            "description": "Changes on every write; internal edits must send it back.",
            "format": "int32"
          },
          "sourceLineNo": {
            "type": "integer",
            "format": "int32"
          },
          "source": {
            "type": "string",
            "description": "The batch's source, or `manual` for a line a buyer added."
          },
          "status": {
            "type": "string",
            "description": "proposed | approved | rejected | superseded | converting | converted. Accept unknown values."
          },
          "band": {
            "type": "string",
            "description": "green | amber | red."
          },
          "reasonCodes": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "exceptionCodes": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "productId": {
            "type": [
              "null",
              "integer"
            ],
            "format": "int32"
          },
          "productNumber": {
            "type": [
              "null",
              "string"
            ]
          },
          "productName": {
            "type": [
              "null",
              "string"
            ]
          },
          "sourceProductCode": {
            "type": [
              "null",
              "string"
            ],
            "description": "The product code as the source sent it; null for a line the source identified by EAN only (review M1)."
          },
          "ean": {
            "type": [
              "null",
              "string"
            ],
            "description": "The EAN as the source sent it (not the matched product's barcode)."
          },
          "vendorProductCode": {
            "type": [
              "null",
              "string"
            ]
          },
          "sourceVendorCode": {
            "type": [
              "null",
              "string"
            ],
            "description": "The vendor code as the source sent it; null for a buyer-added line."
          },
          "companyId": {
            "type": [
              "null",
              "integer"
            ],
            "format": "int32"
          },
          "vendorName": {
            "type": [
              "null",
              "string"
            ]
          },
          "groupId": {
            "type": [
              "null",
              "integer"
            ],
            "format": "int64"
          },
          "groupName": {
            "type": [
              "null",
              "string"
            ]
          },
          "sourceQty": {
            "type": "number",
            "format": "double"
          },
          "qty": {
            "type": "number",
            "format": "double"
          },
          "sourcePrice": {
            "type": [
              "null",
              "number"
            ],
            "format": "double"
          },
          "sourceCurrency": {
            "type": [
              "null",
              "string"
            ]
          },
          "listPrice": {
            "type": [
              "null",
              "number"
            ],
            "format": "double"
          },
          "listCurrencyIso": {
            "type": [
              "null",
              "string"
            ]
          },
          "price": {
            "type": [
              "null",
              "number"
            ],
            "description": "The effective price (the buyer's override, else the vendor list price), 4 decimals.",
            "format": "double"
          },
          "currencyIso": {
            "type": [
              "null",
              "string"
            ]
          },
          "rate": {
            "type": [
              "null",
              "number"
            ],
            "description": "SEK per one unit of string? ProposalLineDto.CurrencyIso; 1 for SEK.",
            "format": "double"
          },
          "priceComparison": {
            "$ref": "#/components/schemas/ProposalPriceComparisonDto"
          },
          "requestedDate": {
            "type": [
              "null",
              "string"
            ],
            "format": "date"
          },
          "hasPriceOverride": {
            "type": "boolean"
          },
          "hasVendorOverride": {
            "type": "boolean"
          },
          "approvedAt": {
            "type": [
              "null",
              "string"
            ],
            "format": "date-time"
          }
        },
        "description": "One proposed purchase line. Unsealed: the line detail extends it."
      },
      "ProposalPriceComparisonDto": {
        "type": "object",
        "properties": {
          "pct": {
            "type": [
              "null",
              "number"
            ],
            "description": "(source − list) / list × 100 on the source's price basis, rounded to 2 decimals.",
            "format": "double"
          },
          "comparable": {
            "type": "boolean"
          }
        }
      },
      "ProposalSourceAliasDto": {
        "type": "object",
        "properties": {
          "source": {
            "type": [
              "null",
              "string"
            ],
            "description": "`^[a-z0-9_-]{1,32}$`; `manual` is reserved."
          },
          "externalCode": {
            "type": [
              "null",
              "string"
            ],
            "description": "The source's vendor code, nonblank, at most 100 characters; matched exactly."
          },
          "companyId": {
            "type": [
              "null",
              "integer"
            ],
            "description": "An active supplier (a Leverantör number or the attest_supplier property).",
            "format": "int32"
          },
          "groupExtCode": {
            "type": [
              "null",
              "string"
            ],
            "description": "When given, the supplier's order group with this code is created or renamed and the alias points at it."
          },
          "groupName": {
            "type": [
              "null",
              "string"
            ]
          }
        },
        "description": "One source vendor code mapped to a supplier (PUT /api/v1/purchase-proposals/source-aliases)."
      },
      "ProposalSourceAliasResultDto": {
        "required": [
          "upserted",
          "recheckedLines"
        ],
        "type": "object",
        "properties": {
          "upserted": {
            "type": "integer",
            "format": "int32"
          },
          "recheckedLines": {
            "type": "integer",
            "description": "Open proposal lines with an upserted code that were re-checked.",
            "format": "int32"
          }
        }
      },
      "PurchaseInvoiceConfirmMatchEntryDto": {
        "required": [
          "invoiceLineIndex",
          "orderItemId",
          "invTransactionId"
        ],
        "type": "object",
        "properties": {
          "invoiceLineIndex": {
            "type": "integer",
            "format": "int32"
          },
          "orderItemId": {
            "type": "integer",
            "format": "int32"
          },
          "invTransactionId": {
            "type": "integer",
            "format": "int32"
          }
        }
      },
      "PurchaseInvoiceConfirmMatchesRequestDto": {
        "required": [
          "matches"
        ],
        "type": "object",
        "properties": {
          "matches": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PurchaseInvoiceConfirmMatchEntryDto"
            }
          }
        }
      },
      "PurchaseInvoiceConfirmMatchesResponseDto": {
        "required": [
          "invoiceId"
        ],
        "type": "object",
        "properties": {
          "invoiceId": {
            "type": "integer",
            "format": "int32"
          }
        }
      },
      "PurchaseInvoiceMatchCandidateDto": {
        "required": [
          "orderId",
          "orderItemId",
          "invTransactionId",
          "receiptQuantity",
          "receiptUnitPriceSek",
          "receiptDate",
          "score",
          "reasons",
          "isAutoEligible"
        ],
        "type": "object",
        "properties": {
          "orderId": {
            "type": "integer",
            "format": "int32"
          },
          "orderItemId": {
            "type": "integer",
            "format": "int32"
          },
          "invTransactionId": {
            "type": "integer",
            "format": "int32"
          },
          "orderName": {
            "type": [
              "null",
              "string"
            ]
          },
          "productNumber": {
            "type": [
              "null",
              "string"
            ]
          },
          "vendorProductNumber": {
            "type": [
              "null",
              "string"
            ]
          },
          "description": {
            "type": [
              "null",
              "string"
            ]
          },
          "receiptQuantity": {
            "type": "number",
            "format": "double"
          },
          "receiptUnitPriceSek": {
            "type": "number",
            "format": "double"
          },
          "receiptDate": {
            "type": "string",
            "format": "date-time"
          },
          "score": {
            "type": "integer",
            "format": "int32"
          },
          "reasons": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "qtyVariance": {
            "type": [
              "null",
              "number"
            ],
            "format": "double"
          },
          "priceVarianceSek": {
            "type": [
              "null",
              "number"
            ],
            "format": "double"
          },
          "totalVarianceSek": {
            "type": [
              "null",
              "number"
            ],
            "format": "double"
          },
          "dateVarianceDays": {
            "type": [
              "null",
              "integer"
            ],
            "format": "int32"
          },
          "isAutoEligible": {
            "type": "boolean"
          }
        }
      },
      "PurchaseInvoiceMatchReceiptDto": {
        "required": [
          "invTransactionId",
          "orderId",
          "orderItemId",
          "quantity",
          "inPriceSek",
          "date"
        ],
        "type": "object",
        "properties": {
          "invTransactionId": {
            "type": "integer",
            "format": "int32"
          },
          "orderId": {
            "type": "integer",
            "format": "int32"
          },
          "orderItemId": {
            "type": "integer",
            "format": "int32"
          },
          "orderName": {
            "type": [
              "null",
              "string"
            ]
          },
          "productNumber": {
            "type": [
              "null",
              "string"
            ]
          },
          "vendorProductNumber": {
            "type": [
              "null",
              "string"
            ]
          },
          "description": {
            "type": [
              "null",
              "string"
            ]
          },
          "quantity": {
            "type": "number",
            "format": "double"
          },
          "inPriceSek": {
            "type": "number",
            "format": "double"
          },
          "date": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "PurchaseInvoiceMatchResponseDto": {
        "required": [
          "invoiceId",
          "tolerances",
          "suggestions",
          "unmatchedReceipts",
          "wholeOrderOptions"
        ],
        "type": "object",
        "properties": {
          "invoiceId": {
            "type": "integer",
            "format": "int32"
          },
          "companyId": {
            "type": [
              "null",
              "integer"
            ],
            "format": "int32"
          },
          "tolerances": {
            "$ref": "#/components/schemas/PurchaseInvoiceMatchTolerancesDto"
          },
          "suggestions": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PurchaseInvoiceMatchSuggestionDto"
            }
          },
          "unmatchedReceipts": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PurchaseInvoiceMatchReceiptDto"
            }
          },
          "wholeOrderOptions": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PurchaseInvoiceWholeOrderOptionDto"
            }
          }
        },
        "description": "Stable v1 DTO surface for the 3-way purchase-invoice matching API.\n            Mirrors the internal MatchSuggestionResponse / ConfirmMatchRequest shapes but\n            uses DateTimeOffset and serialised enum strings on the wire."
      },
      "PurchaseInvoiceMatchSuggestionDto": {
        "required": [
          "invoiceLineIndex",
          "unitPrice",
          "totalExVat",
          "candidates"
        ],
        "type": "object",
        "properties": {
          "invoiceLineIndex": {
            "type": "integer",
            "format": "int32"
          },
          "vendorProductNumber": {
            "type": [
              "null",
              "string"
            ]
          },
          "productNumber": {
            "type": [
              "null",
              "string"
            ]
          },
          "description": {
            "type": [
              "null",
              "string"
            ]
          },
          "quantity": {
            "type": [
              "null",
              "number"
            ],
            "format": "double"
          },
          "unitPrice": {
            "type": "number",
            "format": "double"
          },
          "totalExVat": {
            "type": "number",
            "format": "double"
          },
          "isExtraCharge": {
            "type": "boolean"
          },
          "candidates": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PurchaseInvoiceMatchCandidateDto"
            }
          }
        }
      },
      "PurchaseInvoiceMatchTolerancesDto": {
        "required": [
          "qtyPercent",
          "qtyAbsolute",
          "pricePercent",
          "priceAbsoluteSek",
          "dateWindowDays",
          "autoEligibleScore"
        ],
        "type": "object",
        "properties": {
          "qtyPercent": {
            "type": "number",
            "format": "double"
          },
          "qtyAbsolute": {
            "type": "number",
            "format": "double"
          },
          "pricePercent": {
            "type": "number",
            "format": "double"
          },
          "priceAbsoluteSek": {
            "type": "number",
            "format": "double"
          },
          "dateWindowDays": {
            "type": "integer",
            "format": "int32"
          },
          "autoEligibleScore": {
            "type": "integer",
            "format": "int32"
          }
        }
      },
      "PurchaseInvoiceMatchWholeOrderRequestDto": {
        "required": [
          "orderId"
        ],
        "type": "object",
        "properties": {
          "orderId": {
            "type": "integer",
            "format": "int32"
          }
        }
      },
      "PurchaseInvoiceWholeOrderOptionDto": {
        "required": [
          "orderId",
          "unbookedReceiptCount",
          "openLineCount",
          "unbookedValueSek"
        ],
        "type": "object",
        "properties": {
          "orderId": {
            "type": "integer",
            "format": "int32"
          },
          "orderName": {
            "type": [
              "null",
              "string"
            ]
          },
          "dateOrdered": {
            "type": [
              "null",
              "string"
            ],
            "format": "date-time"
          },
          "unbookedReceiptCount": {
            "type": "integer",
            "format": "int32"
          },
          "openLineCount": {
            "type": "integer",
            "format": "int32"
          },
          "unbookedValueSek": {
            "type": "number",
            "format": "double"
          }
        }
      },
      "PurchaseOrderDto": {
        "required": [
          "id"
        ],
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "format": "int32"
          },
          "purchaseNumber": {
            "type": [
              "null",
              "integer"
            ],
            "format": "int32"
          },
          "vendorId": {
            "type": [
              "null",
              "integer"
            ],
            "format": "int32"
          },
          "vendorName": {
            "type": [
              "null",
              "string"
            ]
          },
          "vendorOrgno": {
            "type": [
              "null",
              "string"
            ]
          },
          "statusId": {
            "type": [
              "null",
              "integer"
            ],
            "format": "int32"
          },
          "statusName": {
            "type": [
              "null",
              "string"
            ]
          },
          "dateOrder": {
            "type": [
              "null",
              "string"
            ],
            "format": "date-time"
          },
          "dateDelivery": {
            "type": [
              "null",
              "string"
            ],
            "format": "date-time"
          },
          "dateInvoice": {
            "type": [
              "null",
              "string"
            ],
            "format": "date-time"
          },
          "dateDue": {
            "type": [
              "null",
              "string"
            ],
            "format": "date-time"
          },
          "orderTotalExVat": {
            "type": [
              "null",
              "number"
            ],
            "format": "double"
          },
          "orderTotalIncVat": {
            "type": [
              "null",
              "number"
            ],
            "format": "double"
          },
          "receivedQtyPercent": {
            "type": [
              "null",
              "number"
            ],
            "format": "double"
          },
          "receivedValueExVat": {
            "type": [
              "null",
              "number"
            ],
            "format": "double"
          },
          "invoicedValueExVat": {
            "type": [
              "null",
              "number"
            ],
            "format": "double"
          },
          "openToInvoiceExVat": {
            "type": [
              "null",
              "number"
            ],
            "format": "double"
          },
          "currencyIsoCode": {
            "type": [
              "null",
              "string"
            ]
          }
        }
      },
      "ReportAggregateRequestDto": {
        "required": [
          "groupBy",
          "measures",
          "filter",
          "sortBy"
        ],
        "type": "object",
        "properties": {
          "groupBy": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "measures": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ReportMeasureDto"
            }
          },
          "filter": {
            "type": [
              "null",
              "array"
            ],
            "items": {
              "$ref": "#/components/schemas/ReportFilterClauseDto"
            }
          },
          "sortBy": {
            "type": [
              "null",
              "string"
            ]
          },
          "desc": {
            "type": "boolean",
            "default": false
          },
          "top": {
            "type": [
              "null",
              "integer"
            ],
            "format": "int32"
          },
          "enrich": {
            "type": [
              "null",
              "array"
            ],
            "items": {
              "$ref": "#/components/schemas/ReportEnrichDto"
            }
          },
          "cursor": {
            "type": [
              "null",
              "string"
            ]
          }
        },
        "description": "POST body for aggregate_report."
      },
      "ReportColumnDto": {
        "required": [
          "name",
          "label",
          "type",
          "unit",
          "enumLegend",
          "groupable",
          "measurable",
          "filterable"
        ],
        "type": "object",
        "properties": {
          "name": {
            "type": "string"
          },
          "label": {
            "type": "string"
          },
          "type": {
            "type": "string"
          },
          "unit": {
            "type": [
              "null",
              "string"
            ]
          },
          "enumLegend": {
            "type": [
              "null",
              "string"
            ]
          },
          "groupable": {
            "type": "boolean"
          },
          "measurable": {
            "type": "boolean"
          },
          "filterable": {
            "type": "boolean"
          },
          "joinKey": {
            "type": [
              "null",
              "string"
            ]
          },
          "description": {
            "type": [
              "null",
              "string"
            ]
          }
        },
        "description": "A column as described to the AI: wire name + human label + type + optional unit + enum legend.\n            JoinKey (when set) is a global key id; columns sharing it can be joined across reports."
      },
      "ReportCountResultDto": {
        "required": [
          "rowTotal"
        ],
        "type": "object",
        "properties": {
          "rowTotal": {
            "type": "integer",
            "format": "int64"
          }
        },
        "description": "Row total behind a filter (for \"x–y of N\" paging displays)."
      },
      "ReportDescribeDto": {
        "required": [
          "name",
          "displayName",
          "description",
          "columns",
          "joinableLookups"
        ],
        "type": "object",
        "properties": {
          "name": {
            "type": "string"
          },
          "displayName": {
            "type": "string"
          },
          "description": {
            "type": [
              "null",
              "string"
            ]
          },
          "columns": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ReportColumnDto"
            }
          },
          "joinableLookups": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/JoinableLookupDto"
            }
          },
          "defaultSortColumn": {
            "type": [
              "null",
              "string"
            ]
          },
          "defaultSortDesc": {
            "type": "boolean",
            "default": false
          },
          "requireDateFilter": {
            "type": "boolean",
            "default": false
          },
          "inOdata": {
            "type": "boolean",
            "default": false
          }
        },
        "description": "describe_report payload. DefaultSortColumn/Desc is the report author's opening sort —\n            clients apply it only when the user hasn't chosen one (explicit sort always wins).\n            RequireDateFilter tells a UI the engine will reject an unbounded query; InOdata tells it the\n            report is also reachable through the OData v4 feed (so it can offer a feed link)."
      },
      "ReportEnrichDto": {
        "required": [
          "report",
          "on"
        ],
        "type": "object",
        "properties": {
          "report": {
            "type": "string"
          },
          "on": {
            "type": "string"
          }
        },
        "description": "One enrichment join request: LEFT JOIN Report (a lookup) onto the base\n            report, matching on the base column On (which must have a JoinKey)."
      },
      "ReportFilterClauseDto": {
        "required": [
          "field",
          "op",
          "value",
          "type"
        ],
        "type": "object",
        "properties": {
          "field": {
            "type": "string"
          },
          "op": {
            "type": "string"
          },
          "value": {
            "type": [
              "null",
              "string"
            ]
          },
          "type": {
            "type": "string"
          }
        },
        "description": "One filter clause from the caller."
      },
      "ReportMeasureDto": {
        "required": [
          "field",
          "func"
        ],
        "type": "object",
        "properties": {
          "field": {
            "type": "string"
          },
          "func": {
            "type": "string"
          }
        },
        "description": "One measure for aggregate_report (func is sum|count|avg|min|max|count_distinct)."
      },
      "ReportQueryRequestDto": {
        "required": [
          "filter",
          "sortBy"
        ],
        "type": "object",
        "properties": {
          "filter": {
            "type": [
              "null",
              "array"
            ],
            "items": {
              "$ref": "#/components/schemas/ReportFilterClauseDto"
            }
          },
          "sortBy": {
            "type": [
              "null",
              "string"
            ]
          },
          "desc": {
            "type": "boolean",
            "default": false
          },
          "cursor": {
            "type": [
              "null",
              "string"
            ]
          },
          "pageSize": {
            "type": [
              "null",
              "integer"
            ],
            "format": "int32"
          },
          "enrich": {
            "type": [
              "null",
              "array"
            ],
            "items": {
              "$ref": "#/components/schemas/ReportEnrichDto"
            }
          }
        },
        "description": "POST body for query_report."
      },
      "ReportQueryResultDto": {
        "required": [
          "columns",
          "rows",
          "rowCount",
          "cursor"
        ],
        "type": "object",
        "properties": {
          "columns": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "rows": {
            "type": "array",
            "items": {
              "type": "array"
            }
          },
          "rowCount": {
            "type": "integer",
            "format": "int32"
          },
          "cursor": {
            "type": [
              "null",
              "string"
            ]
          }
        },
        "description": "Columnar result: column names once, then rows as value arrays."
      },
      "ReportSummaryDto": {
        "required": [
          "name",
          "displayName",
          "description"
        ],
        "type": "object",
        "properties": {
          "name": {
            "type": "string"
          },
          "displayName": {
            "type": "string"
          },
          "description": {
            "type": [
              "null",
              "string"
            ]
          }
        },
        "description": "One report in the MCP-enabled list."
      },
      "ResolvedBrandDto": {
        "type": "object",
        "properties": {
          "brand": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "$ref": "#/components/schemas/BrandRefDto"
              }
            ]
          },
          "source": {
            "type": [
              "null",
              "string"
            ]
          },
          "explicitNone": {
            "type": "boolean"
          }
        },
        "description": "`source`: `variant`, `main` or `brand` (an open set); null when nothing resolves. `explicitNone`: a stored\n        \"none\" stopped inheritance."
      },
      "ResolvedDefaultDto": {
        "required": [
          "source"
        ],
        "type": "object",
        "properties": {
          "value": {
            "type": [
              "null",
              "string"
            ]
          },
          "source": {
            "type": "string"
          }
        },
        "description": "One resolved default: the value that was applied plus where it came from\n            (explicit | user | customer | pricelist | tenant). No silent defaults."
      },
      "ResolvedPartyDto": {
        "required": [
          "role"
        ],
        "type": "object",
        "properties": {
          "role": {
            "type": "string"
          },
          "party": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "$ref": "#/components/schemas/PartyContactDto"
              }
            ]
          },
          "source": {
            "type": [
              "null",
              "string"
            ]
          },
          "explicitNone": {
            "type": "boolean"
          }
        }
      },
      "RowErrorDto": {
        "required": [
          "index",
          "message"
        ],
        "type": "object",
        "properties": {
          "index": {
            "type": "integer",
            "format": "int32"
          },
          "message": {
            "type": "string"
          }
        },
        "description": "One refused row: its zero-based index in the request array, and why."
      },
      "SalesInvoiceDto": {
        "required": [
          "id",
          "documentType"
        ],
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "format": "int32"
          },
          "invoiceNumber": {
            "type": [
              "null",
              "integer"
            ],
            "format": "int32"
          },
          "customerId": {
            "type": [
              "null",
              "integer"
            ],
            "format": "int32"
          },
          "customerName": {
            "type": [
              "null",
              "string"
            ]
          },
          "customerOrgno": {
            "type": [
              "null",
              "string"
            ]
          },
          "statusId": {
            "type": [
              "null",
              "integer"
            ],
            "format": "int32"
          },
          "statusName": {
            "type": [
              "null",
              "string"
            ]
          },
          "dateInvoice": {
            "type": [
              "null",
              "string"
            ],
            "format": "date-time"
          },
          "dateDue": {
            "type": [
              "null",
              "string"
            ],
            "format": "date-time"
          },
          "dateOrder": {
            "type": [
              "null",
              "string"
            ],
            "format": "date-time"
          },
          "totalExVat": {
            "type": [
              "null",
              "number"
            ],
            "format": "double"
          },
          "totalVat": {
            "type": [
              "null",
              "number"
            ],
            "format": "double"
          },
          "totalIncVat": {
            "type": [
              "null",
              "number"
            ],
            "format": "double"
          },
          "openAmount": {
            "type": [
              "null",
              "number"
            ],
            "format": "double"
          },
          "paidAmount": {
            "type": [
              "null",
              "number"
            ],
            "format": "double"
          },
          "isLate": {
            "type": [
              "null",
              "boolean"
            ]
          },
          "isFullyPaid": {
            "type": [
              "null",
              "boolean"
            ]
          },
          "currencyIsoCode": {
            "type": [
              "null",
              "string"
            ]
          },
          "documentType": {
            "type": "string",
            "description": "\"invoice\" or \"credit\" — credit notes are SALESCREDIT documents and have negated amounts."
          }
        }
      },
      "SalesInvoiceLineDto": {
        "required": [
          "invoiceId",
          "lineId"
        ],
        "type": "object",
        "properties": {
          "invoiceId": {
            "type": "integer",
            "format": "int32"
          },
          "invoiceNumber": {
            "type": [
              "null",
              "integer"
            ],
            "format": "int32"
          },
          "lineId": {
            "type": "integer",
            "format": "int32"
          },
          "productId": {
            "type": [
              "null",
              "integer"
            ],
            "format": "int32"
          },
          "productNumber": {
            "type": [
              "null",
              "string"
            ]
          },
          "description": {
            "type": [
              "null",
              "string"
            ]
          },
          "quantity": {
            "type": "number",
            "format": "double"
          },
          "qtyDelivered": {
            "type": "number",
            "format": "double"
          },
          "price": {
            "type": [
              "null",
              "number"
            ],
            "format": "double"
          },
          "discount": {
            "type": "number",
            "format": "double"
          },
          "sumExVat": {
            "type": [
              "null",
              "number"
            ],
            "format": "double"
          },
          "sumIncVat": {
            "type": [
              "null",
              "number"
            ],
            "format": "double"
          },
          "dateInvoice": {
            "type": [
              "null",
              "string"
            ],
            "format": "date-time"
          },
          "customerId": {
            "type": [
              "null",
              "integer"
            ],
            "format": "int32"
          },
          "customerName": {
            "type": [
              "null",
              "string"
            ]
          },
          "currencyIsoCode": {
            "type": [
              "null",
              "string"
            ]
          }
        }
      },
      "SalesOrderAddressDto": {
        "required": [
          "type"
        ],
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "description": "delivery | invoice | other. An open set: accept values you do not know."
          },
          "name": {
            "type": [
              "null",
              "string"
            ]
          },
          "co": {
            "type": [
              "null",
              "string"
            ]
          },
          "street": {
            "type": [
              "null",
              "string"
            ]
          },
          "street2": {
            "type": [
              "null",
              "string"
            ]
          },
          "zip": {
            "type": [
              "null",
              "string"
            ]
          },
          "city": {
            "type": [
              "null",
              "string"
            ]
          },
          "country": {
            "type": [
              "null",
              "string"
            ],
            "description": "ISO 3166-1 alpha-2 country code, or null when the address has no known country."
          }
        },
        "description": "A postal address as stored on the order: no inference, no normalisation."
      },
      "SalesOrderContactDto": {
        "required": [
          "emails",
          "phones",
          "addresses"
        ],
        "type": "object",
        "properties": {
          "emails": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SalesOrderEmailDto"
            }
          },
          "phones": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SalesOrderPhoneDto"
            }
          },
          "addresses": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SalesOrderAddressDto"
            }
          }
        },
        "description": "The order's own active contact rows. Never the customer's."
      },
      "SalesOrderCreatedDto": {
        "required": [
          "id",
          "status",
          "currency",
          "vatType"
        ],
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "format": "int32"
          },
          "status": {
            "$ref": "#/components/schemas/ResolvedDefaultDto"
          },
          "currency": {
            "$ref": "#/components/schemas/ResolvedDefaultDto"
          },
          "vatType": {
            "$ref": "#/components/schemas/ResolvedDefaultDto"
          },
          "paymentTermId": {
            "type": [
              "null",
              "integer"
            ],
            "format": "int32"
          },
          "deliveryTermId": {
            "type": [
              "null",
              "integer"
            ],
            "format": "int32"
          },
          "priceListId": {
            "type": [
              "null",
              "integer"
            ],
            "format": "int32"
          },
          "lineIds": {
            "type": "array",
            "items": {
              "type": "integer",
              "format": "int32"
            }
          }
        }
      },
      "SalesOrderCreateDto": {
        "required": [
          "companyId"
        ],
        "type": "object",
        "properties": {
          "companyId": {
            "type": "integer",
            "format": "int32"
          },
          "name": {
            "type": [
              "null",
              "string"
            ]
          },
          "orderStatusId": {
            "type": [
              "null",
              "integer"
            ],
            "format": "int32"
          },
          "currencyIso": {
            "type": [
              "null",
              "string"
            ],
            "description": "ISO code, e.g. SEK. Omit to use the customer's currency."
          },
          "accVatTypeId": {
            "type": [
              "null",
              "integer"
            ],
            "description": "Momstyp id. Omit to use the customer's, falling back to the tenant default.",
            "format": "int32"
          },
          "dateOrder": {
            "type": [
              "null",
              "string"
            ],
            "format": "date-time"
          },
          "dateDelivery": {
            "type": [
              "null",
              "string"
            ],
            "format": "date-time"
          },
          "lines": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SalesOrderCreateLineDto"
            }
          }
        },
        "description": "Create a sales order. Everything except CompanyId is optional — omitted\n            fields resolve from the customer, then the tenant (the response says exactly what\n            was applied and from where). Lines are optional; they run through the same VAT\n            resolution as interactively added lines."
      },
      "SalesOrderCreateLineDto": {
        "type": "object",
        "properties": {
          "productId": {
            "type": [
              "null",
              "integer"
            ],
            "format": "int32"
          },
          "description": {
            "type": [
              "null",
              "string"
            ]
          },
          "quantity": {
            "type": "number",
            "format": "double"
          },
          "price": {
            "type": [
              "null",
              "number"
            ],
            "format": "double"
          },
          "discount": {
            "type": [
              "null",
              "number"
            ],
            "description": "Discount percent 0-100.",
            "format": "double"
          },
          "vatCodeId": {
            "type": [
              "null",
              "integer"
            ],
            "description": "Omit to resolve: order's exempt momstyp → product momskod → varugrupp\n            default → tenant standard rate.",
            "format": "int32"
          }
        }
      },
      "SalesOrderDetailDto": {
        "required": [
          "id"
        ],
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "format": "int32"
          },
          "name": {
            "type": [
              "null",
              "string"
            ]
          },
          "customerId": {
            "type": [
              "null",
              "integer"
            ],
            "format": "int32"
          },
          "customerName": {
            "type": [
              "null",
              "string"
            ]
          },
          "statusId": {
            "type": [
              "null",
              "integer"
            ],
            "format": "int32"
          },
          "statusName": {
            "type": [
              "null",
              "string"
            ]
          },
          "dateOrder": {
            "type": [
              "null",
              "string"
            ],
            "format": "date-time"
          },
          "dateDelivery": {
            "type": [
              "null",
              "string"
            ],
            "format": "date-time"
          },
          "dateInvoice": {
            "type": [
              "null",
              "string"
            ],
            "format": "date-time"
          },
          "currencyIsoCode": {
            "type": [
              "null",
              "string"
            ]
          },
          "accVatTypeId": {
            "type": [
              "null",
              "integer"
            ],
            "format": "int32"
          },
          "accVatTypeName": {
            "type": [
              "null",
              "string"
            ]
          },
          "accVatTypeExempt": {
            "type": [
              "null",
              "boolean"
            ]
          },
          "paymentTermId": {
            "type": [
              "null",
              "integer"
            ],
            "format": "int32"
          },
          "deliveryTermId": {
            "type": [
              "null",
              "integer"
            ],
            "format": "int32"
          },
          "priceListId": {
            "type": [
              "null",
              "integer"
            ],
            "format": "int32"
          },
          "lineCount": {
            "type": "integer",
            "format": "int32"
          },
          "totalExVat": {
            "type": "number",
            "format": "double"
          },
          "source": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "description": "Where the order came from; null when no known webshop or payment importer created it.",
                "$ref": "#/components/schemas/SalesOrderSourceDto"
              }
            ]
          }
        },
        "description": "Single-order detail — the header fields the list has, plus the accounting\n            context (momstyp, terms, price list) that decides how it invoices."
      },
      "SalesOrderDto": {
        "required": [
          "id"
        ],
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "format": "int32"
          },
          "name": {
            "type": [
              "null",
              "string"
            ]
          },
          "customerId": {
            "type": [
              "null",
              "integer"
            ],
            "format": "int32"
          },
          "customerName": {
            "type": [
              "null",
              "string"
            ]
          },
          "customerOrgno": {
            "type": [
              "null",
              "string"
            ]
          },
          "statusId": {
            "type": [
              "null",
              "integer"
            ],
            "format": "int32"
          },
          "statusName": {
            "type": [
              "null",
              "string"
            ]
          },
          "dateOrder": {
            "type": [
              "null",
              "string"
            ],
            "format": "date-time"
          },
          "dateDelivery": {
            "type": [
              "null",
              "string"
            ],
            "format": "date-time"
          },
          "dateInvoice": {
            "type": [
              "null",
              "string"
            ],
            "format": "date-time"
          },
          "dateDue": {
            "type": [
              "null",
              "string"
            ],
            "format": "date-time"
          },
          "totalExVat": {
            "type": [
              "null",
              "number"
            ],
            "format": "double"
          },
          "totalVat": {
            "type": [
              "null",
              "number"
            ],
            "format": "double"
          },
          "totalIncVat": {
            "type": [
              "null",
              "number"
            ],
            "format": "double"
          },
          "openAmount": {
            "type": [
              "null",
              "number"
            ],
            "format": "double"
          },
          "isLate": {
            "type": [
              "null",
              "boolean"
            ]
          },
          "isFullyPaid": {
            "type": [
              "null",
              "boolean"
            ]
          },
          "hasShipmentDiscrepancy": {
            "type": [
              "null",
              "boolean"
            ]
          },
          "currencyIsoCode": {
            "type": [
              "null",
              "string"
            ]
          },
          "lines": {
            "type": [
              "null",
              "array"
            ],
            "items": {
              "$ref": "#/components/schemas/SalesOrderLineDto"
            },
            "description": "Only with `include=lines`: exactly what `GET /sales-orders/{id}/lines` returns."
          },
          "fulfilment": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "description": "Only with `include=fulfilment`: exactly what `GET /sales-orders/{id}/fulfilment` returns.",
                "$ref": "#/components/schemas/SalesOrderFulfilmentDto"
              }
            ]
          }
        }
      },
      "SalesOrderEmailDto": {
        "required": [
          "type",
          "address"
        ],
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "description": "general | invoice. An open set: accept values you do not know. An invoice address can belong to an\n            invoice recipient rather than the buyer."
          },
          "address": {
            "type": "string"
          }
        }
      },
      "SalesOrderFulfilmentDto": {
        "required": [
          "warehouseOrders",
          "shipments"
        ],
        "type": "object",
        "properties": {
          "warehouseOrders": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SalesOrderWarehouseOrderDto"
            },
            "description": "One entry per warehouse order, newest first by warehouse order number (a heuristic: the warehouse numbers\n            orders in creation order). Usually one."
          },
          "shipments": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SalesOrderShipmentDto"
            },
            "description": "Every outbound parcel of every shipped warehouse order."
          }
        },
        "description": "The order at the warehouse and with the carrier, as last observed. Not a live read."
      },
      "SalesOrderLineAddDto": {
        "required": [
          "productId",
          "quantity"
        ],
        "type": "object",
        "properties": {
          "productId": {
            "type": "integer",
            "format": "int32"
          },
          "quantity": {
            "type": "number",
            "format": "double"
          },
          "price": {
            "type": [
              "null",
              "number"
            ],
            "format": "double"
          },
          "discount": {
            "type": [
              "null",
              "number"
            ],
            "format": "double"
          },
          "vatCodeId": {
            "type": [
              "null",
              "integer"
            ],
            "format": "int32"
          },
          "description": {
            "type": [
              "null",
              "string"
            ]
          },
          "productNumber": {
            "type": [
              "null",
              "string"
            ]
          }
        },
        "description": "Payload to add a line to a sales order. Maps onto the internal\n            OrderLineSave. ProductNumber/Description fall back to the product's own values\n            when blank; when VatCodeId is omitted it resolves upstream from the product's own\n            momskod, then the product's varugrupp default, then the tenant's standard (25%)\n            rate code."
      },
      "SalesOrderLineDto": {
        "required": [
          "lineId"
        ],
        "type": "object",
        "properties": {
          "lineId": {
            "type": "integer",
            "format": "int32"
          },
          "productId": {
            "type": [
              "null",
              "integer"
            ],
            "format": "int32"
          },
          "productNumber": {
            "type": [
              "null",
              "string"
            ]
          },
          "description": {
            "type": [
              "null",
              "string"
            ]
          },
          "quantity": {
            "type": "number",
            "format": "double"
          },
          "price": {
            "type": [
              "null",
              "number"
            ],
            "format": "double"
          },
          "discount": {
            "type": "number",
            "format": "double"
          },
          "vatCodeId": {
            "type": [
              "null",
              "integer"
            ],
            "format": "int32"
          },
          "lineTotalExVat": {
            "type": "number",
            "format": "double"
          },
          "sortId": {
            "type": "integer",
            "format": "int32"
          }
        },
        "description": "A single line on a sales order. decimal SalesOrderLineDto.LineTotalExVat is derived\n            (Quantity * Price * (100 - Discount) / 100) — line totals are never stored."
      },
      "SalesOrderLinePatchDto": {
        "type": "object",
        "properties": {
          "quantity": {
            "type": [
              "null",
              "number"
            ],
            "format": "double"
          },
          "price": {
            "type": [
              "null",
              "number"
            ],
            "format": "double"
          },
          "discount": {
            "type": [
              "null",
              "number"
            ],
            "format": "double"
          },
          "vatCodeId": {
            "type": [
              "null",
              "integer"
            ],
            "format": "int32"
          },
          "description": {
            "type": [
              "null",
              "string"
            ]
          },
          "productNumber": {
            "type": [
              "null",
              "string"
            ]
          }
        },
        "description": "Partial update of a sales-order line — only non-null fields change.\n            Maps onto the internal OrderLinePatch."
      },
      "SalesOrderPatchDto": {
        "type": "object",
        "properties": {
          "name": {
            "type": [
              "null",
              "string"
            ]
          },
          "accVatTypeId": {
            "type": [
              "null",
              "integer"
            ],
            "description": "Momstyp id. Alternative: AccVatTypeName.",
            "format": "int32"
          },
          "accVatTypeName": {
            "type": [
              "null",
              "string"
            ],
            "description": "Momstyp by name (e.g. \"Export\") — resolved case-insensitively; must\n            match exactly one type."
          },
          "applyVatTypeToLines": {
            "type": "boolean",
            "description": "When true (with a momstyp change or on its own), every line's VAT code\n            is rewritten to the order's momstyp mapping — the \"fix the VAT\" verb."
          },
          "dateDelivery": {
            "type": [
              "null",
              "string"
            ],
            "format": "date-time"
          },
          "dateInvoice": {
            "type": [
              "null",
              "string"
            ],
            "description": "Invoice date. Decides which VAT period the invoice lands in, so a run\n            committed in August for July's cutoff is normally dated the last day of July.",
            "format": "date-time"
          }
        },
        "description": "Partial header update: null means \"leave the field as it is\". Status is\n            deliberately NOT here — status transitions are workflow actions and stay in the UI."
      },
      "SalesOrderPatchResultDto": {
        "required": [
          "linesVatRewritten"
        ],
        "type": "object",
        "properties": {
          "linesVatRewritten": {
            "type": "integer",
            "format": "int32"
          }
        },
        "description": "How many of the order's lines had their VAT rewritten by the change."
      },
      "SalesOrderPaymentDto": {
        "required": [
          "provider",
          "state"
        ],
        "type": "object",
        "properties": {
          "provider": {
            "type": "string",
            "description": "kustom | qliro | walley. An open set: accept values you do not know."
          },
          "state": {
            "type": "string",
            "description": "reserved | partlyCaptured | captured | partlyRefunded | refunded | cancelled | expired | unknown. An open\n            set: accept values you do not know. \"unknown\" with null amounts means the provider could not be read."
          },
          "currency": {
            "type": [
              "null",
              "string"
            ]
          },
          "authorized": {
            "type": [
              "null",
              "number"
            ],
            "description": "Null when unknown. Never 0 for unknown.",
            "format": "double"
          },
          "captured": {
            "type": [
              "null",
              "number"
            ],
            "description": "Null when unknown. Never 0 for unknown.",
            "format": "double"
          },
          "refunded": {
            "type": [
              "null",
              "number"
            ],
            "description": "Null when unknown. Never 0 for unknown.",
            "format": "double"
          },
          "observedAt": {
            "type": [
              "null",
              "string"
            ],
            "description": "When the provider read completed; null when it failed or the account is disabled.",
            "format": "date-time"
          }
        }
      },
      "SalesOrderPaymentsDto": {
        "required": [
          "payments"
        ],
        "type": "object",
        "properties": {
          "payments": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SalesOrderPaymentDto"
            },
            "description": "One entry per payment link (split payments and retries give several). Empty when the order has none."
          }
        },
        "description": "The order's payments as the payment providers report them, cached for up to 60 seconds."
      },
      "SalesOrderPhoneDto": {
        "required": [
          "number"
        ],
        "type": "object",
        "properties": {
          "label": {
            "type": [
              "null",
              "string"
            ],
            "description": "The row's free-text description, or null. Not a phone type."
          },
          "number": {
            "type": "string"
          }
        }
      },
      "SalesOrderShipmentDto": {
        "type": "object",
        "properties": {
          "carrier": {
            "type": [
              "null",
              "string"
            ]
          },
          "service": {
            "type": [
              "null",
              "string"
            ]
          },
          "parcelNumber": {
            "type": [
              "null",
              "string"
            ]
          },
          "trackingUrl": {
            "type": [
              "null",
              "string"
            ]
          },
          "returnParcelNumber": {
            "type": [
              "null",
              "string"
            ]
          }
        }
      },
      "SalesOrderSourceDto": {
        "required": [
          "channel",
          "externalOrderId"
        ],
        "type": "object",
        "properties": {
          "channel": {
            "type": "string",
            "description": "woo | storefront | qliro | walley. An open set: accept values you do not know."
          },
          "site": {
            "type": [
              "null",
              "string"
            ],
            "description": "The shop's site code (for example \"de\"), or null when it is not known."
          },
          "shopOrderNumber": {
            "type": [
              "null",
              "string"
            ],
            "description": "The order number the buyer sees, or null when none is reliably stored. For Woo it is the order's current\n            name, which an edit can change."
          },
          "externalOrderId": {
            "type": "string",
            "description": "The platform's own id for the order."
          }
        },
        "description": "Where a sales order came from: the webshop or payment importer that created it. Null on the order when no\n            known origin matches, for example an order created by hand."
      },
      "SalesOrderWarehouseOrderDto": {
        "required": [
          "orderNumber",
          "status"
        ],
        "type": "object",
        "properties": {
          "orderNumber": {
            "type": "string",
            "description": "The warehouse system's own order id."
          },
          "status": {
            "type": "string",
            "description": "sentToWarehouse | atWarehouse | picking | shipped | delivered | returned | cancelled | error | unknown.\n            An open set: accept values you do not know. \"shipped\" includes collected by the carrier; \"delivered\" means\n            delivered to the recipient."
          },
          "statusText": {
            "type": [
              "null",
              "string"
            ],
            "description": "The warehouse's own wording for the status, or null when there is none."
          },
          "shippedAt": {
            "type": [
              "null",
              "string"
            ],
            "format": "date-time"
          },
          "partial": {
            "type": "boolean"
          },
          "observedAt": {
            "type": [
              "null",
              "string"
            ],
            "description": "When Asstio last read this status from the warehouse; null when the warehouse has not reported on it.",
            "format": "date-time"
          }
        }
      },
      "SearchRequest": {
        "required": [
          "from",
          "to",
          "customerId",
          "productId",
          "statusId",
          "includeNonSales",
          "cursor",
          "pageSize"
        ],
        "type": "object",
        "properties": {
          "from": {
            "type": [
              "null",
              "string"
            ],
            "format": "date-time"
          },
          "to": {
            "type": [
              "null",
              "string"
            ],
            "format": "date-time"
          },
          "customerId": {
            "type": [
              "null",
              "integer"
            ],
            "format": "int32"
          },
          "productId": {
            "type": [
              "null",
              "integer"
            ],
            "format": "int32"
          },
          "statusId": {
            "type": [
              "null",
              "integer"
            ],
            "format": "int32"
          },
          "includeNonSales": {
            "type": "boolean"
          },
          "cursor": {
            "type": [
              "null",
              "string"
            ]
          },
          "pageSize": {
            "type": [
              "null",
              "integer"
            ],
            "format": "int32"
          }
        }
      },
      "StoredBrandDto": {
        "required": [
          "state"
        ],
        "type": "object",
        "properties": {
          "state": {
            "type": "string"
          },
          "brand": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "$ref": "#/components/schemas/BrandRefDto"
              }
            ]
          }
        },
        "description": "`state`: `inherit`, `value` or `none` (an open set). `brand` only with `value`."
      },
      "StoredPartyDto": {
        "required": [
          "role",
          "state"
        ],
        "type": "object",
        "properties": {
          "role": {
            "type": "string"
          },
          "state": {
            "type": "string"
          },
          "party": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "$ref": "#/components/schemas/PartySummaryDto"
              }
            ]
          }
        }
      },
      "TimeReportLineDto": {
        "required": [
          "entryId"
        ],
        "type": "object",
        "properties": {
          "entryId": {
            "type": "integer",
            "format": "int32"
          },
          "personId": {
            "type": "integer",
            "format": "int32"
          },
          "personName": {
            "type": [
              "null",
              "string"
            ]
          },
          "date": {
            "type": "string",
            "format": "date-time"
          },
          "hours": {
            "type": "number",
            "format": "double"
          },
          "minutes": {
            "type": "integer",
            "format": "int32"
          },
          "description": {
            "type": [
              "null",
              "string"
            ]
          },
          "billable": {
            "type": "boolean"
          },
          "status": {
            "type": "string"
          },
          "invoicedOrderId": {
            "type": [
              "null",
              "integer"
            ],
            "format": "int32"
          },
          "invoicedOrderLineId": {
            "type": [
              "null",
              "integer"
            ],
            "format": "int32"
          },
          "customerId": {
            "type": [
              "null",
              "integer"
            ],
            "format": "int32"
          },
          "customerName": {
            "type": [
              "null",
              "string"
            ]
          },
          "billingOrderId": {
            "type": [
              "null",
              "integer"
            ],
            "description": "The order this entry is billing-targeted to, if any (from its TimeEntryLink).",
            "format": "int32"
          }
        },
        "description": "A logged time-report entry (one row of work hours). Hours = Minutes / 60.\n            Intended to be read and then billed onto a sales order via add_sales_order_line\n            (Quantity = Hours). string TimeReportLineDto.Status is \"open\" or \"invoiced\"."
      },
      "ValidationProblemDetails": {
        "type": "object",
        "properties": {
          "type": {
            "type": [
              "null",
              "string"
            ]
          },
          "title": {
            "type": [
              "null",
              "string"
            ]
          },
          "status": {
            "type": [
              "null",
              "integer"
            ],
            "format": "int32"
          },
          "detail": {
            "type": [
              "null",
              "string"
            ]
          },
          "instance": {
            "type": [
              "null",
              "string"
            ]
          },
          "errors": {
            "type": "object",
            "additionalProperties": {
              "type": "array",
              "items": {
                "type": "string"
              }
            }
          }
        }
      },
      "VatAccountSettingDto": {
        "required": [
          "id",
          "vatTypeId",
          "vatCodeId"
        ],
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "format": "int32"
          },
          "name": {
            "type": [
              "null",
              "string"
            ]
          },
          "vatTypeId": {
            "type": "integer",
            "format": "int32"
          },
          "vatTypeName": {
            "type": [
              "null",
              "string"
            ]
          },
          "vatCodeId": {
            "type": "integer",
            "format": "int32"
          },
          "vatRate": {
            "type": "number",
            "format": "double"
          },
          "euService": {
            "type": "boolean"
          },
          "vatCalculationMethod": {
            "type": "integer",
            "description": "0 Ingen, 1 Från netto, 2 Omvänd moms (äldre), 3 Omvänd moms.",
            "format": "int32"
          },
          "outputVatAccount": {
            "type": [
              "null",
              "string"
            ]
          },
          "inputVatAccount": {
            "type": [
              "null",
              "string"
            ]
          },
          "reverseChargeOutputVatAccount": {
            "type": [
              "null",
              "string"
            ]
          }
        },
        "description": "One momstyp × momssats row: which VAT accounts are hit and how VAT is computed."
      },
      "VatCodeDto": {
        "required": [
          "id"
        ],
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "format": "int32"
          },
          "name": {
            "type": [
              "null",
              "string"
            ]
          },
          "vatRate": {
            "type": "number",
            "format": "double"
          },
          "inactive": {
            "type": "boolean"
          }
        }
      },
      "VatConfigurationDto": {
        "required": [
          "vatTypes",
          "vatCodes",
          "vatAccountSettings",
          "productGroups",
          "productAccountSettings",
          "momsrapport"
        ],
        "type": "object",
        "properties": {
          "vatTypes": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/VatTypeDto"
            }
          },
          "vatCodes": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/VatCodeDto"
            }
          },
          "vatAccountSettings": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/VatAccountSettingDto"
            }
          },
          "productGroups": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ProductGroupDto"
            }
          },
          "productAccountSettings": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ProductAccountSettingDto"
            }
          },
          "momsrapport": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/MomsrapportRowDto"
            }
          }
        },
        "description": "Everything under Inställningar › Moms (Försäljning, Inköp, Grunddata, Momsdeklaration) in one read."
      },
      "VatTypeDto": {
        "required": [
          "id"
        ],
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "format": "int32"
          },
          "name": {
            "type": [
              "null",
              "string"
            ]
          },
          "exemptVat": {
            "type": "boolean"
          },
          "kind": {
            "type": [
              "null",
              "integer"
            ],
            "description": "0 Custom, 1 Domestic, 2 EuReverseCharge, 3 Export; null = unclassified.",
            "format": "uint8"
          }
        }
      },
      "VendorPriceDto": {
        "required": [
          "productId",
          "supplierId"
        ],
        "type": "object",
        "properties": {
          "productId": {
            "type": "integer",
            "format": "int32"
          },
          "productNumber": {
            "type": [
              "null",
              "string"
            ]
          },
          "supplierId": {
            "type": "integer",
            "format": "int32"
          },
          "supplierName": {
            "type": [
              "null",
              "string"
            ]
          },
          "supplierProductNumber": {
            "type": [
              "null",
              "string"
            ]
          },
          "supplierProductName": {
            "type": [
              "null",
              "string"
            ],
            "description": "The supplier's own name for the product, as it appears in their catalogue."
          },
          "price": {
            "type": [
              "null",
              "number"
            ],
            "format": "double"
          },
          "currencyIsoCode": {
            "type": [
              "null",
              "string"
            ]
          },
          "leadTimeDays": {
            "type": [
              "null",
              "integer"
            ],
            "description": "Configured purchasing lead time in days for this product/supplier pair. Null when not\n            configured — the purchase-suggestion engine then falls back to empirical lead time from receipt\n            history, which this field does not report.",
            "format": "int32"
          },
          "validFrom": {
            "type": [
              "null",
              "string"
            ],
            "description": "Reserved. Vendor prices carry no validity period yet — `CompanyProductLink`\n            has no such column, so this is always null. It stays in the contract because v1 is additive-only\n            (docs/PUBLIC_API.md); it will carry real data when vendor-price validity ships.",
            "format": "date-time"
          },
          "validTo": {
            "type": [
              "null",
              "string"
            ],
            "description": "Reserved, always null. See DateTimeOffset? VendorPriceDto.ValidFrom.",
            "format": "date-time"
          }
        }
      },
      "WarehouseStockRowDto": {
        "required": [
          "productId"
        ],
        "type": "object",
        "properties": {
          "productId": {
            "type": "integer",
            "format": "int32"
          },
          "productNumber": {
            "type": [
              "null",
              "string"
            ]
          },
          "productDescription": {
            "type": [
              "null",
              "string"
            ]
          },
          "warehouseId": {
            "type": [
              "null",
              "integer"
            ],
            "format": "int32"
          },
          "warehouseName": {
            "type": [
              "null",
              "string"
            ]
          },
          "locationId": {
            "type": [
              "null",
              "integer"
            ],
            "format": "int32"
          },
          "locationName": {
            "type": [
              "null",
              "string"
            ]
          },
          "qtyInStock": {
            "type": "number",
            "format": "double"
          },
          "qtyIncoming": {
            "type": "number",
            "format": "double"
          },
          "qtyOutgoing": {
            "type": "number",
            "format": "double"
          },
          "qtyDistributable": {
            "type": "number",
            "format": "double"
          }
        }
      }
    },
    "securitySchemes": {
      "bearer": {
        "type": "http",
        "description": "A Zitadel access token (JWT) for a user of the tenant, or an Asstio API key (asstio_…) created under Inställningar → API-nycklar. An API key is accepted in the Authorization header only, never in the query string.",
        "scheme": "bearer"
      }
    }
  },
  "security": [
    {
      "bearer": [ ]
    }
  ],
  "tags": [
    {
      "name": "WarehouseStockApi"
    },
    {
      "name": "VendorPricesApi"
    },
    {
      "name": "TimeReportLinesApi"
    },
    {
      "name": "TenantSettingsApi"
    },
    {
      "name": "SalesOrderLinesApi"
    },
    {
      "name": "SalesOrdersApi"
    },
    {
      "name": "SalesInvoicesApi"
    },
    {
      "name": "SalesInvoiceLinesApi"
    },
    {
      "name": "ReportsApi"
    },
    {
      "name": "PurchaseProposalsApi"
    },
    {
      "name": "PurchaseOrdersApi"
    },
    {
      "name": "PurchaseInvoiceMatchesApi"
    },
    {
      "name": "ProductCodesApi"
    },
    {
      "name": "ProductFindApi"
    },
    {
      "name": "ProductBulkApi"
    },
    {
      "name": "OpenOrderLinesApi"
    },
    {
      "name": "KanbanBoardsApi"
    },
    {
      "name": "KanbanCardsApi"
    },
    {
      "name": "DocumentsApi"
    },
    {
      "name": "CustomersApi"
    },
    {
      "name": "BrandsApi"
    },
    {
      "name": "PartiesApi"
    },
    {
      "name": "ProductBrandApi"
    },
    {
      "name": "ActivitiesApi"
    },
    {
      "name": "ActivityPeopleApi"
    },
    {
      "name": "ActivityTagsApi"
    },
    {
      "name": "ActivityTimelineApi"
    },
    {
      "name": "ActivityTypesApi"
    }
  ]
}