{
  "swagger": "2.0",
  "info": {
    "title": "Kelomo Public API",
    "version": "1.0",
    "description": "The published Kelomo REST API. Authenticate with an API key (`Authorization: Bearer kelomo_…`) minted in Settings → API access.\n\n**Reading this as raw JSON?** The same contract rendered, with search, examples and guides, is at https://kelomo.fi/developers/reference/\n\n- **Pagination.** List endpoints are cursor-paginated: `cursor`, `limit` → `pageInfo.nextCursor`. Lists with a real change stamp also accept `updatedSince` for incremental mirroring.\n- **Errors.** Every failure is an RFC 9457 `application/problem+json` document with a stable machine-readable `code`. Branch on `code`, never on `title` or `detail`. The catalogue is at https://kelomo.fi/developers/guides/error-codes/.\n- **Capabilities.** Each operation states the capability its key scope must contain (`x-kelomo-capabilities`, repeated in the description). Choosing too narrow a scope shows up as 403 `insufficient_role`.\n- **Idempotency.** Money-document writes require an `Idempotency-Key` header from API-key callers; the key deduplicates for 24 h.\n- **Tracing.** Every response carries `X-Request-Id`, mirrored in the problem body as `requestId`. Log it — support asks for it.\n- **Rate limits.** 600 requests/minute per key and 3000/minute per organisation; `X-RateLimit-*` and `RateLimit-Policy` report the binding budget, and a 429 carries `Retry-After`."
  },
  "host": "api.kelomo.fi",
  "basePath": "/",
  "schemes": [
    "https"
  ],
  "consumes": [
    "application/json"
  ],
  "produces": [
    "application/json"
  ],
  "tags": [
    {
      "name": "Me",
      "description": "The authenticated member’s own data: overview, entitlements, work days, balances and requests. Reachable with ANY key — an empty-scope key is exactly this surface."
    },
    {
      "name": "Members",
      "description": "Members of the organisation (the workforce roster) and their full provisioning lifecycle: create (one or in bulk), invite, update, place in planning units, record the employment window and terms, terminate, deactivate and reactivate. The sensitive personal tier (identity number, bank account, home address), versioned payroll configuration and GDPR erasure are deliberately not reachable here."
    },
    {
      "name": "Search",
      "description": "One aggregate quick-search across every entity family the caller may read. Groups the caller has no access to come back empty, so the response shape leaks nothing."
    },
    {
      "name": "Work days",
      "description": "Work-time bookkeeping: work days, entries and their confirmation lifecycle — including the supervisor-side write that imports a workforce’s hours. Drafts are freely rewritten; a confirmed or approved day is never edited in place, only moved by a lifecycle action (reopen, return, correct)."
    },
    {
      "name": "Presence",
      "description": "Who is at work right now — punch-derived presence."
    },
    {
      "name": "Balances",
      "description": "Balance accounts (flex, overtime, banked leave) and their transactions."
    },
    {
      "name": "Shifts",
      "description": "Planned shifts, publish events, open shifts and shift swaps."
    },
    {
      "name": "Absences",
      "description": "Absence periods, policies and leave balances. Absence types are masked by sensitivity exactly as in the UI."
    },
    {
      "name": "Trips",
      "description": "Travel claims: the caller’s own trips, their travel days (per diem, night allowance, free meals) and the claim lifecycle. A trip is created as a draft and reaches an approver only when it is submitted. Requires the travel-and-expense module (402 `feature_not_in_plan` otherwise)."
    },
    {
      "name": "Expenses",
      "description": "Expense claims: the caller’s own receipt, allowance and mileage lines, the expense-type catalogue they are priced from, and the claim lifecycle. Approving them is on the Approvals surface. Requires the travel-and-expense module (402 `feature_not_in_plan` otherwise)."
    },
    {
      "name": "Approvals",
      "description": "The unified approval queue: work days, absences, expenses and other pending decisions."
    },
    {
      "name": "Payroll exports",
      "description": "Payroll export batches: the frozen material handed to the payroll system."
    },
    {
      "name": "Billing exports",
      "description": "Billing export batches: invoice material handed to an external invoicing system."
    },
    {
      "name": "Invoices",
      "description": "Invoices and credit notes: drafting, issuing, dispatch (e-invoice/email) and renditions (PDF, Finvoice XML)."
    },
    {
      "name": "Payments",
      "description": "Accounts receivable: payments, allocations, bank imports (camt.054) and the AR aging view."
    },
    {
      "name": "Projects",
      "description": "Projects, phases, change orders, installments and purchases."
    },
    {
      "name": "Tasks",
      "description": "Work management tasks and their lifecycle."
    },
    {
      "name": "Quotes",
      "description": "Quotes: drafting, sending, customer decisions and conversion to projects."
    },
    {
      "name": "Customers",
      "description": "The customer register shared by CRM, projects and invoicing."
    },
    {
      "name": "CRM",
      "description": "Sales: leads, deals, pipelines, activities and the customer 360 view."
    },
    {
      "name": "Reports",
      "description": "Generated reports: a closed catalogue of report types rendered as JSON, PDF, XLSX or CSV."
    },
    {
      "name": "Catalogs",
      "description": "Tenant configuration catalogues: planning units, shift types, entry types, dimensions and staff groups."
    },
    {
      "name": "Imports",
      "description": "Migration bulk imports: the admin-only data on-ramp. A batch always answers 200 with a per-row outcome, and re-running the same rows skips what already exists."
    },
    {
      "name": "Integration events",
      "description": "The tenant’s integration-event log: the same truth webhooks fan out, readable for reconciliation and polling."
    },
    {
      "name": "Webhooks",
      "description": "Outgoing webhook endpoints, delivery log and signing-secret management."
    },
    {
      "name": "API keys",
      "description": "API key management (human sessions only — a key cannot manage keys)."
    },
    {
      "name": "Audit",
      "description": "The administrative audit trail."
    },
    {
      "name": "Attachments",
      "description": "File attachments: presigned upload, finalize and download URLs."
    },
    {
      "name": "Intake",
      "description": "Inbound work requests (the front door for “create a request from a form”)."
    }
  ],
  "paths": {
    "/v1/audit-events": {
      "get": {
        "operationId": "AuditController_list",
        "summary": "List audit events",
        "description": "**Capability:** `org.admin` — an API key must carry this in its scope.",
        "tags": [
          "Audit"
        ],
        "parameters": [
          {
            "name": "cursor",
            "required": false,
            "in": "query",
            "type": "string"
          },
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "minimum": 1,
            "maximum": 100,
            "default": 50,
            "type": "integer"
          },
          {
            "name": "q",
            "required": false,
            "in": "query",
            "maxLength": 100,
            "type": "string"
          },
          {
            "name": "from",
            "required": false,
            "in": "query",
            "description": "First calendar day of the window (inclusive). When omitted, the audit LISTING (GET /v1/audit-events) answers the last 90 days, ending at `to` or today; the CSV exports have no default and start at the beginning of the trail.",
            "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
            "type": "string"
          },
          {
            "name": "to",
            "required": false,
            "in": "query",
            "description": "Last calendar day of the window (inclusive).",
            "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
            "type": "string"
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/AuditEventPageResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/attachments": {
      "get": {
        "operationId": "AttachmentsController_list",
        "summary": "List the attachments of an owner object",
        "description": "Authorization follows the owner object. An API key reaches attachments of commercial objects only (deal, invoice, project, purchase, quote, task); HR, absence and whistleblowing documents are never available over the API, whatever the key’s scope.\n\n**Capability:** none — the operation acts as the authenticated member and its authorisation is row-level (ownership, the approver line, project membership). An API key with an empty scope reaches it.",
        "tags": [
          "Attachments"
        ],
        "parameters": [
          {
            "name": "ownerType",
            "required": true,
            "in": "query",
            "type": "string"
          },
          {
            "name": "ownerId",
            "required": true,
            "in": "query",
            "type": "string"
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/AttachmentListResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      },
      "post": {
        "operationId": "AttachmentsController_initiate",
        "summary": "Initiate an attachment upload",
        "description": "Two-phase upload: returns a presigned PUT URL; upload the bytes there, then call finalize. Authorization follows the owner object. An API key reaches attachments of commercial objects only (deal, invoice, project, purchase, quote, task); HR, absence and whistleblowing documents are never available over the API, whatever the key’s scope.\n\n**Capability:** none — the operation acts as the authenticated member and its authorisation is row-level (ownership, the approver line, project membership). An API key with an empty scope reaches it.",
        "tags": [
          "Attachments"
        ],
        "parameters": [
          {
            "name": "body",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/InitiateAttachmentDto"
            }
          }
        ],
        "responses": {
          "201": {
            "description": "Created.",
            "schema": {
              "$ref": "#/definitions/InitiateAttachmentResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/attachments/{id}/finalize": {
      "post": {
        "operationId": "AttachmentsController_finalize",
        "summary": "Finalize an uploaded attachment",
        "description": "Authorization follows the owner object. An API key reaches attachments of commercial objects only (deal, invoice, project, purchase, quote, task); HR, absence and whistleblowing documents are never available over the API, whatever the key’s scope.\n\n**Capability:** none — the operation acts as the authenticated member and its authorisation is row-level (ownership, the approver line, project membership). An API key with an empty scope reaches it.",
        "tags": [
          "Attachments"
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "type": "string"
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/AttachmentViewDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/attachments/{id}/url": {
      "get": {
        "operationId": "AttachmentsController_downloadUrl",
        "summary": "Get a short-lived download URL for an attachment",
        "description": "Authorization follows the owner object. An API key reaches attachments of commercial objects only (deal, invoice, project, purchase, quote, task); HR, absence and whistleblowing documents are never available over the API, whatever the key’s scope.\n\n**Capability:** none — the operation acts as the authenticated member and its authorisation is row-level (ownership, the approver line, project membership). An API key with an empty scope reaches it.",
        "tags": [
          "Attachments"
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "type": "string"
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/AttachmentDownloadResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/attachments/{id}": {
      "delete": {
        "operationId": "AttachmentsController_remove",
        "summary": "Delete an attachment",
        "description": "Authorization follows the owner object. An API key reaches attachments of commercial objects only (deal, invoice, project, purchase, quote, task); HR, absence and whistleblowing documents are never available over the API, whatever the key’s scope.\n\n**Capability:** none — the operation acts as the authenticated member and its authorisation is row-level (ownership, the approver line, project membership). An API key with an empty scope reaches it.",
        "tags": [
          "Attachments"
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "type": "string"
          }
        ],
        "responses": {
          "204": {
            "description": "No content."
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/me/work-days": {
      "get": {
        "operationId": "DaysController_getRange",
        "summary": "List the caller’s work days for a date range",
        "description": "**Capability:** none — the operation acts as the authenticated member and its authorisation is row-level (ownership, the approver line, project membership). An API key with an empty scope reaches it.",
        "tags": [
          "Me"
        ],
        "parameters": [
          {
            "name": "from",
            "required": true,
            "in": "query",
            "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
            "type": "string"
          },
          {
            "name": "to",
            "required": true,
            "in": "query",
            "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
            "type": "string"
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/WorkDayRangeResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/me/work-days/{date}": {
      "get": {
        "operationId": "DaysController_getDay",
        "summary": "Get one of the caller’s work days with entries",
        "description": "**Capability:** none — the operation acts as the authenticated member and its authorisation is row-level (ownership, the approver line, project membership). An API key with an empty scope reaches it.",
        "tags": [
          "Me"
        ],
        "parameters": [
          {
            "name": "date",
            "required": true,
            "in": "path",
            "type": "string"
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/WorkDayDetailResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/me/work-days/{date}/entries": {
      "put": {
        "operationId": "DaysController_setEntries",
        "summary": "Replace the caller’s work entries for a day",
        "description": "Full replacement of the day’s entries; idempotent. Draft days only — a confirmed day must be reopened first.\n\n**Capability:** none — the operation acts as the authenticated member and its authorisation is row-level (ownership, the approver line, project membership). An API key with an empty scope reaches it.",
        "tags": [
          "Me"
        ],
        "parameters": [
          {
            "name": "date",
            "required": true,
            "in": "path",
            "type": "string"
          },
          {
            "name": "body",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/SetWorkEntriesDto"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/WorkDayDetailResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/me/work-days/{date}/proposal-dismissal": {
      "delete": {
        "operationId": "DaysController_restoreProposal",
        "summary": "Show the caller’s day proposal again",
        "description": "Clearing a day also stops that day proposing itself: it then reads as an empty frame with no pre-fill, no sources and no expected window, and carries `proposalDismissed: true`. This drops that dismissal, so the next read derives the proposal as usual. Idempotent — a day that was never cleared answers 204 unchanged. The day’s recorded entries are never touched: restoring a proposal is a view decision about an unrecorded day, not an edit of a record.\n\n**Capability:** none — the operation acts as the authenticated member and its authorisation is row-level (ownership, the approver line, project membership). An API key with an empty scope reaches it.",
        "tags": [
          "Me"
        ],
        "parameters": [
          {
            "name": "date",
            "required": true,
            "in": "path",
            "type": "string"
          }
        ],
        "responses": {
          "204": {
            "description": "No content."
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/me/balance": {
      "get": {
        "operationId": "DaysController_balance",
        "summary": "Get the caller’s current flex balance",
        "description": "**Capability:** none — the operation acts as the authenticated member and its authorisation is row-level (ownership, the approver line, project membership). An API key with an empty scope reaches it.",
        "tags": [
          "Me"
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/BalanceResponseDto"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/staff-groups": {
      "get": {
        "operationId": "StaffGroupsController_list",
        "summary": "List staff groups",
        "description": "**Capability:** `worktime.supervise` or `payroll.run` — an API key must carry one of these in its scope.",
        "tags": [
          "Catalogs"
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/StaffGroupListResponseDto"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/me/work-days/{date}/confirm": {
      "post": {
        "operationId": "ConfirmationsController_confirm",
        "summary": "Confirm the caller’s work day",
        "description": "**Capability:** none — the operation acts as the authenticated member and its authorisation is row-level (ownership, the approver line, project membership). An API key with an empty scope reaches it.",
        "tags": [
          "Me"
        ],
        "parameters": [
          {
            "name": "date",
            "required": true,
            "in": "path",
            "type": "string"
          },
          {
            "name": "body",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/ConfirmWorkDayDto"
            }
          }
        ],
        "responses": {
          "201": {
            "description": "Created.",
            "schema": {
              "$ref": "#/definitions/ConfirmWorkDayResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/me/work-days/{date}/reopen": {
      "post": {
        "operationId": "ConfirmationsController_reopen",
        "summary": "Reopen the caller’s confirmed work day",
        "description": "Allowed only while the day is confirmed but not yet approved.\n\n**Capability:** none — the operation acts as the authenticated member and its authorisation is row-level (ownership, the approver line, project membership). An API key with an empty scope reaches it.",
        "tags": [
          "Me"
        ],
        "parameters": [
          {
            "name": "date",
            "required": true,
            "in": "path",
            "type": "string"
          }
        ],
        "responses": {
          "201": {
            "description": "Created.",
            "schema": {
              "$ref": "#/definitions/WorkDayActionResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/work-days/{id}/approve": {
      "post": {
        "operationId": "ConfirmationsController_approve",
        "summary": "Approve a confirmed work day",
        "description": "**Capability:** `worktime.supervise` — an API key must carry this in its scope.",
        "tags": [
          "Work days"
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "type": "string"
          },
          {
            "name": "body",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/ApproveWorkDayDto"
            }
          }
        ],
        "responses": {
          "201": {
            "description": "Created.",
            "schema": {
              "$ref": "#/definitions/WorkDayActionResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/work-days/approve-batch": {
      "post": {
        "operationId": "ConfirmationsController_approveBatch",
        "summary": "Approve several work days in one request",
        "description": "Batch form of the single-day approval: one request approves an explicit set of work-day ids, so a week never ends up half-approved by a client-side loop. The response reports the outcome per id.\n\n**Capability:** `worktime.supervise` — an API key must carry this in its scope.",
        "tags": [
          "Work days"
        ],
        "parameters": [
          {
            "name": "body",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/ApproveWorkDaysBatchDto"
            }
          }
        ],
        "responses": {
          "201": {
            "description": "Created.",
            "schema": {
              "$ref": "#/definitions/ApproveWorkDaysBatchResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/work-days/{id}/unapprove": {
      "post": {
        "operationId": "ConfirmationsController_unapprove",
        "summary": "Withdraw the approval of a work day",
        "description": "Undo for a mis-approval: an approved day that has NOT been exported goes back to confirmed and any bank movement the approval made is reversed by a counter-entry, never by deletion. Emits workday.unapproved. An exported or already-confirmed day answers 409 day_not_approved — after export the only route is correct. The transition is guarded on the day’s status, so a retry cannot unapprove twice.\n\n**Capability:** `worktime.supervise` — an API key must carry this in its scope.",
        "tags": [
          "Work days"
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "type": "string"
          }
        ],
        "responses": {
          "201": {
            "description": "Created.",
            "schema": {
              "$ref": "#/definitions/WorkDayActionResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/work-days/return-batch": {
      "post": {
        "operationId": "ConfirmationsController_returnBatch",
        "summary": "Return several work days to the employee in one request",
        "description": "Batch form of the single-day return (the twin of approve-batch): one request returns an explicit set of confirmed work-day ids to draft with one shared reason, so a week never ends up half-returned by a client-side loop. At most 500 ids. Each day is its own transaction and emits its own workday.returned — N days produce N events, not one — and days that can no longer act are reported per id in `skipped` instead of failing the batch.\n\n**Capability:** `worktime.supervise` — an API key must carry this in its scope.",
        "tags": [
          "Work days"
        ],
        "parameters": [
          {
            "name": "body",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/ReturnWorkDaysBatchDto"
            }
          }
        ],
        "responses": {
          "201": {
            "description": "Created.",
            "schema": {
              "$ref": "#/definitions/ReturnWorkDaysBatchResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/work-days/{id}/return": {
      "post": {
        "operationId": "ConfirmationsController_returnToDraft",
        "summary": "Return a work day to the employee for correction",
        "description": "**Capability:** `worktime.supervise` — an API key must carry this in its scope.",
        "tags": [
          "Work days"
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "type": "string"
          },
          {
            "name": "body",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/ReturnWorkDayDto"
            }
          }
        ],
        "responses": {
          "201": {
            "description": "Created.",
            "schema": {
              "$ref": "#/definitions/WorkDayActionResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/work-days/{id}/correct": {
      "post": {
        "operationId": "ConfirmationsController_correct",
        "summary": "Correct an approved or exported work day",
        "description": "The ONLY way to change a day that is past approval: the day returns to draft, a `correction` lifecycle event records who and why (reason required), bank movements from the approval are reversed by counter-entries, and the next payroll export picks the day up again with a correction marker — the batch already sent keeps its snapshot untouched. Nothing is edited in place. Emits workday.corrected. A day that is still draft or confirmed answers 409 day_not_correctable, a day inside a locked payroll period 409 period_locked, and a day whose hours are already invoiced 409 day_invoiced.\n\n**Capability:** `worktime.supervise` — an API key must carry this in its scope.",
        "tags": [
          "Work days"
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "type": "string"
          },
          {
            "name": "body",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/ReturnWorkDayDto"
            }
          }
        ],
        "responses": {
          "201": {
            "description": "Created.",
            "schema": {
              "$ref": "#/definitions/WorkDayActionResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/webhooks": {
      "get": {
        "operationId": "WebhooksController_list",
        "summary": "List webhook endpoints",
        "description": "**Capability:** `integrations.manage` — an API key must carry this in its scope.",
        "tags": [
          "Webhooks"
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/WebhookEndpointListResponseDto"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      },
      "post": {
        "operationId": "WebhooksController_create",
        "summary": "Create a webhook endpoint",
        "description": "The signing secret is returned once, in this response only.\n\n**Capability:** `integrations.manage` — an API key must carry this in its scope.",
        "tags": [
          "Webhooks"
        ],
        "parameters": [
          {
            "name": "body",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/CreateWebhookEndpointDto"
            }
          }
        ],
        "responses": {
          "201": {
            "description": "Created.",
            "schema": {
              "$ref": "#/definitions/CreateWebhookEndpointResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/webhooks/{id}": {
      "delete": {
        "operationId": "WebhooksController_remove",
        "summary": "Delete a webhook endpoint",
        "description": "**Capability:** `integrations.manage` — an API key must carry this in its scope.",
        "tags": [
          "Webhooks"
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "type": "string"
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/WebhookOkResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      },
      "patch": {
        "operationId": "WebhooksController_update",
        "summary": "Update a webhook endpoint",
        "description": "**Capability:** `integrations.manage` — an API key must carry this in its scope.",
        "tags": [
          "Webhooks"
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "type": "string"
          },
          {
            "name": "body",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/UpdateWebhookEndpointDto"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/WebhookOkResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/webhooks/{id}/rotate-secret": {
      "post": {
        "operationId": "WebhooksController_rotateSecret",
        "summary": "Rotate a webhook endpoint’s signing secret",
        "description": "The new secret is returned once, in this response only.\n\n**Capability:** `integrations.manage` — an API key must carry this in its scope.",
        "tags": [
          "Webhooks"
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "type": "string"
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/RotateWebhookSecretResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/webhooks/{id}/deliveries": {
      "get": {
        "operationId": "WebhooksController_deliveries",
        "summary": "List deliveries for a webhook endpoint",
        "description": "**Capability:** `integrations.manage` — an API key must carry this in its scope.",
        "tags": [
          "Webhooks"
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "type": "string"
          },
          {
            "name": "cursor",
            "required": false,
            "in": "query",
            "type": "string"
          },
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "minimum": 1,
            "maximum": 100,
            "default": 50,
            "type": "integer"
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/WebhookDeliveryPageResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/webhooks/{id}/deliveries/{deliveryId}/redeliver": {
      "post": {
        "operationId": "WebhooksController_redeliver",
        "summary": "Redeliver a webhook delivery",
        "description": "**Capability:** `integrations.manage` — an API key must carry this in its scope.",
        "tags": [
          "Webhooks"
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "type": "string"
          },
          {
            "name": "deliveryId",
            "required": true,
            "in": "path",
            "type": "string"
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/WebhookOkResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/webhooks/{id}/test": {
      "post": {
        "operationId": "WebhooksController_test",
        "summary": "Send a test event to a webhook endpoint",
        "description": "**Capability:** `integrations.manage` — an API key must carry this in its scope.",
        "tags": [
          "Webhooks"
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "type": "string"
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/WebhookOkResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/integration-events": {
      "get": {
        "operationId": "IntegrationEventsController_list",
        "summary": "List integration events",
        "description": "The same event log webhooks fan out. Asking for an event type outside the caller’s scope is refused (403), never a silently empty page.\n\n**Capability:** `integrations.manage` — an API key must carry this in its scope.",
        "tags": [
          "Integration events"
        ],
        "parameters": [
          {
            "name": "cursor",
            "required": false,
            "in": "query",
            "type": "string"
          },
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "minimum": 1,
            "maximum": 100,
            "default": 50,
            "type": "integer"
          },
          {
            "name": "event",
            "required": false,
            "in": "query",
            "type": "string",
            "enum": [
              "quote.decided",
              "batch.created",
              "status_update.posted",
              "deal.won",
              "lead.created",
              "workday.approved",
              "export_batch.created",
              "export_batch.delivered",
              "export_batch.delivery_failed",
              "absence.submitted",
              "absence.decided",
              "shift.published",
              "invoice.issued",
              "invoice.credited",
              "invoice.dispatched",
              "invoice.delivered",
              "invoice.delivery_failed",
              "payment.recorded",
              "payment.allocated",
              "payment.imported",
              "invoice.overdue",
              "invoice.drafts_ready",
              "recurring_plan.run_completed",
              "batch.delivered",
              "workday.confirmed",
              "workday.returned",
              "workday.corrected",
              "workday.unapproved",
              "absence.cancelled",
              "absence.certificate_provided",
              "shift.changed",
              "open_shift.claimed",
              "open_shift.claim_decided",
              "shift_swap.proposed",
              "shift_swap.decided",
              "export_batch.cancelled",
              "payroll_period.locked",
              "payroll_period.lock_lifted",
              "member.created",
              "member.invited",
              "member.deactivated",
              "employment.terminated",
              "task.created",
              "task.status_changed",
              "task.approval_responded",
              "quote.sent",
              "quote.accepted",
              "deal.lost",
              "deal.stage_changed",
              "lead.converted",
              "intake.received",
              "change_order.approved",
              "project.created",
              "project.closed",
              "contact.anonymized",
              "lead.anonymized",
              "invoice.paid",
              "customer.created",
              "customer.updated",
              "project.updated",
              "member.updated",
              "shift.unpublished"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/IntegrationEventPageResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/webhook-events": {
      "get": {
        "operationId": "WebhookEventsController_list",
        "summary": "List the webhook event catalogue",
        "description": "Every event Kelomo can deliver, with the capability a key must hold to subscribe and the JSON Schema (draft 2020-12) of the delivery’s `data` object. Deliveries carry identifiers, states and timestamps only — read the details you need through the API with the ids in the payload.\n\n**Capability:** none — the operation acts as the authenticated member and its authorisation is row-level (ownership, the approver line, project membership). An API key with an empty scope reaches it.",
        "tags": [
          "Webhooks"
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/WebhookEventCatalogResponseDto"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/me/entitlements": {
      "get": {
        "operationId": "CapabilitiesController_get",
        "summary": "Get the caller’s module entitlements",
        "description": "**Capability:** none — the operation acts as the authenticated member and its authorisation is row-level (ownership, the approver line, project membership). An API key with an empty scope reaches it.",
        "tags": [
          "Me"
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/MeEntitlementsResponseDto"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/me/trips": {
      "get": {
        "operationId": "TripsController_listMine",
        "summary": "List the caller’s own trips",
        "description": "Cursor-paginated, newest first. Optional `from`/`to` (trip start) and `status` narrow the set.\n\n**Capability:** none — the operation acts as the authenticated member and its authorisation is row-level (ownership, the approver line, project membership). An API key with an empty scope reaches it.",
        "tags": [
          "Trips"
        ],
        "parameters": [
          {
            "name": "cursor",
            "required": false,
            "in": "query",
            "type": "string"
          },
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "minimum": 1,
            "maximum": 100,
            "default": 50,
            "type": "integer"
          },
          {
            "name": "from",
            "required": true,
            "in": "query",
            "type": "string"
          },
          {
            "name": "to",
            "required": true,
            "in": "query",
            "type": "string"
          },
          {
            "name": "status",
            "required": true,
            "in": "query",
            "type": "string"
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/TripListResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      },
      "post": {
        "operationId": "TripsController_create",
        "summary": "Create a draft trip for the caller",
        "description": "Creates the trip as a DRAFT and materialises its travel days, so the per-diem and night-allowance entitlement is computed immediately — read the trip back to see it. `startAt`/`endAt` are instants, because a per diem is counted in 24-hour periods from departure, not in calendar days. A foreign trip needs the tenant’s foreign-travel setting on and takes `countryCode` to seed the first leg. Nothing is claimed until the trip is submitted.\n\n**Capability:** none — the operation acts as the authenticated member and its authorisation is row-level (ownership, the approver line, project membership). An API key with an empty scope reaches it.",
        "tags": [
          "Trips"
        ],
        "parameters": [
          {
            "name": "body",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/CreateTripDto"
            }
          }
        ],
        "responses": {
          "201": {
            "description": "Created.",
            "schema": {
              "$ref": "#/definitions/TripIdResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/me/trips/{id}": {
      "get": {
        "operationId": "TripsController_get",
        "summary": "Get one of the caller’s trips",
        "description": "The whole claim: the trip, its travel days with the resolved per-diem level and night allowance, its country legs and its expense lines.\n\n**Capability:** none for the caller's own record — its authorisation is row-level. Reaching ANOTHER member's record with an API key additionally requires `worktime.supervise` or `hr.manage` in the key's scope.",
        "tags": [
          "Trips"
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "type": "string"
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/TripViewDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      },
      "delete": {
        "operationId": "TripsController_remove",
        "summary": "Delete the caller’s draft trip",
        "description": "Draft trips only. Its travel days and inherited lines go with it.\n\n**Capability:** none — the operation acts as the authenticated member and its authorisation is row-level (ownership, the approver line, project membership). An API key with an empty scope reaches it.",
        "tags": [
          "Trips"
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "type": "string"
          }
        ],
        "responses": {
          "204": {
            "description": "No content."
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      },
      "patch": {
        "operationId": "TripsController_update",
        "summary": "Update the caller’s draft trip",
        "description": "Draft trips only. Changing the dates re-materialises the travel days; changing the project carries the new value onto the expense lines that were still inheriting it, and the response reports how many moved and how many a locked batch held back.\n\n**Capability:** none — the operation acts as the authenticated member and its authorisation is row-level (ownership, the approver line, project membership). An API key with an empty scope reaches it.",
        "tags": [
          "Trips"
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "type": "string"
          },
          {
            "name": "body",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/UpdateTripDto"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/UpdateTripResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/me/trips/{id}/days/{dayId}": {
      "patch": {
        "operationId": "TripsController_updateDay",
        "summary": "Adjust one travel day of the caller’s draft trip",
        "description": "Per-day inputs the automatic resolution cannot know: free meals received, an overnight stay, or a country pin that overrides the route. Draft trips only.\n\n**Capability:** none — the operation acts as the authenticated member and its authorisation is row-level (ownership, the approver line, project membership). An API key with an empty scope reaches it.",
        "tags": [
          "Trips"
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "type": "string"
          },
          {
            "name": "dayId",
            "required": true,
            "in": "path",
            "type": "string"
          },
          {
            "name": "body",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/UpdateTripDayDto"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/TripOkResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/me/trips/{id}/submit": {
      "post": {
        "operationId": "TripsController_submit",
        "summary": "Submit the caller’s trip for approval",
        "description": "Hands the whole claim — trip, travel days and its expense lines — to the approver and freezes the amounts. This is the step that turns a draft into a pending decision.\n\n**Capability:** none — the operation acts as the authenticated member and its authorisation is row-level (ownership, the approver line, project membership). An API key with an empty scope reaches it.",
        "tags": [
          "Trips"
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "type": "string"
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/TripOkResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/me/trips/{id}/reopen": {
      "post": {
        "operationId": "TripsController_reopen",
        "summary": "Reopen the caller’s submitted trip",
        "description": "Takes a submitted trip back to draft. An approved trip is not reopenable.\n\n**Capability:** none — the operation acts as the authenticated member and its authorisation is row-level (ownership, the approver line, project membership). An API key with an empty scope reaches it.",
        "tags": [
          "Trips"
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "type": "string"
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/TripOkResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/trips/{id}/approve": {
      "post": {
        "operationId": "TripsController_approve",
        "summary": "Approve a travel claim",
        "description": "The decision half of the `trip` rows in the approval queue. Requires supervisor authority over the traveller.\n\n**Capability:** `worktime.supervise` — an API key must carry this in its scope.",
        "tags": [
          "Approvals"
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "type": "string"
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/TripOkResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/trips/{id}/return": {
      "post": {
        "operationId": "TripsController_returnToDraft",
        "summary": "Return a travel claim to the traveller",
        "description": "The other decision half of the `trip` rows in the approval queue: the claim reopens as the traveller’s draft and the reason routes back to them. Requires supervisor authority over the traveller.\n\n**Capability:** `worktime.supervise` — an API key must carry this in its scope.",
        "tags": [
          "Approvals"
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "type": "string"
          },
          {
            "name": "body",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/ReturnTripDto"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/TripOkResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/projects": {
      "get": {
        "operationId": "ProjectsController_list",
        "summary": "List projects",
        "description": "The project register as a cursor-paginated list, ordered by project code. Filter with `customerId`, `id` or `q` (code/name typeahead). Pass `updatedSince` for an incremental sweep: the page then carries only projects changed at or after that instant, ordered by `updatedAt` — resume from the largest `updatedAt` you have stored and de-duplicate by `id`. Deleted projects never appear here; read them from `GET /v1/integration-events`.\n\n**Capability:** `projects.read` — an API key must carry this in its scope.",
        "tags": [
          "Projects"
        ],
        "parameters": [
          {
            "name": "cursor",
            "required": false,
            "in": "query",
            "type": "string"
          },
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "minimum": 1,
            "maximum": 100,
            "default": 50,
            "type": "integer"
          },
          {
            "name": "updatedSince",
            "required": false,
            "in": "query",
            "format": "date-time",
            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$",
            "type": "string"
          },
          {
            "name": "customerId",
            "required": false,
            "in": "query",
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
            "type": "string"
          },
          {
            "name": "id",
            "required": false,
            "in": "query",
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
            "type": "string"
          },
          {
            "name": "q",
            "required": false,
            "in": "query",
            "maxLength": 200,
            "type": "string"
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/ProjectListResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      },
      "post": {
        "operationId": "ProjectsController_create",
        "summary": "Create a project",
        "description": "**Capability:** `projects.manage` — an API key must carry this in its scope.",
        "tags": [
          "Projects"
        ],
        "parameters": [
          {
            "name": "body",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/CreateProjectDto"
            }
          }
        ],
        "responses": {
          "201": {
            "description": "Created.",
            "schema": {
              "$ref": "#/definitions/ProjectIdResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/projects/{id}/report": {
      "get": {
        "operationId": "ProjectsController_projectReport",
        "summary": "Get the margin report of a project for a period",
        "description": "**Capability:** `projects.read` — an API key must carry this in its scope.",
        "tags": [
          "Projects"
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "type": "string"
          },
          {
            "name": "from",
            "required": true,
            "in": "query",
            "type": "string"
          },
          {
            "name": "to",
            "required": true,
            "in": "query",
            "type": "string"
          },
          {
            "name": "tesCost",
            "required": false,
            "in": "query",
            "description": "Reprice the period through the payroll interpretation into `tesCost` (default true). Pass `false` when only the report meta is wanted — it is the expensive part of this call.",
            "enum": [
              "true",
              "false"
            ],
            "type": "string"
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/ProjectReportResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/projects/{id}": {
      "patch": {
        "operationId": "ProjectsController_update",
        "summary": "Update a project",
        "description": "**Capability:** `projects.manage` — an API key must carry this in its scope.",
        "tags": [
          "Projects"
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "type": "string"
          },
          {
            "name": "body",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/UpdateProjectDto"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/ProjectOkResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/projects/{id}/status-updates": {
      "get": {
        "operationId": "ProjectsController_statusUpdates",
        "summary": "List the status updates of a project",
        "description": "**Capability:** `projects.read` — an API key must carry this in its scope.",
        "tags": [
          "Projects"
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "type": "string"
          },
          {
            "name": "cursor",
            "required": false,
            "in": "query",
            "type": "string"
          },
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "minimum": 1,
            "maximum": 100,
            "default": 50,
            "type": "integer"
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/ProjectStatusUpdateListResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      },
      "post": {
        "operationId": "ProjectsController_createStatusUpdate",
        "summary": "Post a status update on a project",
        "description": "**Capability:** `projects.manage` — an API key must carry this in its scope.",
        "tags": [
          "Projects"
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "type": "string"
          },
          {
            "name": "body",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/CreateProjectStatusUpdateDto"
            }
          }
        ],
        "responses": {
          "201": {
            "description": "Created.",
            "schema": {
              "$ref": "#/definitions/ProjectStatusUpdateViewDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/projects/{id}/installments": {
      "get": {
        "operationId": "ProjectsController_listInstallments",
        "summary": "List the billing installments of a project",
        "description": "**Capability:** `projects.read` — an API key must carry this in its scope.",
        "tags": [
          "Projects"
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "type": "string"
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/ProjectInstallmentListResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/projects/{id}/purchases": {
      "get": {
        "operationId": "ProjectsController_listPurchases",
        "summary": "List the purchases of a project",
        "description": "**Capability:** `projects.read` — an API key must carry this in its scope.",
        "tags": [
          "Projects"
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "type": "string"
          },
          {
            "name": "from",
            "required": false,
            "in": "query",
            "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
            "type": "string"
          },
          {
            "name": "to",
            "required": false,
            "in": "query",
            "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
            "type": "string"
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/ProjectPurchaseListResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/projects/{id}/activity": {
      "get": {
        "operationId": "ProjectsController_activity",
        "summary": "Get the activity of a project for a period",
        "description": "**Capability:** `projects.read` — an API key must carry this in its scope.",
        "tags": [
          "Projects"
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "type": "string"
          },
          {
            "name": "from",
            "required": true,
            "in": "query",
            "type": "string"
          },
          {
            "name": "to",
            "required": true,
            "in": "query",
            "type": "string"
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/ProjectActivityResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/projects/{id}/phases": {
      "get": {
        "operationId": "ProjectsController_phases",
        "summary": "List the phases of a project",
        "description": "**Capability:** `projects.read` — an API key must carry this in its scope.",
        "tags": [
          "Projects"
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "type": "string"
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/ProjectPhaseListResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/export-batches": {
      "get": {
        "operationId": "ExportController_list",
        "summary": "List payroll export batches",
        "description": "**Capability:** `payroll.run` — an API key must carry this in its scope.",
        "tags": [
          "Payroll exports"
        ],
        "parameters": [
          {
            "name": "cursor",
            "required": false,
            "in": "query",
            "type": "string"
          },
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "minimum": 1,
            "maximum": 100,
            "default": 50,
            "type": "integer"
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/ExportBatchListResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      },
      "post": {
        "operationId": "ExportController_create",
        "summary": "Create a payroll export batch",
        "description": "**Capability:** `payroll.run` — an API key must carry this in its scope.",
        "tags": [
          "Payroll exports"
        ],
        "parameters": [
          {
            "name": "body",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/CreateExportBatchDto"
            }
          }
        ],
        "responses": {
          "201": {
            "description": "Created.",
            "schema": {
              "$ref": "#/definitions/ExportBatchViewDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/export-batches/preflight": {
      "get": {
        "operationId": "ExportController_preflight",
        "summary": "Check payroll export readiness for a period",
        "description": "Read-only pre-export verdict for `from`–`to`: exportable and still-unapproved day counts, carry-over from earlier periods, per-target pay-code coverage, non-blocking warnings and the calculation exceptions that block locking. Creates nothing. A single verdict object for one period, so it is not paginated.\n\n**Capability:** `payroll.run` — an API key must carry this in its scope.",
        "tags": [
          "Payroll exports"
        ],
        "parameters": [
          {
            "name": "from",
            "required": true,
            "in": "query",
            "type": "string"
          },
          {
            "name": "to",
            "required": true,
            "in": "query",
            "type": "string"
          },
          {
            "name": "groupId",
            "required": false,
            "in": "query",
            "type": "string"
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/ExportPreflightResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/export-batches/{id}/components": {
      "get": {
        "operationId": "ExportController_components",
        "summary": "Get the locked pay components of a batch",
        "description": "**Capability:** `payroll.run` — an API key must carry this in its scope.",
        "tags": [
          "Payroll exports"
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "type": "string"
          },
          {
            "name": "targetId",
            "required": false,
            "in": "query",
            "type": "string"
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/CalculationRunResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/export-batches/{id}/cancel": {
      "post": {
        "operationId": "ExportController_cancel",
        "summary": "Cancel a payroll export batch",
        "description": "**Capability:** `payroll.run` — an API key must carry this in its scope.",
        "tags": [
          "Payroll exports"
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "type": "string"
          },
          {
            "name": "body",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/CancelExportBatchDto"
            }
          }
        ],
        "responses": {
          "201": {
            "description": "Created.",
            "schema": {
              "$ref": "#/definitions/CancelExportBatchResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/team/members/{membershipId}/work-days": {
      "get": {
        "operationId": "TeamDaysController_getRange",
        "summary": "List work days for a member",
        "description": "**Capability:** `worktime.supervise` — an API key must carry this in its scope.",
        "tags": [
          "Work days"
        ],
        "parameters": [
          {
            "name": "membershipId",
            "required": true,
            "in": "path",
            "type": "string"
          },
          {
            "name": "from",
            "required": true,
            "in": "query",
            "type": "string"
          },
          {
            "name": "to",
            "required": true,
            "in": "query",
            "type": "string"
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/WorkDayRangeResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/team/members/{membershipId}/work-days/details": {
      "get": {
        "operationId": "TeamDaysController_getDayDetails",
        "summary": "Get a member’s work days with entries",
        "description": "The window form of GET /v1/team/members/{membershipId}/work-days/{date}: the SAME per-day content — entries, breaks, supplements, effective settings, the open correction request — for every day in [from, to], in one request. Days the member has no working-time model for are absent, exactly as the single-day route answers 404 for them. Beyond 31 days the request answers 422 range_too_long. Same authority as the single-day read; no on-behalf opt-in is required to READ.\n\n**Capability:** `worktime.supervise` — an API key must carry this in its scope.",
        "tags": [
          "Work days"
        ],
        "parameters": [
          {
            "name": "membershipId",
            "required": true,
            "in": "path",
            "type": "string"
          },
          {
            "name": "from",
            "required": true,
            "in": "query",
            "type": "string"
          },
          {
            "name": "to",
            "required": true,
            "in": "query",
            "type": "string"
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/WorkDayDetailRangeResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/team/members/{membershipId}/work-days/{date}": {
      "get": {
        "operationId": "TeamDaysController_getDay",
        "summary": "Get a member’s work day with entries",
        "description": "**Capability:** `worktime.supervise` — an API key must carry this in its scope.",
        "tags": [
          "Work days"
        ],
        "parameters": [
          {
            "name": "membershipId",
            "required": true,
            "in": "path",
            "type": "string"
          },
          {
            "name": "date",
            "required": true,
            "in": "path",
            "type": "string"
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/WorkDayDetailResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/team/members/{membershipId}/work-days/{date}/entries": {
      "put": {
        "operationId": "TeamDaysController_setEntries",
        "summary": "Replace a member’s work entries for a day",
        "description": "THE time-import route: writes one member’s day from an external system (a terminal, another time tracker, a migration). The request REPLACES the day’s entries in full, so re-sending the same body is idempotent — a retried import cannot double-write and needs no Idempotency-Key. Draft days only: a confirmed, approved or exported day answers 409 day_confirmed_locked and must go back to draft through reopen (confirmed) or correct (approved/exported) first — a record past the confirmation boundary is never edited in place. Requires the organisation’s “supervisor may act on behalf” setting and authority over the member.\n\n**Capability:** `worktime.supervise` — an API key must carry this in its scope.",
        "tags": [
          "Work days"
        ],
        "parameters": [
          {
            "name": "membershipId",
            "required": true,
            "in": "path",
            "type": "string"
          },
          {
            "name": "date",
            "required": true,
            "in": "path",
            "type": "string"
          },
          {
            "name": "body",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/SetWorkEntriesDto"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/WorkDayDetailResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/team/work-days/{date}/batch-entries": {
      "post": {
        "operationId": "TeamDaysController_batchEntries",
        "summary": "Write the same work day for several members",
        "description": "Batch form of PUT /v1/team/members/{membershipId}/work-days/{date}/entries: ONE day’s content — entries (with their stated breaks) or a full-day day type — written for up to 100 members at once, which is what a crew that worked the same Saturday needs. Each member is its own transaction with its own audit event, exactly as N separate calls would be; a member the caller may not act for (403 not_authorized / on_behalf_disabled) or whose day has left draft (409 day_confirmed_locked) is reported in `skipped` with that code instead of failing the batch. Beyond 100 members the request answers 422 batch_too_large. Because each member’s day is REPLACED in full, re-sending the same body is idempotent and needs no Idempotency-Key.\n\n**Capability:** `worktime.supervise` — an API key must carry this in its scope.",
        "tags": [
          "Work days"
        ],
        "parameters": [
          {
            "name": "date",
            "required": true,
            "in": "path",
            "type": "string"
          },
          {
            "name": "body",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/TeamBatchEntriesDto"
            }
          }
        ],
        "responses": {
          "201": {
            "description": "Created.",
            "schema": {
              "$ref": "#/definitions/TeamBatchEntriesResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/team/members/{membershipId}/work-days/{date}/day-type": {
      "put": {
        "operationId": "TeamDaysController_setDayType",
        "summary": "Set a member’s full-day day type",
        "description": "Marks the whole day as one day type (from GET /v1/day-types) instead of entries — the import path for “this day was a public holiday / a training day”. Full replacement of the day’s type, so re-sending it is idempotent. Draft days only (409 day_confirmed_locked otherwise).\n\n**Capability:** `worktime.supervise` — an API key must carry this in its scope.",
        "tags": [
          "Work days"
        ],
        "parameters": [
          {
            "name": "membershipId",
            "required": true,
            "in": "path",
            "type": "string"
          },
          {
            "name": "date",
            "required": true,
            "in": "path",
            "type": "string"
          },
          {
            "name": "body",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/SetDayTypeDto"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/WorkDayViewDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/team/members/{membershipId}/work-days/{date}/confirm": {
      "post": {
        "operationId": "TeamDaysController_confirm",
        "summary": "Confirm a member’s work day on their behalf",
        "description": "Asserts the day as the member’s record: it crosses the confirmation boundary (draft → confirmed) and writes an append-only lifecycle event naming the acting key. Emits workday.confirmed. A day that is already confirmed answers 409 day_already_confirmed, so a retried call cannot confirm twice; the transition is guarded on the day’s status, which is why no Idempotency-Key is required (send one anyway to replay the original response instead of the 409).\n\n**Capability:** `worktime.supervise` — an API key must carry this in its scope.",
        "tags": [
          "Work days"
        ],
        "parameters": [
          {
            "name": "membershipId",
            "required": true,
            "in": "path",
            "type": "string"
          },
          {
            "name": "date",
            "required": true,
            "in": "path",
            "type": "string"
          },
          {
            "name": "body",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/ConfirmWorkDayDto"
            }
          }
        ],
        "responses": {
          "201": {
            "description": "Created.",
            "schema": {
              "$ref": "#/definitions/ConfirmWorkDayResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/team/members/{membershipId}/work-days/confirm-range": {
      "post": {
        "operationId": "TeamDaysController_confirmRange",
        "summary": "Confirm a member’s work days over a date range",
        "description": "Confirms every day in the range that can confirm; days that cannot (already confirmed, empty free day) are SKIPPED, never failed, and counted in skippedCount. Each day is its own transaction and emits its own workday.confirmed — N days produce N events, not one. Maximum window 31 days (422 range_too_long beyond it). A retry is safe: already-confirmed days simply skip, so the second call reports actedCount 0 — send an Idempotency-Key to replay the original counts instead.\n\n**Capability:** `worktime.supervise` — an API key must carry this in its scope.",
        "tags": [
          "Work days"
        ],
        "parameters": [
          {
            "name": "membershipId",
            "required": true,
            "in": "path",
            "type": "string"
          },
          {
            "name": "body",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/RangeActionDto"
            }
          }
        ],
        "responses": {
          "201": {
            "description": "Created.",
            "schema": {
              "$ref": "#/definitions/RangeActionResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/team/members/{membershipId}/work-days/{date}/reopen": {
      "post": {
        "operationId": "TeamDaysController_reopen",
        "summary": "Reopen a member’s confirmed work day",
        "description": "Takes a confirmed (not yet approved) day back to draft so its entries can be written again — the way an import corrects a day it already confirmed. Records an append-only lifecycle event and emits workday.returned. Allowed only while the day is confirmed: a draft answers 409 day_already_editable and an approved day 409 day_already_approved (use correct instead).\n\n**Capability:** `worktime.supervise` — an API key must carry this in its scope.",
        "tags": [
          "Work days"
        ],
        "parameters": [
          {
            "name": "membershipId",
            "required": true,
            "in": "path",
            "type": "string"
          },
          {
            "name": "date",
            "required": true,
            "in": "path",
            "type": "string"
          }
        ],
        "responses": {
          "201": {
            "description": "Created.",
            "schema": {
              "$ref": "#/definitions/WorkDayActionResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/team/members/{membershipId}/work-days/reopen-range": {
      "post": {
        "operationId": "TeamDaysController_reopenRange",
        "summary": "Reopen a member’s confirmed work days over a date range",
        "description": "Range form of reopen: every still-confirmed day in the window goes back to draft, one transaction and one workday.returned event per day. Days that cannot reopen (already draft, approved, exported, or no row) are skipped, never failed. Maximum window 31 days (422 range_too_long beyond it).\n\n**Capability:** `worktime.supervise` — an API key must carry this in its scope.",
        "tags": [
          "Work days"
        ],
        "parameters": [
          {
            "name": "membershipId",
            "required": true,
            "in": "path",
            "type": "string"
          },
          {
            "name": "body",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/RangeActionDto"
            }
          }
        ],
        "responses": {
          "201": {
            "description": "Created.",
            "schema": {
              "$ref": "#/definitions/RangeActionResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/work-days": {
      "get": {
        "operationId": "WorkDayRegisterController_list",
        "summary": "List work days across the organisation",
        "description": "The stored work-day rows for an inclusive `from`–`to` window (max 366 days), cursor-paginated. Scoped like the team grid: admin and payroll read the whole organisation, a manager their own reports. Add `updatedSince` to read only what changed — the list then orders by `(updatedAt asc, id asc)` and the window still applies. Deletions never appear in a list; read them from `GET /v1/integration-events`. For the calculated day (target, applied credit, balance terms) read the per-member day detail.\n\n**Capability:** `worktime.supervise` or `payroll.run` — an API key must carry one of these in its scope.",
        "tags": [
          "Work days"
        ],
        "parameters": [
          {
            "name": "cursor",
            "required": false,
            "in": "query",
            "type": "string"
          },
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "minimum": 1,
            "maximum": 100,
            "default": 50,
            "type": "integer"
          },
          {
            "name": "updatedSince",
            "required": false,
            "in": "query",
            "format": "date-time",
            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$",
            "type": "string"
          },
          {
            "name": "from",
            "required": true,
            "in": "query",
            "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
            "type": "string"
          },
          {
            "name": "to",
            "required": true,
            "in": "query",
            "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
            "type": "string"
          },
          {
            "name": "membershipId",
            "required": false,
            "in": "query",
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
            "type": "string"
          },
          {
            "name": "status",
            "required": false,
            "in": "query",
            "type": "string",
            "enum": [
              "draft",
              "confirmed",
              "approved",
              "exported"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/WorkDayRegisterPageResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/customers/{id}/contacts": {
      "get": {
        "operationId": "ContactsController_list",
        "summary": "List the contacts of a customer",
        "description": "**Capability:** `crm.use` — an API key must carry this in its scope.",
        "tags": [
          "CRM"
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "type": "string"
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/ContactListResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      },
      "post": {
        "operationId": "ContactsController_create",
        "summary": "Create a contact for a customer",
        "description": "**Capability:** `crm.use` — an API key must carry this in its scope.",
        "tags": [
          "CRM"
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "type": "string"
          },
          {
            "name": "body",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/CreateContactDto"
            }
          }
        ],
        "responses": {
          "201": {
            "description": "Created.",
            "schema": {
              "$ref": "#/definitions/ContactViewDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/crm/contacts/{id}": {
      "patch": {
        "operationId": "CrmContactsController_update",
        "summary": "Update a contact",
        "description": "**Capability:** `crm.use` — an API key must carry this in its scope.",
        "tags": [
          "CRM"
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "type": "string"
          },
          {
            "name": "body",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/UpdateContactDto"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/ContactViewDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/customers/{id}/crm-360": {
      "get": {
        "operationId": "Customer360Controller_get360",
        "summary": "Get the 360-degree view of a customer",
        "description": "**Capability:** `crm.use` — an API key must carry this in its scope.",
        "tags": [
          "CRM"
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "type": "string"
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/Customer360ViewDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/crm/leads": {
      "get": {
        "operationId": "LeadsController_list",
        "summary": "List leads",
        "description": "**Capability:** `crm.use` — an API key must carry this in its scope.",
        "tags": [
          "CRM"
        ],
        "parameters": [
          {
            "name": "cursor",
            "required": false,
            "in": "query",
            "type": "string"
          },
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "minimum": 1,
            "maximum": 100,
            "default": 50,
            "type": "integer"
          },
          {
            "name": "updatedSince",
            "required": false,
            "in": "query",
            "format": "date-time",
            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$",
            "type": "string"
          },
          {
            "name": "status",
            "required": false,
            "in": "query",
            "type": "string",
            "enum": [
              "new",
              "working",
              "converted",
              "discarded"
            ]
          },
          {
            "name": "ownerMembershipId",
            "required": false,
            "in": "query",
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
            "type": "string"
          },
          {
            "name": "source",
            "required": false,
            "in": "query",
            "type": "string",
            "enum": [
              "manual",
              "intake",
              "import",
              "website",
              "referral",
              "other"
            ]
          },
          {
            "name": "q",
            "required": false,
            "in": "query",
            "maxLength": 200,
            "type": "string"
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/LeadPageResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      },
      "post": {
        "operationId": "LeadsController_create",
        "summary": "Create a lead",
        "description": "**Capability:** `crm.use` — an API key must carry this in its scope.",
        "tags": [
          "CRM"
        ],
        "parameters": [
          {
            "name": "body",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/CreateLeadDto"
            }
          }
        ],
        "responses": {
          "201": {
            "description": "Created.",
            "schema": {
              "$ref": "#/definitions/LeadViewDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/crm/leads/{id}": {
      "patch": {
        "operationId": "LeadsController_update",
        "summary": "Update a lead",
        "description": "**Capability:** `crm.use` — an API key must carry this in its scope.",
        "tags": [
          "CRM"
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "type": "string"
          },
          {
            "name": "body",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/UpdateLeadDto"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/LeadViewDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/crm/leads/{id}/convert": {
      "post": {
        "operationId": "LeadsController_convert",
        "summary": "Convert a lead into a customer and deal",
        "description": "**Capability:** `crm.use` — an API key must carry this in its scope.",
        "tags": [
          "CRM"
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "type": "string"
          },
          {
            "name": "body",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/ConvertLeadDto"
            }
          }
        ],
        "responses": {
          "201": {
            "description": "Created.",
            "schema": {
              "$ref": "#/definitions/ConvertLeadResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/crm/pipelines": {
      "get": {
        "operationId": "PipelinesController_list",
        "summary": "List pipelines with their stages",
        "description": "**Capability:** `crm.use` — an API key must carry this in its scope.",
        "tags": [
          "CRM"
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/PipelineListResponseDto"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/crm/deals": {
      "get": {
        "operationId": "DealsController_list",
        "summary": "List deals",
        "description": "**Capability:** `crm.use` — an API key must carry this in its scope.",
        "tags": [
          "CRM"
        ],
        "parameters": [
          {
            "name": "cursor",
            "required": false,
            "in": "query",
            "type": "string"
          },
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "minimum": 1,
            "maximum": 100,
            "default": 50,
            "type": "integer"
          },
          {
            "name": "updatedSince",
            "required": false,
            "in": "query",
            "format": "date-time",
            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$",
            "type": "string"
          },
          {
            "name": "pipelineId",
            "required": false,
            "in": "query",
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
            "type": "string"
          },
          {
            "name": "stageId",
            "required": false,
            "in": "query",
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
            "type": "string"
          },
          {
            "name": "status",
            "required": false,
            "in": "query",
            "type": "string",
            "enum": [
              "open",
              "won",
              "lost"
            ]
          },
          {
            "name": "ownerMembershipId",
            "required": false,
            "in": "query",
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
            "type": "string"
          },
          {
            "name": "customerId",
            "required": false,
            "in": "query",
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
            "type": "string"
          },
          {
            "name": "projectId",
            "required": false,
            "in": "query",
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
            "type": "string"
          },
          {
            "name": "q",
            "required": false,
            "in": "query",
            "maxLength": 200,
            "type": "string"
          },
          {
            "name": "tagId",
            "required": false,
            "in": "query",
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
            "type": "string"
          },
          {
            "name": "stale",
            "required": false,
            "in": "query",
            "type": "string",
            "enum": [
              "true",
              "false"
            ]
          },
          {
            "name": "sort",
            "required": false,
            "in": "query",
            "type": "string",
            "enum": [
              "createdAt",
              "valueCents",
              "expectedCloseDate",
              "nextActivityAt"
            ]
          },
          {
            "name": "direction",
            "required": false,
            "in": "query",
            "type": "string",
            "enum": [
              "asc",
              "desc"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/DealPageResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      },
      "post": {
        "operationId": "DealsController_create",
        "summary": "Create a deal",
        "description": "**Capability:** `crm.use` — an API key must carry this in its scope.",
        "tags": [
          "CRM"
        ],
        "parameters": [
          {
            "name": "body",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/CreateDealDto"
            }
          }
        ],
        "responses": {
          "201": {
            "description": "Created.",
            "schema": {
              "$ref": "#/definitions/DealViewDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/crm/deals/{id}": {
      "get": {
        "operationId": "DealsController_get",
        "summary": "Get a deal",
        "description": "**Capability:** `crm.use` — an API key must carry this in its scope.",
        "tags": [
          "CRM"
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "type": "string"
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/DealViewDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      },
      "patch": {
        "operationId": "DealsController_update",
        "summary": "Update a deal",
        "description": "**Capability:** `crm.use` — an API key must carry this in its scope.",
        "tags": [
          "CRM"
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "type": "string"
          },
          {
            "name": "body",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/UpdateDealDto"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/DealViewDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/crm/deals/{id}/stage": {
      "post": {
        "operationId": "DealsController_moveStage",
        "summary": "Move a deal to another pipeline stage",
        "description": "**Capability:** `crm.use` — an API key must carry this in its scope.",
        "tags": [
          "CRM"
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "type": "string"
          },
          {
            "name": "body",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/MoveDealStageDto"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/DealViewDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/crm/deals/{id}/win": {
      "post": {
        "operationId": "DealsController_win",
        "summary": "Mark a deal as won",
        "description": "**Capability:** `crm.use` — an API key must carry this in its scope.",
        "tags": [
          "CRM"
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "type": "string"
          },
          {
            "name": "body",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/WinDealDto"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/DealViewDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/crm/deals/{id}/lose": {
      "post": {
        "operationId": "DealsController_lose",
        "summary": "Mark a deal as lost",
        "description": "**Capability:** `crm.use` — an API key must carry this in its scope.",
        "tags": [
          "CRM"
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "type": "string"
          },
          {
            "name": "body",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/LoseDealDto"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/DealViewDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/crm/pipelines/{id}/board": {
      "get": {
        "operationId": "BoardController_board",
        "summary": "Get the deal board of a pipeline",
        "description": "**Capability:** `crm.use` — an API key must carry this in its scope.",
        "tags": [
          "CRM"
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "type": "string"
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/BoardViewDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/crm/activities": {
      "get": {
        "operationId": "ActivitiesController_list",
        "summary": "List CRM activities",
        "description": "**Capability:** `crm.use` — an API key must carry this in its scope.",
        "tags": [
          "CRM"
        ],
        "parameters": [
          {
            "name": "cursor",
            "required": false,
            "in": "query",
            "type": "string"
          },
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "minimum": 1,
            "maximum": 100,
            "default": 50,
            "type": "integer"
          },
          {
            "name": "customerId",
            "required": false,
            "in": "query",
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
            "type": "string"
          },
          {
            "name": "dealId",
            "required": false,
            "in": "query",
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
            "type": "string"
          },
          {
            "name": "leadId",
            "required": false,
            "in": "query",
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
            "type": "string"
          },
          {
            "name": "projectId",
            "required": false,
            "in": "query",
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
            "type": "string"
          },
          {
            "name": "ownerMembershipId",
            "required": false,
            "in": "query",
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
            "type": "string"
          },
          {
            "name": "type",
            "required": false,
            "in": "query",
            "type": "string",
            "enum": [
              "call",
              "meeting",
              "email",
              "note",
              "task"
            ]
          },
          {
            "name": "state",
            "required": false,
            "in": "query",
            "type": "string",
            "enum": [
              "open",
              "done"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/ActivityPageResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      },
      "post": {
        "operationId": "ActivitiesController_create",
        "summary": "Create an activity",
        "description": "**Capability:** `crm.use` — an API key must carry this in its scope.",
        "tags": [
          "CRM"
        ],
        "parameters": [
          {
            "name": "body",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/CreateActivityDto"
            }
          }
        ],
        "responses": {
          "201": {
            "description": "Created.",
            "schema": {
              "$ref": "#/definitions/ActivityViewDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/crm/activities/agenda": {
      "get": {
        "operationId": "ActivitiesController_agenda",
        "summary": "Get the sales activity agenda",
        "description": "**Capability:** `crm.use` — an API key must carry this in its scope.",
        "tags": [
          "CRM"
        ],
        "parameters": [
          {
            "name": "ownerMembershipId",
            "required": false,
            "in": "query",
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
            "type": "string"
          },
          {
            "name": "onDate",
            "required": false,
            "in": "query",
            "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
            "type": "string"
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/ActivityAgendaResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/crm/activities/{id}/done": {
      "post": {
        "operationId": "ActivitiesController_toggleDone",
        "summary": "Mark an activity done or reopen it",
        "description": "**Capability:** `crm.use` — an API key must carry this in its scope.",
        "tags": [
          "CRM"
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "type": "string"
          },
          {
            "name": "body",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/ToggleActivityDoneDto"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/ActivityViewDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/api-keys": {
      "get": {
        "operationId": "ApiKeysController_list",
        "summary": "List every API key in the organisation (human session required)",
        "description": "Includes the owner member each key executes as, so an offboarding can see what a leaver carries.\n\n**Capability:** `org.admin` — an API key must carry this in its scope.",
        "tags": [
          "API keys"
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/ApiKeyListResponseDto"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/api-keys/service": {
      "post": {
        "operationId": "ApiKeysController_createService",
        "summary": "Create a service API key with a named owner (human session required)",
        "description": "A service key belongs to the organisation and executes with the named owner member’s authority. The owner and the capabilities are both required, the capabilities must fit the owner’s effective set, and the key value is returned once, in this response only.\n\n**Capability:** `org.admin` — an API key must carry this in its scope.",
        "tags": [
          "API keys"
        ],
        "parameters": [
          {
            "name": "body",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/CreateServiceApiKeyDto"
            }
          }
        ],
        "responses": {
          "201": {
            "description": "Created.",
            "schema": {
              "$ref": "#/definitions/CreateApiKeyResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/api-keys/{id}/reassign": {
      "post": {
        "operationId": "ApiKeysController_reassign",
        "summary": "Reassign a service API key to another owner (human session required)",
        "description": "The token and its scopes are unchanged; only the executing identity moves. The scopes are re-validated against the new owner’s effective set.\n\n**Capability:** `org.admin` — an API key must carry this in its scope.",
        "tags": [
          "API keys"
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "type": "string"
          },
          {
            "name": "body",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/ReassignApiKeyDto"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/ApiKeyOkResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/api-keys/{id}": {
      "delete": {
        "operationId": "ApiKeysController_revoke",
        "summary": "Revoke any API key in the organisation (human session required)",
        "description": "**Capability:** `org.admin` — an API key must carry this in its scope.",
        "tags": [
          "API keys"
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "type": "string"
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/ApiKeyOkResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/me/api-keys": {
      "get": {
        "operationId": "MeApiKeysController_list",
        "summary": "List the caller’s own API keys (human session required)",
        "description": "**Capability:** none — the operation acts as the authenticated member and its authorisation is row-level (ownership, the approver line, project membership). An API key with an empty scope reaches it.",
        "tags": [
          "Me"
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/ApiKeyListResponseDto"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      },
      "post": {
        "operationId": "MeApiKeysController_create",
        "summary": "Create an API key for the caller (human session required)",
        "description": "The key acts as the caller: its capabilities must fit the caller’s own effective set. The key value is returned once, in this response only, and a key cannot manage keys.\n\n**Capability:** none — the operation acts as the authenticated member and its authorisation is row-level (ownership, the approver line, project membership). An API key with an empty scope reaches it.",
        "tags": [
          "Me"
        ],
        "parameters": [
          {
            "name": "body",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/CreateApiKeyDto"
            }
          }
        ],
        "responses": {
          "201": {
            "description": "Created.",
            "schema": {
              "$ref": "#/definitions/CreateApiKeyResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/me/api-keys/{id}/rotate": {
      "post": {
        "operationId": "MeApiKeysController_rotate",
        "summary": "Rotate the caller’s own API key (human session required)",
        "description": "The previous token keeps authenticating for 24 hours.\n\n**Capability:** none — the operation acts as the authenticated member and its authorisation is row-level (ownership, the approver line, project membership). An API key with an empty scope reaches it.",
        "tags": [
          "Me"
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "type": "string"
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/RotateApiKeyResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/me/api-keys/{id}": {
      "delete": {
        "operationId": "MeApiKeysController_revoke",
        "summary": "Revoke the caller’s own API key (human session required)",
        "description": "**Capability:** none — the operation acts as the authenticated member and its authorisation is row-level (ownership, the approver line, project membership). An API key with an empty scope reaches it.",
        "tags": [
          "Me"
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "type": "string"
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/ApiKeyOkResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/me/access": {
      "get": {
        "operationId": "AccessController_describe",
        "summary": "Describe the credential this request was made with",
        "description": "The member the call acts as, the capabilities it can actually exercise (the member’s effective set intersected with the key’s scope), the key’s own declaration, and the rate limits in force. Compare `capabilities` with an operation’s `x-kelomo-capabilities` when a call is refused with `insufficient_role`.\n\n**Capability:** none — the operation acts as the authenticated member and its authorisation is row-level (ownership, the approver line, project membership). An API key with an empty scope reaches it.",
        "tags": [
          "Me"
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/AccessContextDto"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/oauth-grants": {
      "get": {
        "operationId": "OAuthGrantsController_list",
        "summary": "List every connected app in the organisation (human session required)",
        "description": "One row per app-and-member connection, with the capabilities the member consented to and when the app last called. Revoked connections are omitted.\n\n**Capability:** `org.admin` — an API key must carry this in its scope.",
        "tags": [
          "API keys"
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/OAuthGrantListResponseDto"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/oauth-grants/{id}": {
      "delete": {
        "operationId": "OAuthGrantsController_revoke",
        "summary": "Disconnect any app in the organisation (human session required)",
        "description": "Ends the connection immediately: the refresh token family dies and the next call with an existing access token is refused.\n\n**Capability:** `org.admin` — an API key must carry this in its scope.",
        "tags": [
          "API keys"
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "type": "string"
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/OAuthGrantOkResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/me/oauth-grants": {
      "get": {
        "operationId": "MeOAuthGrantsController_list",
        "summary": "List the caller’s own connected apps (human session required)",
        "description": "**Capability:** none — the operation acts as the authenticated member and its authorisation is row-level (ownership, the approver line, project membership). An API key with an empty scope reaches it.",
        "tags": [
          "Me"
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/OAuthGrantListResponseDto"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/me/oauth-grants/{id}": {
      "delete": {
        "operationId": "MeOAuthGrantsController_revoke",
        "summary": "Disconnect one of the caller’s own apps (human session required)",
        "description": "**Capability:** none — the operation acts as the authenticated member and its authorisation is row-level (ownership, the approver line, project membership). An API key with an empty scope reaches it.",
        "tags": [
          "Me"
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "type": "string"
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/OAuthGrantOkResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/shift-plans": {
      "get": {
        "operationId": "ShiftPlansController_plan",
        "summary": "Get the shift plan of a planning unit for a date range",
        "description": "**Capability:** `scheduling.plan` — an API key must carry this in its scope.",
        "tags": [
          "Shifts"
        ],
        "parameters": [
          {
            "name": "planningUnitId",
            "required": true,
            "in": "query",
            "type": "string"
          },
          {
            "name": "from",
            "required": true,
            "in": "query",
            "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
            "type": "string"
          },
          {
            "name": "to",
            "required": true,
            "in": "query",
            "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
            "type": "string"
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/ShiftPlanResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/shift-plans/{planningUnitId}/uncovered": {
      "get": {
        "operationId": "ShiftPlansController_uncovered",
        "summary": "List published shifts in a unit whose assignee is absent",
        "description": "The coverage gaps of one planning unit over `from`–`to`: published shifts whose assignee is absent that day and therefore need cover. Read-only.\n\n**Capability:** `scheduling.plan` — an API key must carry this in its scope.",
        "tags": [
          "Shifts"
        ],
        "parameters": [
          {
            "name": "planningUnitId",
            "required": true,
            "in": "path",
            "type": "string"
          },
          {
            "name": "from",
            "required": true,
            "in": "query",
            "type": "string"
          },
          {
            "name": "to",
            "required": true,
            "in": "query",
            "type": "string"
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/UncoveredShiftListResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/shift-plans/publish-events": {
      "get": {
        "operationId": "ShiftPlansController_publishEvents",
        "summary": "List publish events of a planning unit",
        "description": "**Capability:** `scheduling.plan` — an API key must carry this in its scope.",
        "tags": [
          "Shifts"
        ],
        "parameters": [
          {
            "name": "planningUnitId",
            "required": true,
            "in": "query",
            "type": "string"
          },
          {
            "name": "cursor",
            "required": false,
            "in": "query",
            "type": "string"
          },
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "minimum": 1,
            "maximum": 100,
            "default": 50,
            "type": "integer"
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/PublishEventPageResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/planning-units": {
      "get": {
        "operationId": "PlanningUnitsController_list",
        "summary": "List planning units",
        "description": "**Capability:** `scheduling.plan` or `members.manage` — an API key must carry one of these in its scope.",
        "tags": [
          "Catalogs"
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/PlanningUnitListResponseDto"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/me/shifts": {
      "get": {
        "operationId": "MyShiftsController_myShifts",
        "summary": "List the caller’s published shifts for a date range",
        "description": "**Capability:** none — the operation acts as the authenticated member and its authorisation is row-level (ownership, the approver line, project membership). An API key with an empty scope reaches it.",
        "tags": [
          "Me"
        ],
        "parameters": [
          {
            "name": "from",
            "required": true,
            "in": "query",
            "type": "string"
          },
          {
            "name": "to",
            "required": true,
            "in": "query",
            "type": "string"
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/MyShiftsResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/me/open-shifts": {
      "get": {
        "operationId": "MyShiftsController_openShifts",
        "summary": "List open shifts offered to the caller, with own claim status",
        "description": "**Capability:** none — the operation acts as the authenticated member and its authorisation is row-level (ownership, the approver line, project membership). An API key with an empty scope reaches it.",
        "tags": [
          "Me"
        ],
        "parameters": [
          {
            "name": "cursor",
            "required": false,
            "in": "query",
            "type": "string"
          },
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "minimum": 1,
            "maximum": 100,
            "default": 50,
            "type": "integer"
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/OpenShiftPageResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/me/open-shifts/{id}/claim": {
      "post": {
        "operationId": "MyShiftsController_claim",
        "summary": "Claim an open shift offered to the caller",
        "description": "Registers the caller’s claim on an open shift from `GET /v1/me/open-shifts`. The claim is a request, not an assignment: a planner decides between the claims, and the shift lands on the roster only when one is approved. An optional message opens a thread with the claim.\n\n**Capability:** none — the operation acts as the authenticated member and its authorisation is row-level (ownership, the approver line, project membership). An API key with an empty scope reaches it.",
        "tags": [
          "Me"
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "type": "string"
          },
          {
            "name": "body",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/ClaimOpenShiftDto"
            }
          }
        ],
        "responses": {
          "201": {
            "description": "Created.",
            "schema": {
              "$ref": "#/definitions/SchedulingOkResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      },
      "delete": {
        "operationId": "MyShiftsController_withdrawClaim",
        "summary": "Withdraw the caller’s claim on an open shift",
        "description": "Removes the caller’s pending claim on an open shift. Only an undecided claim can be withdrawn.\n\n**Capability:** none — the operation acts as the authenticated member and its authorisation is row-level (ownership, the approver line, project membership). An API key with an empty scope reaches it.",
        "tags": [
          "Me"
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "type": "string"
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/SchedulingOkResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/me/unit-roster": {
      "get": {
        "operationId": "MyShiftsController_unitRoster",
        "summary": "List the published roster of the caller’s own unit",
        "description": "The published shifts of the caller’s planning unit over `from`–`to` (the direct-swap picker source), plus the caller’s units for the unit selector. A range-bounded read, so it is not paginated. Requires the tenant (or the caller’s unit) to have autonomous scheduling enabled.\n\n**Capability:** none — the operation acts as the authenticated member and its authorisation is row-level (ownership, the approver line, project membership). An API key with an empty scope reaches it.",
        "tags": [
          "Me"
        ],
        "parameters": [
          {
            "name": "from",
            "required": true,
            "in": "query",
            "type": "string"
          },
          {
            "name": "to",
            "required": true,
            "in": "query",
            "type": "string"
          },
          {
            "name": "unit",
            "required": false,
            "in": "query",
            "type": "string"
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/UnitRosterResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/open-shifts": {
      "get": {
        "operationId": "OpenShiftsController_list",
        "summary": "List open shifts of a planning unit, with pending claims",
        "description": "**Capability:** `scheduling.plan` — an API key must carry this in its scope.",
        "tags": [
          "Shifts"
        ],
        "parameters": [
          {
            "name": "planningUnitId",
            "required": true,
            "in": "query",
            "type": "string"
          },
          {
            "name": "cursor",
            "required": false,
            "in": "query",
            "type": "string"
          },
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "minimum": 1,
            "maximum": 100,
            "default": 50,
            "type": "integer"
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/OpenShiftPageResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/open-shifts/{id}/approve": {
      "post": {
        "operationId": "OpenShiftsController_approve",
        "summary": "Approve a member’s claim on an open shift",
        "description": "The decision half of the `open_shift_claim` rows in the approval queue: `membershipId` picks WHICH claimant gets the shift when several have claimed it.\n\n**Capability:** `scheduling.plan` — an API key must carry this in its scope.",
        "tags": [
          "Approvals"
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "type": "string"
          },
          {
            "name": "body",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/ResolveClaimDto"
            }
          }
        ],
        "responses": {
          "201": {
            "description": "Created.",
            "schema": {
              "$ref": "#/definitions/SchedulingOkResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/open-shifts/{id}/reject": {
      "post": {
        "operationId": "OpenShiftsController_reject",
        "summary": "Reject a member’s claim on an open shift",
        "description": "The other decision half of the `open_shift_claim` rows in the approval queue: `membershipId` picks WHICH claim is rejected, and the reason routes back to that claimant. The shift stays open for the remaining claims.\n\n**Capability:** `scheduling.plan` — an API key must carry this in its scope.",
        "tags": [
          "Approvals"
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "type": "string"
          },
          {
            "name": "body",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/ResolveClaimDto"
            }
          }
        ],
        "responses": {
          "201": {
            "description": "Created.",
            "schema": {
              "$ref": "#/definitions/SchedulingOkResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/shift-swaps": {
      "get": {
        "operationId": "ShiftSwapsController_list",
        "summary": "List shift swap requests of a planning unit",
        "description": "**Capability:** `scheduling.plan` — an API key must carry this in its scope.",
        "tags": [
          "Shifts"
        ],
        "parameters": [
          {
            "name": "planningUnitId",
            "required": true,
            "in": "query",
            "type": "string"
          },
          {
            "name": "cursor",
            "required": false,
            "in": "query",
            "type": "string"
          },
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "minimum": 1,
            "maximum": 100,
            "default": 50,
            "type": "integer"
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/ShiftSwapPageResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/shift-swaps/{id}/approve": {
      "post": {
        "operationId": "ShiftSwapsController_approve",
        "summary": "Approve a shift swap between two members",
        "description": "The decision half of the `swap` rows in the approval queue: both members’ published shifts change hands when the swap is approved.\n\n**Capability:** `scheduling.plan` — an API key must carry this in its scope.",
        "tags": [
          "Approvals"
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "type": "string"
          }
        ],
        "responses": {
          "201": {
            "description": "Created.",
            "schema": {
              "$ref": "#/definitions/SchedulingOkResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/shift-swaps/{id}/reject": {
      "post": {
        "operationId": "ShiftSwapsController_reject",
        "summary": "Reject a shift swap between two members",
        "description": "The other decision half of the `swap` rows in the approval queue: both members keep their published shifts and the reason routes back to the requester.\n\n**Capability:** `scheduling.plan` — an API key must carry this in its scope.",
        "tags": [
          "Approvals"
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "type": "string"
          },
          {
            "name": "body",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/RejectSwapDto"
            }
          }
        ],
        "responses": {
          "201": {
            "description": "Created.",
            "schema": {
              "$ref": "#/definitions/SchedulingOkResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/day-types": {
      "get": {
        "operationId": "DayTypesController_list",
        "summary": "List day types",
        "description": "**Capability:** none — the operation acts as the authenticated member and its authorisation is row-level (ownership, the approver line, project membership). An API key with an empty scope reaches it.",
        "tags": [
          "Catalogs"
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/DayTypeListResponseDto"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/entry-types": {
      "get": {
        "operationId": "EntryTypesController_list",
        "summary": "List work entry types",
        "description": "**Capability:** none — the operation acts as the authenticated member and its authorisation is row-level (ownership, the approver line, project membership). An API key with an empty scope reaches it.",
        "tags": [
          "Catalogs"
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/EntryTypeListResponseDto"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/break-types": {
      "get": {
        "operationId": "BreakTypesController_list",
        "summary": "List break types",
        "description": "**Capability:** none — the operation acts as the authenticated member and its authorisation is row-level (ownership, the approver line, project membership). An API key with an empty scope reaches it.",
        "tags": [
          "Catalogs"
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/BreakTypeListResponseDto"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/shift-types": {
      "get": {
        "operationId": "ShiftTypesController_list",
        "summary": "List shift types",
        "description": "**Capability:** none — the operation acts as the authenticated member and its authorisation is row-level (ownership, the approver line, project membership). An API key with an empty scope reaches it.",
        "tags": [
          "Catalogs"
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/ShiftTypeListResponseDto"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/balance-transactions": {
      "get": {
        "operationId": "BalancesController_list",
        "summary": "List a member’s balance transactions",
        "description": "**Capability:** `payroll.run` — an API key must carry this in its scope.",
        "tags": [
          "Balances"
        ],
        "parameters": [
          {
            "name": "membershipId",
            "required": true,
            "in": "query",
            "type": "string"
          },
          {
            "name": "cursor",
            "required": false,
            "in": "query",
            "type": "string"
          },
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "minimum": 1,
            "maximum": 100,
            "default": 50,
            "type": "integer"
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/BalanceTransactionListResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/me/balance-transactions": {
      "get": {
        "operationId": "MeBalanceTransactionsController_list",
        "summary": "List the caller’s balance transactions",
        "description": "**Capability:** none — the operation acts as the authenticated member and its authorisation is row-level (ownership, the approver line, project membership). An API key with an empty scope reaches it.",
        "tags": [
          "Me"
        ],
        "parameters": [
          {
            "name": "cursor",
            "required": false,
            "in": "query",
            "type": "string"
          },
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "minimum": 1,
            "maximum": 100,
            "default": 50,
            "type": "integer"
          },
          {
            "name": "accountTypeId",
            "required": true,
            "in": "query",
            "type": "string"
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/BalanceTransactionListResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/balance-account-types": {
      "get": {
        "operationId": "BalanceAccountTypesController_list",
        "summary": "List balance account types",
        "description": "**Capability:** none — the operation acts as the authenticated member and its authorisation is row-level (ownership, the approver line, project membership). An API key with an empty scope reaches it.",
        "tags": [
          "Balances"
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/BalanceAccountTypeListResponseDto"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/dimensions": {
      "get": {
        "operationId": "DimensionsController_list",
        "summary": "List tracking dimensions",
        "description": "**Capability:** none — the operation acts as the authenticated member and its authorisation is row-level (ownership, the approver line, project membership). An API key with an empty scope reaches it.",
        "tags": [
          "Catalogs"
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/DimensionListResponseDto"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/customers": {
      "get": {
        "operationId": "CustomersController_list",
        "summary": "List customers",
        "description": "Buyer billing identifiers are masked for manager-tier callers exactly as in the UI.\n\n**Capability:** `crm.use` or `payroll.run` — an API key must carry one of these in its scope.",
        "tags": [
          "Customers"
        ],
        "parameters": [
          {
            "name": "cursor",
            "required": false,
            "in": "query",
            "type": "string"
          },
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "minimum": 1,
            "maximum": 100,
            "default": 50,
            "type": "integer"
          },
          {
            "name": "updatedSince",
            "required": false,
            "in": "query",
            "format": "date-time",
            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$",
            "type": "string"
          },
          {
            "name": "q",
            "required": false,
            "in": "query",
            "minLength": 1,
            "maxLength": 200,
            "type": "string"
          },
          {
            "name": "ownerMembershipId",
            "required": false,
            "in": "query",
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
            "type": "string"
          },
          {
            "name": "tagId",
            "required": false,
            "in": "query",
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
            "type": "string"
          },
          {
            "name": "includeInactive",
            "required": false,
            "in": "query",
            "type": "string",
            "enum": [
              "true",
              "false"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/CustomerPageResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      },
      "post": {
        "operationId": "CustomersController_create",
        "summary": "Create a customer",
        "description": "**Capability:** `crm.use` or `projects.manage` — an API key must carry one of these in its scope.",
        "tags": [
          "Customers"
        ],
        "parameters": [
          {
            "name": "body",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/CreateCustomerDto"
            }
          }
        ],
        "responses": {
          "201": {
            "description": "Created.",
            "schema": {
              "$ref": "#/definitions/CustomerIdResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/customers/{id}": {
      "get": {
        "operationId": "CustomersController_get",
        "summary": "Get a customer",
        "description": "Buyer billing identifiers are masked for manager-tier callers exactly as in the UI.\n\n**Capability:** `crm.use` or `payroll.run` — an API key must carry one of these in its scope.",
        "tags": [
          "Customers"
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "type": "string"
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/CustomerGetResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      },
      "patch": {
        "operationId": "CustomersController_update",
        "summary": "Update a customer",
        "description": "**Capability:** `crm.use` or `projects.manage` — an API key must carry one of these in its scope.",
        "tags": [
          "Customers"
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "type": "string"
          },
          {
            "name": "body",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/UpdateCustomerDto"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/CustomerOkResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/memberships/{id}/employment": {
      "get": {
        "operationId": "EmploymentController_get",
        "summary": "Get the member’s employment terms",
        "description": "The terms record behind the PUT below — job title, employment and pay type, fixed-term grounds and end date, probation, contract hours, place of work, employer, payroll number and insurers. Published because the PUT is a full replace: read this, change what you mean to change, send the whole object back. Carries no monetary amounts and none of the sensitive personal tier (identity number, bank account, home address are not reachable over the API at all). Requires the HR add-on module; a supervisor reads it only when the organisation allows it (`403 manager_terms_read_disabled`).\n\n**Capability:** `reports.team` — an API key must carry this in its scope.",
        "tags": [
          "Members"
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "type": "string"
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/EmploymentResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      },
      "put": {
        "operationId": "EmploymentController_update",
        "summary": "Replace the member’s employment terms",
        "description": "Full REPLACE, not a patch: every omitted optional field is CLEARED, so read `GET /v1/memberships/{id}/employment` first and send the whole object back. `employmentType` and `payType` are required. Fixed-term employment requires written grounds (`422 fixed_term_requires_grounds`, Employment Contracts Act 1:3). This is the terms record; the employment WINDOW (start/end dates) is on `PATCH /v1/memberships/{id}`, and DATED terms changes — the version history payroll calculates historical weeks from — are deliberately not part of the public API. A PUT is a correction of the CURRENT terms: it keeps the open version in step and never rewrites a closed one. Requires the HR add-on module. Fires `member.updated`.\n\n**Capability:** `hr.manage` — an API key must carry this in its scope.",
        "tags": [
          "Members"
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "type": "string"
          },
          {
            "name": "body",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/UpdateEmploymentDto"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/EmploymentOkResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/memberships/{id}/payroll-identity": {
      "get": {
        "operationId": "PayrollIdentityController_get",
        "summary": "Read a member’s payroll identifier",
        "description": "**Capability:** `payroll.run` — an API key must carry this in its scope.",
        "tags": [
          "Members"
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "type": "string"
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/PayrollIdentityViewDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      },
      "put": {
        "operationId": "PayrollIdentityController_update",
        "summary": "Set a member’s payroll identifier",
        "description": "**Capability:** `payroll.run` — an API key must carry this in its scope.",
        "tags": [
          "Members"
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "type": "string"
          },
          {
            "name": "body",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/UpdatePayrollIdentityDto"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/EmploymentOkResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/memberships/{id}/termination": {
      "post": {
        "operationId": "EmploymentLifecycleController_terminate",
        "summary": "Record a termination",
        "description": "Records the end of the employment: writes the member’s `employmentEndDate`, the coded `reasonCode`, the `noticeDate` that anchors the notice period and an optional note, and starts an offboarding checklist run when `startOffboarding` is true. It does NOT deactivate the member — the end-date sweep does that on the day itself, or call `POST /v1/memberships/{id}/deactivate` explicitly. Repeating the call overwrites the record rather than adding a second one. `422 termination_end_before_start`. Requires the HR add-on module. Fires `employment.terminated` (identifiers and end date only — the reason and the note never ride the event).\n\n**Capability:** `hr.manage` — an API key must carry this in its scope.",
        "tags": [
          "Members"
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "type": "string"
          },
          {
            "name": "body",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/TerminateEmploymentDto"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/TerminationResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      },
      "delete": {
        "operationId": "EmploymentLifecycleController_cancel",
        "summary": "Cancel a recorded termination",
        "description": "Clears the end date and the termination fields. Deliberately narrow: it does not cancel an offboarding checklist run and does not reactivate a member the end-date sweep already deactivated — both are separate, separately-audited operations (`POST /v1/memberships/{id}/reactivate`). `404 termination_not_found` when nothing is recorded. Requires the HR add-on module. Fires `member.updated`.\n\n**Capability:** `hr.manage` — an API key must carry this in its scope.",
        "tags": [
          "Members"
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "type": "string"
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/TerminationResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/me/absence/policies": {
      "get": {
        "operationId": "AbsenceController_listPolicies",
        "summary": "List absence policies the caller can request",
        "description": "**Capability:** none — the operation acts as the authenticated member and its authorisation is row-level (ownership, the approver line, project membership). An API key with an empty scope reaches it.",
        "tags": [
          "Me"
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/AbsencePolicyListResponseDto"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/me/absence-periods": {
      "get": {
        "operationId": "AbsenceController_listMine",
        "summary": "List the caller’s absence periods for a date range",
        "description": "**Capability:** none — the operation acts as the authenticated member and its authorisation is row-level (ownership, the approver line, project membership). An API key with an empty scope reaches it.",
        "tags": [
          "Me"
        ],
        "parameters": [
          {
            "name": "from",
            "required": true,
            "in": "query",
            "type": "string"
          },
          {
            "name": "to",
            "required": true,
            "in": "query",
            "type": "string"
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/AbsencePeriodListResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      },
      "post": {
        "operationId": "AbsenceController_create",
        "summary": "Create a draft absence request for the caller",
        "description": "**Capability:** none — the operation acts as the authenticated member and its authorisation is row-level (ownership, the approver line, project membership). An API key with an empty scope reaches it.",
        "tags": [
          "Me"
        ],
        "parameters": [
          {
            "name": "body",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/CreateAbsencePeriodDto"
            }
          }
        ],
        "responses": {
          "201": {
            "description": "Created.",
            "schema": {
              "$ref": "#/definitions/AbsencePeriodDetailDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/me/absence-periods/preview": {
      "post": {
        "operationId": "AbsenceController_preview",
        "summary": "Preview an absence request’s day resolution and balance impact",
        "description": "**Capability:** none — the operation acts as the authenticated member and its authorisation is row-level (ownership, the approver line, project membership). An API key with an empty scope reaches it.",
        "tags": [
          "Me"
        ],
        "parameters": [
          {
            "name": "body",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/PreviewAbsencePeriodDto"
            }
          }
        ],
        "responses": {
          "201": {
            "description": "Created.",
            "schema": {
              "$ref": "#/definitions/AbsencePeriodPreviewDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/me/absence-periods/{id}/submit": {
      "post": {
        "operationId": "AbsenceController_submit",
        "summary": "Submit the caller’s absence request for approval",
        "description": "**Capability:** none — the operation acts as the authenticated member and its authorisation is row-level (ownership, the approver line, project membership). An API key with an empty scope reaches it.",
        "tags": [
          "Me"
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "type": "string"
          },
          {
            "name": "body",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/SubmitAbsencePeriodDto"
            }
          }
        ],
        "responses": {
          "201": {
            "description": "Created.",
            "schema": {
              "$ref": "#/definitions/AbsencePeriodDetailDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/me/absence-periods/{id}/withdraw": {
      "post": {
        "operationId": "AbsenceController_withdraw",
        "summary": "Withdraw the caller’s submitted absence request",
        "description": "**Capability:** none — the operation acts as the authenticated member and its authorisation is row-level (ownership, the approver line, project membership). An API key with an empty scope reaches it.",
        "tags": [
          "Me"
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "type": "string"
          }
        ],
        "responses": {
          "201": {
            "description": "Created.",
            "schema": {
              "$ref": "#/definitions/AbsencePeriodDetailDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/absence-periods/{id}": {
      "get": {
        "operationId": "AbsenceController_detail",
        "summary": "Get an absence period’s detail",
        "description": "Absence types are masked by sensitivity exactly as in the UI.\n\n**Capability:** `worktime.supervise` or `hr.manage` — an API key must carry one of these in its scope.",
        "tags": [
          "Absences"
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "type": "string"
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/AbsencePeriodDetailDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/absence-periods/{id}/cancel": {
      "post": {
        "operationId": "AbsenceController_cancel",
        "summary": "Cancel an approved absence period",
        "description": "Reverses the period’s balance consumption. Refused with 409 `absence_cancel_after_confirmed_day` once a materialised day has been confirmed — leave actually taken is an append-only record; postpone the untaken tail instead. Pass `expectedUpdatedAt` from the period detail to detect a concurrent decision.\n\n**Capability:** none for the caller's own record — its authorisation is row-level. Reaching ANOTHER member's record with an API key additionally requires `worktime.supervise` or `hr.manage` in the key's scope.",
        "tags": [
          "Absences"
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "type": "string"
          },
          {
            "name": "body",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/ApproveAbsencePeriodDto"
            }
          }
        ],
        "responses": {
          "201": {
            "description": "Created.",
            "schema": {
              "$ref": "#/definitions/AbsencePeriodDetailDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/team/absence": {
      "get": {
        "operationId": "AbsenceController_team",
        "summary": "List team absences for a date range",
        "description": "Absence types are masked by sensitivity exactly as in the UI.\n\n**Capability:** `worktime.supervise` — an API key must carry this in its scope.",
        "tags": [
          "Absences"
        ],
        "parameters": [
          {
            "name": "from",
            "required": true,
            "in": "query",
            "type": "string"
          },
          {
            "name": "to",
            "required": true,
            "in": "query",
            "type": "string"
          },
          {
            "name": "cursor",
            "required": false,
            "in": "query",
            "type": "string"
          },
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "minimum": 1,
            "maximum": 100,
            "default": 50,
            "type": "integer"
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/TeamAbsenceResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/absence-periods/{id}/approve": {
      "post": {
        "operationId": "AbsenceController_approve",
        "summary": "Approve a submitted absence period",
        "description": "**Capability:** `worktime.supervise` — an API key must carry this in its scope.",
        "tags": [
          "Approvals"
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "type": "string"
          },
          {
            "name": "body",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/ApproveAbsencePeriodDto"
            }
          }
        ],
        "responses": {
          "201": {
            "description": "Created.",
            "schema": {
              "$ref": "#/definitions/AbsencePeriodDetailDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/absence-periods/{id}/reject": {
      "post": {
        "operationId": "AbsenceController_reject",
        "summary": "Reject a submitted absence period",
        "description": "**Capability:** `worktime.supervise` — an API key must carry this in its scope.",
        "tags": [
          "Approvals"
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "type": "string"
          },
          {
            "name": "body",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/RejectAbsencePeriodDto"
            }
          }
        ],
        "responses": {
          "201": {
            "description": "Created.",
            "schema": {
              "$ref": "#/definitions/AbsencePeriodDetailDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/team/absence/preview": {
      "post": {
        "operationId": "AbsenceController_teamPreview",
        "summary": "Preview an employer-assigned absence for a member",
        "description": "Resolves the period day by day and reports the balance it would consume plus any conflicts (confirmed days, overlapping absences, shift coverage) — without writing anything. Run this before assigning, so an import can refuse a whole file instead of half-placing it.\n\n**Capability:** `worktime.supervise` — an API key must carry this in its scope.",
        "tags": [
          "Absences"
        ],
        "parameters": [
          {
            "name": "body",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/PlanAbsencePeriodDto"
            }
          }
        ],
        "responses": {
          "201": {
            "description": "Created.",
            "schema": {
              "$ref": "#/definitions/AbsencePeriodPreviewDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/team/absence/plan": {
      "post": {
        "operationId": "AbsenceController_plan",
        "summary": "Assign an absence to a member",
        "description": "Creates the period already granted, the way an employer places leave (shutdown, layoff) or an HR system of record pushes an approved absence. Only policies marked employer-assignable are accepted; the balance is consumed and `absence.decided` is emitted. Preview first to see the consumption and conflicts. Retrying a placement that already exists is refused with 422 `absence_period_overlap` rather than booked twice, so a timed-out request is safe to repeat.\n\n**Capability:** `worktime.supervise` — an API key must carry this in its scope.",
        "tags": [
          "Absences"
        ],
        "parameters": [
          {
            "name": "body",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/PlanAbsencePeriodDto"
            }
          }
        ],
        "responses": {
          "201": {
            "description": "Created.",
            "schema": {
              "$ref": "#/definitions/AbsencePeriodDetailDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/me/leave-balance": {
      "get": {
        "operationId": "LeaveEntitlementController_myBalance",
        "summary": "Get the caller’s leave balance, optionally projected to a date",
        "description": "**Capability:** none — the operation acts as the authenticated member and its authorisation is row-level (ownership, the approver line, project membership). An API key with an empty scope reaches it.",
        "tags": [
          "Me"
        ],
        "parameters": [
          {
            "name": "asOf",
            "required": false,
            "in": "query",
            "description": "ISO date to project to (default: today)",
            "type": "string"
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/LeaveBalanceResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/leave-save-proposals/{id}/approve": {
      "post": {
        "operationId": "LeaveEntitlementController_approveSaveProposal",
        "summary": "Approve a saved-leave proposal",
        "description": "The decision half of the `leave_save` rows in the approval queue; executes the annual-holidays-act § 27 ledger transfer. `expectedUpdatedAt` is the optimistic-concurrency stamp read from the queue row.\n\n**Capability:** `worktime.supervise` — an API key must carry this in its scope.",
        "tags": [
          "Approvals"
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "type": "string"
          },
          {
            "name": "body",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/ApproveLeaveSaveProposalDto"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/LeaveSaveProposalOkResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/leave-save-proposals/{id}/decline": {
      "post": {
        "operationId": "LeaveEntitlementController_declineSaveProposal",
        "summary": "Decline a saved-leave proposal",
        "description": "The other decision half of the `leave_save` rows in the approval queue: no ledger transfer happens and the reason routes back to the proposer. `expectedUpdatedAt` is the optimistic-concurrency stamp read from the queue row.\n\n**Capability:** `worktime.supervise` — an API key must carry this in its scope.",
        "tags": [
          "Approvals"
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "type": "string"
          },
          {
            "name": "body",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/DeclineLeaveSaveProposalDto"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/LeaveSaveProposalOkResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/team/members/{membershipId}/leave-balance": {
      "get": {
        "operationId": "LeaveEntitlementController_memberBalance",
        "summary": "Get a report’s projected leave balance",
        "description": "Scoped to the caller’s reports.\n\n**Capability:** `worktime.supervise` — an API key must carry this in its scope.",
        "tags": [
          "Absences"
        ],
        "parameters": [
          {
            "name": "membershipId",
            "required": true,
            "in": "path",
            "type": "string"
          },
          {
            "name": "asOf",
            "required": false,
            "in": "query",
            "type": "string"
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/LeaveBalanceResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/memberships": {
      "get": {
        "operationId": "MembershipsController_list",
        "summary": "List members of the organisation",
        "description": "Scoped to the caller’s authority: a supervisor sees only their own reports.\n\n**Capability:** `members.manage` or `worktime.supervise` or `payroll.run` — an API key must carry one of these in its scope.",
        "tags": [
          "Members"
        ],
        "parameters": [
          {
            "name": "cursor",
            "required": false,
            "in": "query",
            "type": "string"
          },
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "minimum": 1,
            "maximum": 100,
            "default": 50,
            "type": "integer"
          },
          {
            "name": "updatedSince",
            "required": false,
            "in": "query",
            "format": "date-time",
            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$",
            "type": "string"
          },
          {
            "name": "q",
            "required": false,
            "in": "query",
            "type": "string"
          },
          {
            "name": "role",
            "required": false,
            "in": "query",
            "type": "string",
            "enum": [
              "employee",
              "manager",
              "admin",
              "payroll",
              "hr"
            ]
          },
          {
            "name": "unitId",
            "required": false,
            "in": "query",
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
            "type": "string"
          },
          {
            "name": "employerId",
            "required": false,
            "in": "query",
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
            "type": "string"
          },
          {
            "name": "status",
            "required": false,
            "in": "query",
            "type": "string",
            "enum": [
              "active",
              "future",
              "ended"
            ]
          },
          {
            "name": "incompleteOnly",
            "required": false,
            "in": "query",
            "type": "string",
            "enum": [
              "true",
              "false"
            ]
          },
          {
            "name": "includeInactive",
            "required": false,
            "in": "query",
            "type": "string",
            "enum": [
              "true",
              "false"
            ]
          },
          {
            "name": "leadsOnly",
            "required": false,
            "in": "query",
            "type": "string",
            "enum": [
              "true",
              "false"
            ]
          },
          {
            "name": "excludePayroll",
            "required": false,
            "in": "query",
            "type": "string",
            "enum": [
              "true",
              "false"
            ]
          },
          {
            "name": "attention",
            "required": false,
            "in": "query",
            "type": "string",
            "enum": [
              "true",
              "false"
            ]
          },
          {
            "name": "needsAttention",
            "required": false,
            "in": "query",
            "type": "string",
            "enum": [
              "true",
              "false"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/MembershipListResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      },
      "post": {
        "operationId": "MembershipsController_create",
        "summary": "Create a member",
        "description": "Required: `displayName` and `role`. `email` is optional — omit it for a device-only punch-clock worker, and the server mints a synthetic, never-deliverable address and sends no invite (give a `phone` so SMS can still reach them). Every optional id (`managerMembershipId`, `worktimeModelId`, `leaveGroupId`) is readable from the public surface, so nothing here needs an internal endpoint. A new passwordless member is created AND invited in one call: `member.created` and `member.invited` both fire, and the response carries the one-time activation URL. Called with an API key the `Idempotency-Key` header is REQUIRED — a retried create then replays the original 201 instead of answering `409 already_member` with no id. Re-creating an address that is already a member of this organisation is `409 already_member`.\n\n**Capability:** `members.manage` — an API key must carry this in its scope.",
        "tags": [
          "Members"
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "description": "Caller-generated unique key (max 200 characters) that makes this money-document write exactly-once. Required for API-key callers; deduplicated per organisation for 24 h. Replaying the same key with the same body replays the stored response; a different body is refused with 409 `idempotency_key_reused`.",
            "example": "payroll-run-2026-08-invoice-4711",
            "type": "string",
            "maxLength": 200
          },
          {
            "name": "body",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/CreateMembershipDto"
            }
          }
        ],
        "responses": {
          "201": {
            "description": "Created.",
            "schema": {
              "$ref": "#/definitions/CreateMembershipResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/memberships/{id}": {
      "get": {
        "operationId": "MembershipsController_get",
        "summary": "Get a member’s record",
        "description": "**Capability:** `members.manage` or `worktime.supervise` or `payroll.run` — an API key must carry one of these in its scope.",
        "tags": [
          "Members"
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "type": "string"
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/MembershipDetailResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      },
      "patch": {
        "operationId": "MembershipsController_update",
        "summary": "Update a member",
        "description": "Partial update — only the fields present in the body change. The EMPLOYMENT WINDOW lives here (`employmentStartDate` / `employmentEndDate`, both nullable), alongside role, supervisor, worktime model, primary planning unit and leave group. A `planningUnitId` change is effective-dated from today and never rewrites which unit the person belonged to in the past. Refused for a supervisor loop (`422 manager_cannot_be_self`, `422 manager_cycle`) and for demoting yourself (`422 cannot_change_own_role`); a role change ends the member’s live sessions. The privilege fields (`hrScopeUnitIds`, `hrRecorder`, `crmSeat`, `canPlanAllUnits`) are admin-only and refused for anyone else. Fires `member.updated`.\n\n**Capability:** `members.manage` — an API key must carry this in its scope.",
        "tags": [
          "Members"
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "type": "string"
          },
          {
            "name": "body",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/UpdateMembershipDto"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/MembershipOkResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/memberships/bulk": {
      "post": {
        "operationId": "MembershipsController_bulk",
        "summary": "Create members in bulk",
        "description": "The migration on-ramp: 1–500 rows per request (`rows`), each created independently so one bad row never fails the batch. Always answers 200 with a per-row outcome — `invited`, `created`, `skipped` (already a member) or `error` with a machine-readable `code` (`manager_not_found`, `planning_unit_not_found`, `worktime_model_not_found`, `employer_not_found`). A row may name its supervisor by e-mail and its unit / worktime model / employer by name or registry code, resolved server-side against this organisation AND the other rows of the same request, so a payroll export can be posted without looking any ids up first. Re-posting the same file is safe: existing members are skipped, never duplicated, so no `Idempotency-Key` is needed. Fires `member.created` (and `member.invited`) per created row.\n\n**Capability:** `members.manage` — an API key must carry this in its scope.",
        "tags": [
          "Members"
        ],
        "parameters": [
          {
            "name": "body",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/BulkCreateMembershipsDto"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/BulkCreateMembershipsResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/memberships/{id}/invite": {
      "post": {
        "operationId": "MembershipsController_invite",
        "summary": "Send or resend the activation invite",
        "description": "Mints a NEW single-use activation link — the previous one stops working — and e-mails it in `locale` (default: the member’s own preferred language). Not needed after `POST /v1/memberships`, which already invites; this is the \"the mail never arrived\" and \"the link expired\" path. Refused with `422 invitation_accepted` when the member already has a password and `422 membership_deactivated` for an offboarded member. Fires `member.invited` on every send: each send is a real issuance that supersedes the previous link.\n\n**Capability:** `members.manage` — an API key must carry this in its scope.",
        "tags": [
          "Members"
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "type": "string"
          },
          {
            "name": "body",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/InviteMemberDto"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/MembershipInviteResultDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/memberships/{id}/units": {
      "post": {
        "operationId": "MembershipsController_addUnit",
        "summary": "Assign the member to a planning unit",
        "description": "Multi-unit membership: adds ONE MORE open unit assignment (effective today) so the person can be rostered there; the member’s first unit also becomes their primary one. `planningUnitId` comes from `GET /v1/planning-units`; an unknown id is `404 planning_unit_not_found`. Needs the `org.admin` scope — for the ordinary \"which unit does this person belong to\" case use `planningUnitId` on `PATCH /v1/memberships/{id}`, which needs only `members.manage`. Fires `member.updated`.\n\n**Capability:** `org.admin` — an API key must carry this in its scope.",
        "tags": [
          "Members"
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "type": "string"
          },
          {
            "name": "body",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/AddMembershipUnitDto"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/MembershipOkResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/memberships/{id}/units/{unitId}": {
      "delete": {
        "operationId": "MembershipsController_removeUnit",
        "summary": "Remove a planning unit from the member",
        "description": "Closes the assignment as of today; the past is kept, so which unit’s shifts applied last month never changes. If the removed unit was the primary one, another open assignment takes its place — or none, when it was the last. Needs the `org.admin` scope. Fires `member.updated`.\n\n**Capability:** `org.admin` — an API key must carry this in its scope.",
        "tags": [
          "Members"
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "type": "string"
          },
          {
            "name": "unitId",
            "required": true,
            "in": "path",
            "type": "string"
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/MembershipOkResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/memberships/{id}/deactivate": {
      "post": {
        "operationId": "MembershipsController_deactivate",
        "summary": "Deactivate a member",
        "description": "Offboarding: all bookkeeping history is kept, sign-in is blocked and the member’s live sessions end immediately. This operation NEVER fails on account of API keys — offboarding must always be possible — so the response instead lists in `orphanedServiceKeys` the SERVICE keys the member owned. Those keys execute with their owner’s authority and stop authenticating (`401 api_key_owner_inactive`) the moment the owner does, so reassign them or the integrations behind them go dark. Personal keys are deliberately not listed: dying with their owner is what a personal key is for. Idempotent — a second call is a no-op with an empty list and emits nothing. Fires `member.deactivated` on a real change. `422 cannot_deactivate_self`.\n\n**Capability:** `members.manage` — an API key must carry this in its scope.",
        "tags": [
          "Members"
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "type": "string"
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/DeactivateMembershipResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/memberships/{id}/reactivate": {
      "post": {
        "operationId": "MembershipsController_reactivate",
        "summary": "Reactivate a member",
        "description": "Brings a deactivated member back into the active roster (a rehire, or an offboarding that turned out to be wrong). Service keys the member owns start authenticating again by themselves — the owner’s status is checked per request, not frozen at deactivation. Idempotent; fires `member.updated` on a real change.\n\n**Capability:** `members.manage` — an API key must carry this in its scope.",
        "tags": [
          "Members"
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "type": "string"
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/MembershipOkResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/training-requests/{id}/approve": {
      "post": {
        "operationId": "TrainingRequestsController_approve",
        "summary": "Approve a training request",
        "description": "The decision half of the `training` rows in the approval queue. `expectedUpdatedAt` is the optimistic-concurrency stamp read from the queue row.\n\n**Capability:** `worktime.supervise` — an API key must carry this in its scope.",
        "tags": [
          "Approvals"
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "type": "string"
          },
          {
            "name": "body",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/ApproveTrainingRequestDto"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/TrainingRequestOkResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/training-requests/{id}/decline": {
      "post": {
        "operationId": "TrainingRequestsController_decline",
        "summary": "Decline a training request",
        "description": "The other decision half of the `training` rows in the approval queue: the reason routes back to the requester. `expectedUpdatedAt` is the optimistic-concurrency stamp read from the queue row.\n\n**Capability:** `worktime.supervise` — an API key must carry this in its scope.",
        "tags": [
          "Approvals"
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "type": "string"
          },
          {
            "name": "body",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/DeclineTrainingRequestDto"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/TrainingRequestOkResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/projects/portfolio/attention": {
      "get": {
        "operationId": "ProjectOverviewController_portfolioAttention",
        "summary": "Get the portfolio attention roll-up",
        "description": "**Capability:** `projects.read` — an API key must carry this in its scope.",
        "tags": [
          "Projects"
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/ProjectPortfolioAttentionResponseDto"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/projects/roster": {
      "get": {
        "operationId": "ProjectOverviewController_roster",
        "summary": "List projects",
        "description": "Paginated, server-filtered and sorted portfolio roster; each row carries the project state and money figures.\n\n**Capability:** `projects.read` — an API key must carry this in its scope.",
        "tags": [
          "Projects"
        ],
        "parameters": [
          {
            "name": "cursor",
            "required": false,
            "in": "query",
            "type": "string"
          },
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "minimum": 1,
            "maximum": 100,
            "default": 50,
            "type": "integer"
          },
          {
            "name": "from",
            "required": true,
            "in": "query",
            "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
            "type": "string"
          },
          {
            "name": "to",
            "required": true,
            "in": "query",
            "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
            "type": "string"
          },
          {
            "name": "q",
            "required": false,
            "in": "query",
            "type": "string"
          },
          {
            "name": "status",
            "required": false,
            "in": "query",
            "type": "string",
            "enum": [
              "draft",
              "active",
              "on_hold",
              "closed"
            ]
          },
          {
            "name": "health",
            "required": false,
            "in": "query",
            "type": "string",
            "enum": [
              "on_track",
              "at_risk",
              "over_budget",
              "no_data"
            ]
          },
          {
            "name": "situation",
            "required": false,
            "in": "query",
            "type": "string",
            "enum": [
              "on_track",
              "at_risk",
              "off_track",
              "none"
            ]
          },
          {
            "name": "mine",
            "required": false,
            "in": "query",
            "type": "string",
            "enum": [
              "true",
              "false"
            ]
          },
          {
            "name": "unbilled",
            "required": false,
            "in": "query",
            "type": "string",
            "enum": [
              "true",
              "false"
            ]
          },
          {
            "name": "sort",
            "required": false,
            "in": "query",
            "type": "string",
            "enum": [
              "hours",
              "health",
              "margin",
              "budget",
              "name",
              "deadline"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/ProjectRosterResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/projects/{id}/overview": {
      "get": {
        "operationId": "ProjectOverviewController_overview",
        "summary": "Get the overview aggregate of a project",
        "description": "**Capability:** `projects.read` — an API key must carry this in its scope.",
        "tags": [
          "Projects"
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "type": "string"
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/ProjectOverviewResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/projects/{id}/tasks": {
      "get": {
        "operationId": "ProjectTasksController_board",
        "summary": "List the tasks of a project",
        "description": "The whole board: columns with card windows, dependencies and milestones. Page a single column with the tasks/page operation.\n\n**Capability:** `projects.read` — an API key must carry this in its scope.",
        "tags": [
          "Tasks"
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "type": "string"
          },
          {
            "name": "cursor",
            "required": false,
            "in": "query",
            "type": "string"
          },
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "minimum": 1,
            "maximum": 100,
            "default": 50,
            "type": "integer"
          },
          {
            "name": "statusId",
            "required": false,
            "in": "query",
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
            "type": "string"
          },
          {
            "name": "assigneeMembershipId",
            "required": false,
            "in": "query",
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
            "type": "string"
          },
          {
            "name": "phaseId",
            "required": false,
            "in": "query",
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
            "type": "string"
          },
          {
            "name": "milestoneId",
            "required": false,
            "in": "query",
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
            "type": "string"
          },
          {
            "name": "priority",
            "required": false,
            "in": "query",
            "type": "string",
            "enum": [
              "low",
              "normal",
              "high",
              "urgent"
            ]
          },
          {
            "name": "tagId",
            "required": false,
            "in": "query",
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
            "type": "string"
          },
          {
            "name": "q",
            "required": false,
            "in": "query",
            "maxLength": 200,
            "type": "string"
          },
          {
            "name": "includeClosed",
            "required": false,
            "in": "query",
            "type": "string",
            "enum": [
              "true",
              "false"
            ]
          },
          {
            "name": "archived",
            "required": false,
            "in": "query",
            "type": "string",
            "enum": [
              "true",
              "false"
            ]
          },
          {
            "name": "fieldId",
            "required": false,
            "in": "query",
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
            "type": "string"
          },
          {
            "name": "fieldValue",
            "required": false,
            "in": "query",
            "maxLength": 100,
            "type": "string"
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/TaskBoardResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      },
      "post": {
        "operationId": "ProjectTasksController_create",
        "summary": "Create a task in a project",
        "description": "**Capability:** `projects.manage` — an API key must carry this in its scope.",
        "tags": [
          "Tasks"
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "type": "string"
          },
          {
            "name": "body",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/CreateTaskDto"
            }
          }
        ],
        "responses": {
          "201": {
            "description": "Created.",
            "schema": {
              "$ref": "#/definitions/TaskViewDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/projects/{id}/tasks/page": {
      "get": {
        "operationId": "ProjectTasksController_taskPage",
        "summary": "Page the tasks of a project",
        "description": "Cursor-paginated tasks in one of three lenses: one board column (statusId), the archive (archived=true) or everything changed since an instant (updatedSince — the incremental-sync read, which spans archived tasks too). Exactly one lens must be selected.\n\n**Capability:** `projects.read` — an API key must carry this in its scope.",
        "tags": [
          "Tasks"
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "type": "string"
          },
          {
            "name": "cursor",
            "required": false,
            "in": "query",
            "type": "string"
          },
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "minimum": 1,
            "maximum": 100,
            "default": 50,
            "type": "integer"
          },
          {
            "name": "statusId",
            "required": false,
            "in": "query",
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
            "type": "string"
          },
          {
            "name": "assigneeMembershipId",
            "required": false,
            "in": "query",
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
            "type": "string"
          },
          {
            "name": "phaseId",
            "required": false,
            "in": "query",
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
            "type": "string"
          },
          {
            "name": "milestoneId",
            "required": false,
            "in": "query",
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
            "type": "string"
          },
          {
            "name": "priority",
            "required": false,
            "in": "query",
            "type": "string",
            "enum": [
              "low",
              "normal",
              "high",
              "urgent"
            ]
          },
          {
            "name": "tagId",
            "required": false,
            "in": "query",
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
            "type": "string"
          },
          {
            "name": "q",
            "required": false,
            "in": "query",
            "maxLength": 200,
            "type": "string"
          },
          {
            "name": "includeClosed",
            "required": false,
            "in": "query",
            "type": "string",
            "enum": [
              "true",
              "false"
            ]
          },
          {
            "name": "archived",
            "required": false,
            "in": "query",
            "type": "string",
            "enum": [
              "true",
              "false"
            ]
          },
          {
            "name": "fieldId",
            "required": false,
            "in": "query",
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
            "type": "string"
          },
          {
            "name": "fieldValue",
            "required": false,
            "in": "query",
            "maxLength": 100,
            "type": "string"
          },
          {
            "name": "updatedSince",
            "required": false,
            "in": "query",
            "format": "date-time",
            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$",
            "type": "string"
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/TaskPageResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/projects/{id}/statuses": {
      "get": {
        "operationId": "ProjectTasksController_statuses",
        "summary": "List the task statuses of a project board",
        "description": "The closed status catalogue of one project’s task board. `PATCH /v1/me/tasks/{id}/status` takes a `statusId` from this list; `category` tells which statuses mean todo / in progress / done / cancelled.\n\n**Capability:** `projects.read` — an API key must carry this in its scope.",
        "tags": [
          "Tasks"
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "type": "string"
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/TaskStatusListResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/tasks/{id}": {
      "get": {
        "operationId": "TasksController_detail",
        "summary": "Get a task",
        "description": "**Capability:** `projects.read` or `projects.manage` — an API key must carry one of these in its scope.",
        "tags": [
          "Tasks"
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "type": "string"
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/TaskDetailResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/me/tasks": {
      "get": {
        "operationId": "MeTasksController_myTasks",
        "summary": "List the tasks assigned to the caller",
        "description": "The caller’s own task desk: tasks they are assignee, commenter or watcher on, plus the board status options (`boards[].statuses`) an assignee may move their own card between with `PATCH /v1/me/tasks/{id}/status`. Reachable with any key — the per-project board reads require `projects.read`, this one is the employee’s own surface.\n\n**Capability:** none — the operation acts as the authenticated member and its authorisation is row-level (ownership, the approver line, project membership). An API key with an empty scope reaches it.",
        "tags": [
          "Me"
        ],
        "parameters": [
          {
            "name": "includeClosed",
            "required": false,
            "in": "query",
            "type": "string",
            "enum": [
              "true",
              "false"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/MeTasksResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/me/tasks/{id}/status": {
      "patch": {
        "operationId": "MeTasksController_changeStatus",
        "summary": "Change the status of a task assigned to the caller",
        "description": "Moves the task to another board column. Only the assignee may move their own card here; 404 for tasks assigned to someone else.\n\n**Capability:** none — the operation acts as the authenticated member and its authorisation is row-level (ownership, the approver line, project membership). An API key with an empty scope reaches it.",
        "tags": [
          "Tasks"
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "type": "string"
          },
          {
            "name": "body",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/MeTaskStatusChangeDto"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/TaskOkResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/billing-export/candidates": {
      "get": {
        "operationId": "BillingExportController_candidates",
        "summary": "List billable candidates for a period",
        "description": "**Capability:** `projects.manage` or `payroll.run` — an API key must carry one of these in its scope.",
        "tags": [
          "Billing exports"
        ],
        "parameters": [
          {
            "name": "from",
            "required": true,
            "in": "query",
            "type": "string"
          },
          {
            "name": "to",
            "required": true,
            "in": "query",
            "type": "string"
          },
          {
            "name": "granularity",
            "required": false,
            "in": "query",
            "type": "string"
          },
          {
            "name": "targetId",
            "required": false,
            "in": "query",
            "type": "string"
          },
          {
            "name": "lang",
            "required": false,
            "in": "query",
            "type": "string"
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/BillingCandidatesResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/billing-export/batches": {
      "get": {
        "operationId": "BillingExportController_listBatches",
        "summary": "List billing export batches",
        "description": "**Capability:** `projects.manage` or `payroll.run` — an API key must carry one of these in its scope.",
        "tags": [
          "Billing exports"
        ],
        "parameters": [
          {
            "name": "cursor",
            "required": false,
            "in": "query",
            "type": "string"
          },
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "minimum": 1,
            "maximum": 100,
            "default": 50,
            "type": "integer"
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/BillingBatchListResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      },
      "post": {
        "operationId": "BillingExportController_createBatch",
        "summary": "Create a billing export batch",
        "description": "**Capability:** `projects.manage` or `payroll.run` — an API key must carry one of these in its scope.",
        "tags": [
          "Billing exports"
        ],
        "parameters": [
          {
            "name": "lang",
            "required": false,
            "in": "query",
            "type": "string"
          },
          {
            "name": "body",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/CreateBillingBatchDto"
            }
          }
        ],
        "responses": {
          "201": {
            "description": "Created.",
            "schema": {
              "$ref": "#/definitions/BillingIdResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/billing-export/batches/{id}/download": {
      "get": {
        "operationId": "BillingExportController_downloadBatch",
        "summary": "Download a billing export batch file",
        "description": "**Capability:** `projects.manage` or `payroll.run` — an API key must carry one of these in its scope.",
        "tags": [
          "Billing exports"
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "type": "string"
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "type": "string",
              "format": "binary"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/billing-export/batches/{id}/deliver": {
      "post": {
        "operationId": "BillingExportController_deliver",
        "summary": "Deliver a billing export batch to its target",
        "description": "**Capability:** `projects.manage` or `payroll.run` — an API key must carry one of these in its scope.",
        "tags": [
          "Billing exports"
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "type": "string"
          }
        ],
        "responses": {
          "201": {
            "description": "Created.",
            "schema": {
              "$ref": "#/definitions/BillingIdResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/billing-export/batches/{id}/deliveries": {
      "get": {
        "operationId": "BillingExportController_listDeliveries",
        "summary": "List deliveries of a billing export batch",
        "description": "**Capability:** `projects.manage` or `payroll.run` — an API key must carry one of these in its scope.",
        "tags": [
          "Billing exports"
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "type": "string"
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/BillingDeliveryListResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/invoicing/invoices": {
      "get": {
        "operationId": "InvoicesController_list",
        "summary": "List invoices",
        "description": "**Capability:** `projects.manage` or `payroll.run` — an API key must carry one of these in its scope.",
        "tags": [
          "Invoices"
        ],
        "parameters": [
          {
            "name": "cursor",
            "required": false,
            "in": "query",
            "type": "string"
          },
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "minimum": 1,
            "maximum": 100,
            "default": 50,
            "type": "integer"
          },
          {
            "name": "updatedSince",
            "required": false,
            "in": "query",
            "format": "date-time",
            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$",
            "type": "string"
          },
          {
            "name": "lane",
            "required": false,
            "in": "query",
            "type": "string",
            "enum": [
              "draft",
              "approved",
              "issued",
              "sent",
              "overdue",
              "paid",
              "credited"
            ]
          },
          {
            "name": "status",
            "required": false,
            "in": "query",
            "type": "string",
            "enum": [
              "draft",
              "issued"
            ]
          },
          {
            "name": "documentType",
            "required": false,
            "in": "query",
            "type": "string",
            "enum": [
              "invoice",
              "credit_note",
              "reminder",
              "advance"
            ]
          },
          {
            "name": "customerId",
            "required": false,
            "in": "query",
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
            "type": "string"
          },
          {
            "name": "projectId",
            "required": false,
            "in": "query",
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
            "type": "string"
          },
          {
            "name": "from",
            "required": false,
            "in": "query",
            "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
            "type": "string"
          },
          {
            "name": "to",
            "required": false,
            "in": "query",
            "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
            "type": "string"
          },
          {
            "name": "overdue",
            "required": false,
            "in": "query",
            "type": "string",
            "enum": [
              "true",
              "false"
            ]
          },
          {
            "name": "openOnly",
            "required": false,
            "in": "query",
            "type": "string",
            "enum": [
              "true",
              "false"
            ]
          },
          {
            "name": "q",
            "required": false,
            "in": "query",
            "maxLength": 200,
            "type": "string"
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/InvoicePageResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/invoicing/invoices/summary": {
      "get": {
        "operationId": "InvoicesController_summary",
        "summary": "Get invoicing summary figures",
        "description": "**Capability:** `projects.manage` or `payroll.run` — an API key must carry one of these in its scope.",
        "tags": [
          "Invoices"
        ],
        "parameters": [
          {
            "name": "accept-language",
            "required": true,
            "in": "header",
            "type": "string"
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/InvoicingSummaryResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/invoicing/invoices/drafts": {
      "post": {
        "operationId": "InvoicesController_createDrafts",
        "summary": "Create invoice drafts from billable candidates",
        "description": "**Capability:** `projects.manage` or `payroll.run` — an API key must carry one of these in its scope.",
        "tags": [
          "Invoices"
        ],
        "parameters": [
          {
            "name": "accept-language",
            "required": true,
            "in": "header",
            "type": "string"
          },
          {
            "name": "body",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/CreateInvoiceDraftsDto"
            }
          }
        ],
        "responses": {
          "201": {
            "description": "Created.",
            "schema": {
              "$ref": "#/definitions/CreateInvoiceDraftsResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/invoicing/invoices/{id}": {
      "get": {
        "operationId": "InvoicesController_get",
        "summary": "Get an invoice",
        "description": "**Capability:** `projects.manage` or `payroll.run` — an API key must carry one of these in its scope.",
        "tags": [
          "Invoices"
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "type": "string"
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/InvoiceViewDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      },
      "delete": {
        "operationId": "InvoicesController_remove",
        "summary": "Delete an invoice draft",
        "description": "**Capability:** `projects.manage` or `payroll.run` — an API key must carry one of these in its scope.",
        "tags": [
          "Invoices"
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "type": "string"
          },
          {
            "name": "body",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/DeleteInvoiceDraftDto"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/InvoiceOkResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      },
      "patch": {
        "operationId": "InvoicesController_update",
        "summary": "Update an invoice draft",
        "description": "**Capability:** `projects.manage` or `payroll.run` — an API key must carry one of these in its scope.",
        "tags": [
          "Invoices"
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "type": "string"
          },
          {
            "name": "body",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/UpdateInvoiceDraftDto"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/InvoiceViewDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/invoicing/invoices/{id}/lines": {
      "post": {
        "operationId": "InvoicesController_addLine",
        "summary": "Add a manual line to an invoice draft",
        "description": "**Capability:** `projects.manage` or `payroll.run` — an API key must carry one of these in its scope.",
        "tags": [
          "Invoices"
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "type": "string"
          },
          {
            "name": "body",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/AddManualLineDto"
            }
          }
        ],
        "responses": {
          "201": {
            "description": "Created.",
            "schema": {
              "$ref": "#/definitions/InvoiceViewDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/invoicing/invoices/{id}/lines/{lineId}": {
      "delete": {
        "operationId": "InvoicesController_deleteLine",
        "summary": "Delete an invoice draft line",
        "description": "**Capability:** `projects.manage` or `payroll.run` — an API key must carry one of these in its scope.",
        "tags": [
          "Invoices"
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "type": "string"
          },
          {
            "name": "lineId",
            "required": true,
            "in": "path",
            "type": "string"
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/InvoiceViewDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      },
      "patch": {
        "operationId": "InvoicesController_updateLine",
        "summary": "Update an invoice draft line",
        "description": "**Capability:** `projects.manage` or `payroll.run` — an API key must carry one of these in its scope.",
        "tags": [
          "Invoices"
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "type": "string"
          },
          {
            "name": "lineId",
            "required": true,
            "in": "path",
            "type": "string"
          },
          {
            "name": "body",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/UpdateDraftLineDto"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/InvoiceViewDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/invoicing/invoices/{id}/lines/reorder": {
      "post": {
        "operationId": "InvoicesController_reorderLines",
        "summary": "Reorder the lines of an invoice draft",
        "description": "**Capability:** `projects.manage` or `payroll.run` — an API key must carry one of these in its scope.",
        "tags": [
          "Invoices"
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "type": "string"
          },
          {
            "name": "body",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/ReorderDraftLinesDto"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/InvoiceViewDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/invoicing/invoices/{id}/review": {
      "post": {
        "operationId": "InvoicesController_review",
        "summary": "Request or approve review of an invoice draft",
        "description": "**Capability:** `projects.manage` or `payroll.run` — an API key must carry one of these in its scope.",
        "tags": [
          "Invoices"
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "type": "string"
          },
          {
            "name": "body",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/SetInvoiceReviewDto"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/InvoiceViewDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/invoicing/invoices/{id}/issue": {
      "post": {
        "operationId": "InvoicesController_issueInvoice",
        "summary": "Issue an invoice",
        "description": "Burns a gapless invoice number; irreversible — corrections are credit notes. Requires an Idempotency-Key header when called with an API key.\n\n**Capability:** `payroll.run` — an API key must carry this in its scope.",
        "tags": [
          "Invoices"
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "type": "string"
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "description": "Caller-generated unique key (max 200 characters) that makes this money-document write exactly-once. Required for API-key callers; deduplicated per organisation for 24 h. Replaying the same key with the same body replays the stored response; a different body is refused with 409 `idempotency_key_reused`.",
            "example": "payroll-run-2026-08-invoice-4711",
            "type": "string",
            "maxLength": 200
          },
          {
            "name": "body",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/IssueInvoiceDto"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/IssueResultDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/invoicing/invoices/{id}/credit-note": {
      "post": {
        "operationId": "InvoicesController_creditNote",
        "summary": "Create a credit note for an issued invoice",
        "description": "**Capability:** `payroll.run` — an API key must carry this in its scope.",
        "tags": [
          "Invoices"
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "type": "string"
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "description": "Caller-generated unique key (max 200 characters) that makes this money-document write exactly-once. Required for API-key callers; deduplicated per organisation for 24 h. Replaying the same key with the same body replays the stored response; a different body is refused with 409 `idempotency_key_reused`.",
            "example": "payroll-run-2026-08-invoice-4711",
            "type": "string",
            "maxLength": 200
          },
          {
            "name": "body",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/CreditNoteDto"
            }
          }
        ],
        "responses": {
          "201": {
            "description": "Created.",
            "schema": {
              "$ref": "#/definitions/CreditNoteResultDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/invoicing/invoices/{id}/dispatches": {
      "get": {
        "operationId": "InvoicesController_dispatches",
        "summary": "List dispatch attempts for an invoice",
        "description": "**Capability:** `projects.manage` or `payroll.run` — an API key must carry one of these in its scope.",
        "tags": [
          "Invoices"
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "type": "string"
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/InvoiceDispatchListResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/invoicing/invoices/{id}/dispatch": {
      "post": {
        "operationId": "InvoicesController_send",
        "summary": "Dispatch an invoice",
        "description": "**Capability:** `payroll.run` — an API key must carry this in its scope.",
        "tags": [
          "Invoices"
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "type": "string"
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "description": "Caller-generated unique key (max 200 characters) that makes this money-document write exactly-once. Required for API-key callers; deduplicated per organisation for 24 h. Replaying the same key with the same body replays the stored response; a different body is refused with 409 `idempotency_key_reused`.",
            "example": "payroll-run-2026-08-invoice-4711",
            "type": "string",
            "maxLength": 200
          },
          {
            "name": "body",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/DispatchRequestDto"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/InvoiceDispatchViewDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/invoicing/invoices/{id}/dispatch/resend": {
      "post": {
        "operationId": "InvoicesController_resend",
        "summary": "Resend an invoice dispatch",
        "description": "**Capability:** `payroll.run` — an API key must carry this in its scope.",
        "tags": [
          "Invoices"
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "type": "string"
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "description": "Caller-generated unique key (max 200 characters) that makes this money-document write exactly-once. Required for API-key callers; deduplicated per organisation for 24 h. Replaying the same key with the same body replays the stored response; a different body is refused with 409 `idempotency_key_reused`.",
            "example": "payroll-run-2026-08-invoice-4711",
            "type": "string",
            "maxLength": 200
          },
          {
            "name": "body",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/DispatchRequestDto"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/InvoiceDispatchViewDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/invoicing/invoices/{id}/dispatch/sync": {
      "post": {
        "operationId": "InvoicesController_syncDispatchStatus",
        "summary": "Sync e-invoice dispatch status from the operator",
        "description": "**Capability:** `payroll.run` — an API key must carry this in its scope.",
        "tags": [
          "Invoices"
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "type": "string"
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/InvoiceDispatchListResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/invoicing/invoices/{id}/pdf": {
      "get": {
        "operationId": "InvoicesController_pdf",
        "summary": "Download the invoice PDF",
        "description": "**Capability:** `payroll.run` — an API key must carry this in its scope.",
        "tags": [
          "Invoices"
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "type": "string"
          },
          {
            "name": "specification",
            "required": true,
            "in": "query",
            "type": "string"
          }
        ],
        "responses": {
          "200": {
            "description": "Success."
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/invoicing/invoices/{id}/finvoice.xml": {
      "get": {
        "operationId": "InvoicesController_finvoice",
        "summary": "Download the Finvoice 3.0 e-invoice XML",
        "description": "**Capability:** `payroll.run` — an API key must carry this in its scope.",
        "tags": [
          "Invoices"
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "type": "string"
          }
        ],
        "responses": {
          "200": {
            "description": "Success."
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/invoicing/payments": {
      "get": {
        "operationId": "PaymentsController_list",
        "summary": "List payments",
        "description": "**Capability:** `payroll.run` — an API key must carry this in its scope.",
        "tags": [
          "Payments"
        ],
        "parameters": [
          {
            "name": "cursor",
            "required": false,
            "in": "query",
            "type": "string"
          },
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "minimum": 1,
            "maximum": 100,
            "default": 50,
            "type": "integer"
          },
          {
            "name": "q",
            "required": false,
            "in": "query",
            "maxLength": 200,
            "type": "string"
          },
          {
            "name": "source",
            "required": false,
            "in": "query",
            "type": "string",
            "enum": [
              "manual",
              "netvisor",
              "camt054"
            ]
          },
          {
            "name": "unallocatedOnly",
            "required": false,
            "in": "query",
            "type": "string",
            "enum": [
              "true",
              "false"
            ]
          },
          {
            "name": "from",
            "required": false,
            "in": "query",
            "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
            "type": "string"
          },
          {
            "name": "to",
            "required": false,
            "in": "query",
            "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
            "type": "string"
          },
          {
            "name": "invoiceId",
            "required": false,
            "in": "query",
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
            "type": "string"
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/PaymentPageResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      },
      "post": {
        "operationId": "PaymentsController_record",
        "summary": "Record a payment",
        "description": "**Capability:** `payroll.run` — an API key must carry this in its scope.",
        "tags": [
          "Payments"
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "description": "Caller-generated unique key (max 200 characters) that makes this money-document write exactly-once. Required for API-key callers; deduplicated per organisation for 24 h. Replaying the same key with the same body replays the stored response; a different body is refused with 409 `idempotency_key_reused`.",
            "example": "payroll-run-2026-08-invoice-4711",
            "type": "string",
            "maxLength": 200
          },
          {
            "name": "body",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/RecordPaymentDto"
            }
          }
        ],
        "responses": {
          "201": {
            "description": "Created.",
            "schema": {
              "$ref": "#/definitions/PaymentViewDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/invoicing/ar/aging": {
      "get": {
        "operationId": "PaymentsController_aging",
        "summary": "Get the aged receivables report",
        "description": "**Capability:** `payroll.run` — an API key must carry this in its scope.",
        "tags": [
          "Payments"
        ],
        "parameters": [
          {
            "name": "asOf",
            "required": false,
            "in": "query",
            "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
            "type": "string"
          },
          {
            "name": "customerId",
            "required": false,
            "in": "query",
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
            "type": "string"
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/ArAgingResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/invoicing/bank-imports": {
      "get": {
        "operationId": "PaymentsController_imports",
        "summary": "List bank file imports",
        "description": "**Capability:** `payroll.run` — an API key must carry this in its scope.",
        "tags": [
          "Payments"
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/BankImportListResponseDto"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      },
      "post": {
        "operationId": "PaymentsController_importBankFile",
        "summary": "Import a camt.054 bank file",
        "description": "**Capability:** `payroll.run` — an API key must carry this in its scope.",
        "tags": [
          "Payments"
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "description": "Caller-generated unique key (max 200 characters) that makes this money-document write exactly-once. Required for API-key callers; deduplicated per organisation for 24 h. Replaying the same key with the same body replays the stored response; a different body is refused with 409 `idempotency_key_reused`.",
            "example": "payroll-run-2026-08-invoice-4711",
            "type": "string",
            "maxLength": 200
          },
          {
            "name": "body",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/ImportBankFileDto"
            }
          }
        ],
        "responses": {
          "201": {
            "description": "Created.",
            "schema": {
              "$ref": "#/definitions/ImportResultViewDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/invoicing/customers/{id}/payment-behaviour": {
      "get": {
        "operationId": "PaymentsController_paymentBehaviour",
        "summary": "Get payment behaviour for a customer",
        "description": "**Capability:** `payroll.run` — an API key must carry this in its scope.",
        "tags": [
          "Payments"
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "type": "string"
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/CustomerPaymentBehaviourDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/invoicing/customers/{id}/advance-balance": {
      "get": {
        "operationId": "PaymentsController_advanceBalance",
        "summary": "Get the unapplied advance balance for a customer",
        "description": "**Capability:** `payroll.run` — an API key must carry this in its scope.",
        "tags": [
          "Payments"
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "type": "string"
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/CustomerAdvanceBalanceResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/invoicing/archive": {
      "get": {
        "operationId": "PaymentsController_exportArchive",
        "summary": "Download the invoice archive for a year",
        "description": "**Capability:** `payroll.run` — an API key must carry this in its scope.",
        "tags": [
          "Payments"
        ],
        "parameters": [
          {
            "name": "year",
            "required": true,
            "in": "query",
            "minimum": 2000,
            "maximum": 2100,
            "type": "integer"
          },
          {
            "name": "format",
            "required": false,
            "in": "query",
            "default": "zip",
            "type": "string",
            "enum": [
              "zip"
            ]
          },
          {
            "name": "profileId",
            "required": false,
            "in": "query",
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
            "type": "string"
          },
          {
            "name": "accept-language",
            "required": true,
            "in": "header",
            "type": "string"
          }
        ],
        "responses": {
          "200": {
            "description": "Success."
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/invoicing/payments/{id}": {
      "get": {
        "operationId": "PaymentsController_get",
        "summary": "Get a payment",
        "description": "**Capability:** `payroll.run` — an API key must carry this in its scope.",
        "tags": [
          "Payments"
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "type": "string"
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/PaymentViewDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/invoicing/payments/{id}/allocations": {
      "post": {
        "operationId": "PaymentsController_allocate",
        "summary": "Allocate a payment to invoices",
        "description": "**Capability:** `payroll.run` — an API key must carry this in its scope.",
        "tags": [
          "Payments"
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "type": "string"
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "description": "Caller-generated unique key (max 200 characters) that makes this money-document write exactly-once. Required for API-key callers; deduplicated per organisation for 24 h. Replaying the same key with the same body replays the stored response; a different body is refused with 409 `idempotency_key_reused`.",
            "example": "payroll-run-2026-08-invoice-4711",
            "type": "string",
            "maxLength": 200
          },
          {
            "name": "body",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/AllocatePaymentDto"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/PaymentViewDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/invoicing/recurring": {
      "get": {
        "operationId": "RecurringController_list",
        "summary": "List recurring invoice schedules",
        "description": "**Capability:** `projects.manage` or `payroll.run` — an API key must carry one of these in its scope.",
        "tags": [
          "Invoices"
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/RecurringScheduleListResponseDto"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/invoicing/recurring/runs": {
      "get": {
        "operationId": "RecurringController_runs",
        "summary": "List recurring invoicing runs",
        "description": "**Capability:** `projects.manage` or `payroll.run` — an API key must carry one of these in its scope.",
        "tags": [
          "Invoices"
        ],
        "parameters": [
          {
            "name": "scheduleId",
            "required": false,
            "in": "query",
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
            "type": "string"
          },
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "minimum": 1,
            "maximum": 100,
            "type": "integer"
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/RecurringRunListResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/quotes": {
      "get": {
        "operationId": "QuotesController_list",
        "summary": "List quotes",
        "description": "**Capability:** `crm.use` or `projects.manage` — an API key must carry one of these in its scope.",
        "tags": [
          "Quotes"
        ],
        "parameters": [
          {
            "name": "cursor",
            "required": false,
            "in": "query",
            "type": "string"
          },
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "minimum": 1,
            "maximum": 100,
            "default": 50,
            "type": "integer"
          },
          {
            "name": "updatedSince",
            "required": false,
            "in": "query",
            "format": "date-time",
            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$",
            "type": "string"
          },
          {
            "name": "status",
            "required": false,
            "in": "query",
            "type": "string",
            "enum": [
              "draft",
              "sent",
              "accepted",
              "declined",
              "expired"
            ]
          },
          {
            "name": "q",
            "required": false,
            "in": "query",
            "maxLength": 200,
            "type": "string"
          },
          {
            "name": "projectId",
            "required": false,
            "in": "query",
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
            "type": "string"
          },
          {
            "name": "customerId",
            "required": false,
            "in": "query",
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
            "type": "string"
          },
          {
            "name": "dealId",
            "required": false,
            "in": "query",
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
            "type": "string"
          },
          {
            "name": "templatesOnly",
            "required": false,
            "in": "query",
            "type": "string",
            "enum": [
              "true",
              "false"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/QuotePageResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      },
      "post": {
        "operationId": "QuotesController_create",
        "summary": "Create a quote draft",
        "description": "**Capability:** `crm.use` or `projects.manage` — an API key must carry one of these in its scope.",
        "tags": [
          "Quotes"
        ],
        "parameters": [
          {
            "name": "body",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/CreateQuoteDto"
            }
          }
        ],
        "responses": {
          "201": {
            "description": "Created.",
            "schema": {
              "$ref": "#/definitions/QuoteIdResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/quotes/stats": {
      "get": {
        "operationId": "QuotesController_stats",
        "summary": "Get quote hit-rate statistics",
        "description": "**Capability:** `crm.use` or `projects.manage` — an API key must carry one of these in its scope.",
        "tags": [
          "Quotes"
        ],
        "parameters": [
          {
            "name": "months",
            "required": false,
            "in": "query",
            "minimum": 1,
            "maximum": 36,
            "default": 12,
            "type": "integer"
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/QuoteStatsResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/quotes/{id}": {
      "get": {
        "operationId": "QuotesController_get",
        "summary": "Get a quote",
        "description": "**Capability:** `crm.use` or `projects.manage` — an API key must carry one of these in its scope.",
        "tags": [
          "Quotes"
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "type": "string"
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/QuoteViewDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/quotes/{id}/send": {
      "post": {
        "operationId": "QuotesController_send",
        "summary": "Send a quote to the customer",
        "description": "Freezes the draft, mints the customer share link and optionally emails it.\n\n**Capability:** `crm.use` or `projects.manage` — an API key must carry one of these in its scope.",
        "tags": [
          "Quotes"
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "type": "string"
          },
          {
            "name": "body",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/SendQuoteDto"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/SendQuoteResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/quotes/{id}/convert": {
      "post": {
        "operationId": "QuotesController_convert",
        "summary": "Convert an accepted quote into a project",
        "description": "**Capability:** `crm.use` or `projects.manage` — an API key must carry one of these in its scope.",
        "tags": [
          "Quotes"
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "type": "string"
          },
          {
            "name": "body",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/ConvertQuoteDto"
            }
          }
        ],
        "responses": {
          "201": {
            "description": "Created.",
            "schema": {
              "$ref": "#/definitions/QuoteIdResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/quotes/{id}/pdf": {
      "get": {
        "operationId": "QuotesController_pdf",
        "summary": "Download a quote as a PDF",
        "description": "Binary response (application/pdf): the frozen snapshot, or a live preview for a draft.\n\n**Capability:** `crm.use` or `projects.manage` — an API key must carry one of these in its scope.",
        "tags": [
          "Quotes"
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "type": "string"
          }
        ],
        "responses": {
          "200": {
            "description": "Success."
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/me/balances": {
      "get": {
        "operationId": "InsightsController_myBalances",
        "summary": "List the caller’s balance accounts",
        "description": "Every balance account the caller holds (flex plus each banked-leave account) with its current standing. A closed per-member set — one row per account type the tenant runs — so it is not paginated.\n\n**Capability:** none — the operation acts as the authenticated member and its authorisation is row-level (ownership, the approver line, project membership). An API key with an empty scope reaches it.",
        "tags": [
          "Me"
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/BalanceAccountsResponseDto"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/imports/customers": {
      "post": {
        "operationId": "ImportsController_customers",
        "summary": "Import customers in bulk",
        "description": "Answers 200 with one `results` row per submitted row — `{index, status, id, code}` where `index` is the 0-based position in the request, `status` is `created`, `skipped` or `error`, `id` is the created customer (null otherwise) and `code` a machine-readable reason (null when created). A partial import is a report, not an HTTP failure. Idempotent: a row whose `code` already exists is skipped (`code_already_in_use`), so re-running the same file creates nothing twice. Omit `code` and it is derived from the name, kept unique. Max 500 rows per batch — chunk larger files.\n\n**Capability:** `org.admin` — an API key must carry this in its scope.",
        "tags": [
          "Imports"
        ],
        "parameters": [
          {
            "name": "body",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/BulkCreateCustomersDto"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/BulkImportResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/imports/projects": {
      "post": {
        "operationId": "ImportsController_projects",
        "summary": "Import projects in bulk",
        "description": "Answers 200 with one `results` row per submitted row — `{index, status, id, code}` where `index` is the 0-based position in the request, `status` is `created`, `skipped` or `error`, `id` is the created project (null otherwise) and `code` a machine-readable reason (null when created). A partial import is a report, not an HTTP failure. Idempotent: a row whose `code` already exists is skipped (`code_already_in_use`), so re-running the same file creates nothing twice. Max 500 rows per batch — chunk larger files.\n\n**Capability:** `org.admin` — an API key must carry this in its scope.",
        "tags": [
          "Imports"
        ],
        "parameters": [
          {
            "name": "body",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/BulkCreateProjectsDto"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/BulkImportResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/imports/tasks": {
      "post": {
        "operationId": "ImportsController_tasks",
        "summary": "Import project tasks in bulk",
        "description": "Answers 200 with one `results` row per submitted row — `{index, status, id, code}` where `index` is the 0-based position in the request, `status` is `created` or `error`, `id` is the created task (null otherwise) and `code` a machine-readable reason (null when created). A partial import is a report, not an HTTP failure. Unlike the customer and project imports a task carries no tenant-unique key, so nothing is skipped: re-sending the same rows creates them again. Max 500 rows per batch — chunk larger files.\n\n**Capability:** `org.admin` — an API key must carry this in its scope.",
        "tags": [
          "Imports"
        ],
        "parameters": [
          {
            "name": "body",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/BulkCreateTasksDto"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/BulkImportResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/imports/leads": {
      "post": {
        "operationId": "ImportsController_leads",
        "summary": "Import CRM leads in bulk",
        "description": "Answers 200 with one `results` row per submitted row — `{index, status, id, code}` where `index` is the 0-based position in the request, `status` is `created`, `skipped` or `error`, `id` is the created lead (null otherwise) and `code` a machine-readable reason (null when created). A partial import is a report, not an HTTP failure. Idempotent: a row matching an existing lead by e-mail or by title + company is skipped (`duplicate_lead`) and ALSO listed in `duplicates` with the matched `existingId` and the match basis, so re-running the same file creates nothing twice. Max 500 rows per batch — chunk larger files.\n\n**Capability:** `org.admin` — an API key must carry this in its scope.",
        "tags": [
          "Imports"
        ],
        "parameters": [
          {
            "name": "body",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/BulkCreateLeadsDto"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/BulkImportWithDuplicatesResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/imports/contacts": {
      "post": {
        "operationId": "ImportsController_contacts",
        "summary": "Import customer contacts in bulk",
        "description": "Answers 200 with one `results` row per submitted row — `{index, status, id, code}` where `index` is the 0-based position in the request, `status` is `created`, `skipped` or `error`, `id` is the created contact (null otherwise) and `code` a machine-readable reason (null when created). A partial import is a report, not an HTTP failure. Idempotent: a row whose e-mail already exists on the same customer is skipped (`duplicate_contact`) and ALSO listed in `duplicates` with the matched `existingId`, so re-running the same file creates nothing twice. Max 500 rows per batch — chunk larger files.\n\n**Capability:** `org.admin` — an API key must carry this in its scope.",
        "tags": [
          "Imports"
        ],
        "parameters": [
          {
            "name": "body",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/BulkCreateContactsDto"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/BulkImportWithDuplicatesResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/intake": {
      "get": {
        "operationId": "IntakeController_list",
        "summary": "List intake items",
        "description": "**Capability:** `projects.manage` — an API key must carry this in its scope.",
        "tags": [
          "Intake"
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/IntakeListResponseDto"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      },
      "post": {
        "operationId": "IntakeController_create",
        "summary": "Create an intake item",
        "description": "Any member may drop a work request in; a project manager triages it.\n\n**Capability:** none — the operation acts as the authenticated member and its authorisation is row-level (ownership, the approver line, project membership). An API key with an empty scope reaches it.",
        "tags": [
          "Intake"
        ],
        "parameters": [
          {
            "name": "body",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/CreateIntakeItemDto"
            }
          }
        ],
        "responses": {
          "201": {
            "description": "Created.",
            "schema": {
              "$ref": "#/definitions/IntakeItemViewDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/intake/{id}/accept": {
      "post": {
        "operationId": "IntakeController_accept",
        "summary": "Accept an intake item into a project",
        "description": "**Capability:** `projects.manage` — an API key must carry this in its scope.",
        "tags": [
          "Intake"
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "type": "string"
          },
          {
            "name": "body",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/AcceptIntakeItemDto"
            }
          }
        ],
        "responses": {
          "201": {
            "description": "Created.",
            "schema": {
              "$ref": "#/definitions/IntakeItemViewDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/intake/{id}/route-to-lead": {
      "post": {
        "operationId": "IntakeController_routeToLead",
        "summary": "Route an intake item to a CRM lead",
        "description": "**Capability:** `crm.admin` — an API key must carry this in its scope.",
        "tags": [
          "Intake"
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "type": "string"
          },
          {
            "name": "body",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/RouteIntakeToLeadDto"
            }
          }
        ],
        "responses": {
          "201": {
            "description": "Created.",
            "schema": {
              "$ref": "#/definitions/IntakeItemViewDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/intake/{id}/dismiss": {
      "post": {
        "operationId": "IntakeController_dismiss",
        "summary": "Dismiss an intake item",
        "description": "**Capability:** `projects.manage` — an API key must carry this in its scope.",
        "tags": [
          "Intake"
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "type": "string"
          },
          {
            "name": "body",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/DismissIntakeItemDto"
            }
          }
        ],
        "responses": {
          "201": {
            "description": "Created.",
            "schema": {
              "$ref": "#/definitions/IntakeItemViewDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/projects/{id}/change-orders": {
      "get": {
        "operationId": "ChangeOrdersController_list",
        "summary": "List the change orders of a project",
        "description": "**Capability:** `projects.read` — an API key must carry this in its scope.",
        "tags": [
          "Projects"
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "type": "string"
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/ChangeOrderListResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      },
      "post": {
        "operationId": "ChangeOrdersController_create",
        "summary": "Create a change order on a project",
        "description": "**Capability:** `projects.manage` — an API key must carry this in its scope.",
        "tags": [
          "Projects"
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "type": "string"
          },
          {
            "name": "body",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/CreateChangeOrderDto"
            }
          }
        ],
        "responses": {
          "201": {
            "description": "Created.",
            "schema": {
              "$ref": "#/definitions/ChangeOrderViewDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/projects/{id}/change-orders/{orderId}/approve": {
      "post": {
        "operationId": "ChangeOrdersController_approve",
        "summary": "Record a manual approval of a change order",
        "description": "Records an approval agreed outside the customer link (phone, on site).\n\n**Capability:** `projects.manage` — an API key must carry this in its scope.",
        "tags": [
          "Projects"
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "type": "string"
          },
          {
            "name": "orderId",
            "required": true,
            "in": "path",
            "type": "string"
          },
          {
            "name": "body",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/ApproveChangeOrderDto"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/ChangeOrderViewDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/search": {
      "get": {
        "operationId": "SearchController_search",
        "summary": "Search across people, projects, tasks, customers and CRM records",
        "description": "One aggregate query over every entity family the caller may read. `limit` is a PER-GROUP cap (default 6, max 10), not a total — the response is bounded by design and therefore not cursor-paginated. Hits carry machine-readable ids only; a group the caller cannot read comes back as an empty array.\n\n**Capability:** `reports.team` or `crm.use` — an API key must carry one of these in its scope.",
        "tags": [
          "Search"
        ],
        "parameters": [
          {
            "name": "q",
            "required": true,
            "in": "query",
            "minLength": 1,
            "maxLength": 120,
            "type": "string"
          },
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "minimum": 1,
            "maximum": 10,
            "default": 6,
            "type": "integer"
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/SearchResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/expense-types": {
      "get": {
        "operationId": "ExpensesController_listTypes",
        "summary": "List the expense types a claim can use",
        "description": "The organisation’s expense catalogue: receipts, allowances and mileage types, with the unit each is priced in. Resolve the `expenseTypeId` a claim line needs from here — a mileage type takes the `mileage` block instead of an amount.\n\n**Capability:** none — the operation acts as the authenticated member and its authorisation is row-level (ownership, the approver line, project membership). An API key with an empty scope reaches it.",
        "tags": [
          "Expenses"
        ],
        "parameters": [
          {
            "name": "all",
            "required": false,
            "in": "query",
            "type": "string"
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/ExpenseTypeListResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/me/expenses": {
      "get": {
        "operationId": "ExpensesController_listMine",
        "summary": "List the caller’s own expense claims",
        "description": "Cursor-paginated, newest first. Optional `from`/`to` (expense date), `status` and `category` (`drive` = mileage lines, `expense` = everything else) narrow the set.\n\n**Capability:** none — the operation acts as the authenticated member and its authorisation is row-level (ownership, the approver line, project membership). An API key with an empty scope reaches it.",
        "tags": [
          "Expenses"
        ],
        "parameters": [
          {
            "name": "cursor",
            "required": false,
            "in": "query",
            "type": "string"
          },
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "minimum": 1,
            "maximum": 100,
            "default": 50,
            "type": "integer"
          },
          {
            "name": "from",
            "required": false,
            "in": "query",
            "type": "string"
          },
          {
            "name": "to",
            "required": false,
            "in": "query",
            "type": "string"
          },
          {
            "name": "status",
            "required": false,
            "in": "query",
            "enum": [
              "draft",
              "submitted",
              "approved"
            ],
            "type": "string"
          },
          {
            "name": "category",
            "required": false,
            "in": "query",
            "enum": [
              "drive",
              "expense"
            ],
            "type": "string"
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/ExpenseListResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      },
      "post": {
        "operationId": "ExpensesController_create",
        "summary": "Create a draft expense claim line for the caller",
        "description": "Creates the line as a DRAFT — it enters no approval queue and moves no money until it is submitted. Give `amountCents` for a receipt or allowance line, or the `mileage` block for a kilometre type (the server prices it from the organisation’s rates). `tripId` attaches the line to a trip, where it is decided with the trip rather than on its own.\n\n**Capability:** none — the operation acts as the authenticated member and its authorisation is row-level (ownership, the approver line, project membership). An API key with an empty scope reaches it.",
        "tags": [
          "Expenses"
        ],
        "parameters": [
          {
            "name": "body",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/CreateExpenseDto"
            }
          }
        ],
        "responses": {
          "201": {
            "description": "Created.",
            "schema": {
              "$ref": "#/definitions/ExpenseIdResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/me/expenses/{id}": {
      "delete": {
        "operationId": "ExpensesController_remove",
        "summary": "Delete the caller’s draft expense claim line",
        "description": "Draft lines only.\n\n**Capability:** none — the operation acts as the authenticated member and its authorisation is row-level (ownership, the approver line, project membership). An API key with an empty scope reaches it.",
        "tags": [
          "Expenses"
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "type": "string"
          }
        ],
        "responses": {
          "204": {
            "description": "No content."
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      },
      "patch": {
        "operationId": "ExpensesController_update",
        "summary": "Update the caller’s draft expense claim line",
        "description": "Draft lines only — a submitted line is reopened first (409 otherwise).\n\n**Capability:** none — the operation acts as the authenticated member and its authorisation is row-level (ownership, the approver line, project membership). An API key with an empty scope reaches it.",
        "tags": [
          "Expenses"
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "type": "string"
          },
          {
            "name": "body",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/UpdateExpenseDto"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/ExpenseOkResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/me/expenses/{id}/submit": {
      "post": {
        "operationId": "ExpensesController_submit",
        "summary": "Submit the caller’s expense claim line for approval",
        "description": "Hands the line to the approver and freezes its amount. This is the step that turns a draft into a pending decision — leave it to the person whose claim it is unless your integration IS that person’s system of record.\n\n**Capability:** none — the operation acts as the authenticated member and its authorisation is row-level (ownership, the approver line, project membership). An API key with an empty scope reaches it.",
        "tags": [
          "Expenses"
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "type": "string"
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/ExpenseOkResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/me/expenses/{id}/reopen": {
      "post": {
        "operationId": "ExpensesController_reopen",
        "summary": "Reopen the caller’s submitted expense claim line",
        "description": "Takes a submitted line back to draft. An approved line is not reopenable.\n\n**Capability:** none — the operation acts as the authenticated member and its authorisation is row-level (ownership, the approver line, project membership). An API key with an empty scope reaches it.",
        "tags": [
          "Expenses"
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "type": "string"
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/ExpenseOkResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/expenses/{id}/approve": {
      "post": {
        "operationId": "ExpensesController_approve",
        "summary": "Approve an expense claim",
        "description": "The decision half of the `expense` rows in the approval queue. Requires supervisor authority over the claimant.\n\n**Capability:** `worktime.supervise` — an API key must carry this in its scope.",
        "tags": [
          "Approvals"
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "type": "string"
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/ExpenseOkResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/expenses/{id}/return": {
      "post": {
        "operationId": "ExpensesController_returnToDraft",
        "summary": "Return an expense claim to the claimant",
        "description": "The other decision half of the `expense` rows in the approval queue: the line reopens as the claimant’s draft and the reason routes back to them. Requires supervisor authority over the claimant.\n\n**Capability:** `worktime.supervise` — an API key must carry this in its scope.",
        "tags": [
          "Approvals"
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "type": "string"
          },
          {
            "name": "body",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/ReturnExpenseDto"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/ExpenseOkResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "402": {
            "description": "The organisation’s plan does not include the module this operation belongs to (`feature_not_in_plan`, with the missing `feature` named in the body). Not a permission problem — an administrator activates the module in Kelomo.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/me/punch/clock-in": {
      "post": {
        "operationId": "PunchesController_clockIn",
        "summary": "Clock the caller in",
        "description": "Opens a punch session for the caller with their own key. Requires the organisation’s punch clock to be enabled (403 punch_clock_disabled otherwise) and no session already open (409 punch_session_open). Send a `clientPunchId` (UUID, generated ONCE per tap and reused on every retry): a replay of a punch that already landed returns the live session state instead of opening a second one, so a lost response can never double-punch. `occurredAt` may back-date the punch for an offline queue (at most 60 days back, at most 5 minutes into the future); omit it for server-now. Send `occurredAtSource: \"entered\"` when a PERSON typed that time rather than a clock observing it: it is recorded on the punch and shown to supervisors, the organisation may forbid it (403 backdated_punch_disabled), and it has its own, much shorter window (422 backdated_punch_too_old) — the 60-day tolerance is for an offline queue, not for repairing an old bookkeeping week. This is the self-service clock — a shared wall terminal uses the device realm and its own pairing credential, not a member key.\n\n**Capability:** none — the operation acts as the authenticated member and its authorisation is row-level (ownership, the approver line, project membership). An API key with an empty scope reaches it.",
        "tags": [
          "Me"
        ],
        "parameters": [
          {
            "name": "body",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/ClockInDto"
            }
          }
        ],
        "responses": {
          "201": {
            "description": "Created.",
            "schema": {
              "$ref": "#/definitions/PunchSessionStateDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/me/punch/break-start": {
      "post": {
        "operationId": "PunchesController_breakStart",
        "summary": "Start a break on the caller’s open session",
        "description": "Needs an open session (409 no_open_session) that is not already on a break (409 already_on_break). Carries the break type: a `reasonId` from the organisation’s punch reasons, or `paid` directly. Idempotent through `clientPunchId` exactly like clock-in — a replayed break punch returns the live state instead of a second mark.\n\n**Capability:** none — the operation acts as the authenticated member and its authorisation is row-level (ownership, the approver line, project membership). An API key with an empty scope reaches it.",
        "tags": [
          "Me"
        ],
        "parameters": [
          {
            "name": "body",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/PunchMarkDto"
            }
          }
        ],
        "responses": {
          "201": {
            "description": "Created.",
            "schema": {
              "$ref": "#/definitions/PunchSessionStateDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/me/punch/break-end": {
      "post": {
        "operationId": "PunchesController_breakEnd",
        "summary": "End the break on the caller’s open session",
        "description": "Needs an open session that IS on a break (409 not_on_break). Idempotent through `clientPunchId` like the other punches.\n\n**Capability:** none — the operation acts as the authenticated member and its authorisation is row-level (ownership, the approver line, project membership). An API key with an empty scope reaches it.",
        "tags": [
          "Me"
        ],
        "parameters": [
          {
            "name": "body",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/PunchMarkDto"
            }
          }
        ],
        "responses": {
          "201": {
            "description": "Created.",
            "schema": {
              "$ref": "#/definitions/PunchSessionStateDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/me/punch/absence-gap": {
      "post": {
        "operationId": "PunchesController_absenceGap",
        "summary": "Explain the caller’s unexplained past days as an absence",
        "description": "Records the span `GET /me/punch/state` offered in `returnGap` as leave, using a punch reason the organisation marked usable on clock-in (422 punch_reason_not_usable_on_clock_in otherwise). Send back the span you SHOWED the member: a span reaching today or the future, or longer than 31 days, is refused (422 punch_return_gap_invalid) — those belong to the planned leave flow and to the supervisor. Days already covered by an existing absence are skipped, never overwritten. Returns the refreshed session state, whose `returnGap` is then empty.\n\n**Capability:** none — the operation acts as the authenticated member and its authorisation is row-level (ownership, the approver line, project membership). An API key with an empty scope reaches it.",
        "tags": [
          "Me"
        ],
        "parameters": [
          {
            "name": "body",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/RecordAbsenceGapDto"
            }
          }
        ],
        "responses": {
          "201": {
            "description": "Created.",
            "schema": {
              "$ref": "#/definitions/PunchSessionStateDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/me/punch/set-allocation": {
      "post": {
        "operationId": "PunchesController_setAllocation",
        "summary": "Retarget the caller’s open session to another project or task",
        "description": "Rewrites the open session’s project / cost-centre allocation (or `taskId`) mid-shift, so the draft day the session materialises books to the new target. Needs an open session (409 no_open_session). A full replacement of the session’s allocation hint — sending it twice leaves the same result — and it touches only a session whose day is still a draft, never a confirmed record.\n\n**Capability:** none — the operation acts as the authenticated member and its authorisation is row-level (ownership, the approver line, project membership). An API key with an empty scope reaches it.",
        "tags": [
          "Me"
        ],
        "parameters": [
          {
            "name": "body",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/SetPunchAllocationDto"
            }
          }
        ],
        "responses": {
          "201": {
            "description": "Created.",
            "schema": {
              "$ref": "#/definitions/PunchSessionStateDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/me/punch/clock-out": {
      "post": {
        "operationId": "PunchesController_clockOut",
        "summary": "Clock the caller out",
        "description": "Closes the open session (409 no_open_session if there is none) and materialises the session into the DRAFT work day it produced, which is returned so the caller can review and confirm it. The day is a draft, never a confirmed record — confirmation is a separate, explicit act. Idempotent through `clientPunchId`: a replayed clock-out reads back the same materialised day instead of failing. `reasonId` carries the day-ending reason when the organisation asks for one (422 punch_reason_required). A member who forgot to clock out may send the time they finished as `occurredAt` together with `occurredAtSource: \"entered\"`; see the clock-in description for the switch and the window that govern it.\n\n**Capability:** none — the operation acts as the authenticated member and its authorisation is row-level (ownership, the approver line, project membership). An API key with an empty scope reaches it.",
        "tags": [
          "Me"
        ],
        "parameters": [
          {
            "name": "body",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/PunchMarkDto"
            }
          }
        ],
        "responses": {
          "201": {
            "description": "Created.",
            "schema": {
              "$ref": "#/definitions/WorkDayDetailResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/me/punch/day/{date}/rebuild": {
      "post": {
        "operationId": "PunchesController_rebuildDay",
        "summary": "Rebuild the caller’s work day from its recorded punches",
        "description": "Re-derives the day’s DRAFT from the punches it already holds. Punches recorded while the day could not take them (an approved leave day, a confirmed record, hand-entered rows) stay in the stream as evidence; this is what turns them back into a work day once the obstacle is gone. Refused while the obstacle stands (409 with the lock code: day_on_approved_leave, day_confirmed_locked, day_has_manual_entries, day_has_duration_entries) and when the day holds no punches to derive from (422 punch_day_not_punched). Never touches a confirmed record — the day is rebuilt as a draft, exactly as a clock-out would.\n\n**Capability:** none — the operation acts as the authenticated member and its authorisation is row-level (ownership, the approver line, project membership). An API key with an empty scope reaches it.",
        "tags": [
          "Me"
        ],
        "parameters": [
          {
            "name": "date",
            "required": true,
            "in": "path",
            "type": "string"
          }
        ],
        "responses": {
          "201": {
            "description": "Created.",
            "schema": {
              "$ref": "#/definitions/PunchDayViewDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "409": {
            "description": "Conflict with the object’s current state — an append-only boundary, a concurrent edit, or an idempotency-key collision (`idempotency_key_reused`, `idempotency_key_in_flight`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/team/presence": {
      "get": {
        "operationId": "PunchPresenceController_presence",
        "summary": "List who is on the clock right now",
        "description": "Requires the tenant’s presence board to be enabled; scoped to the caller’s reports.\n\n**Capability:** `worktime.supervise` — an API key must carry this in its scope.",
        "tags": [
          "Presence"
        ],
        "parameters": [
          {
            "name": "cursor",
            "required": false,
            "in": "query",
            "type": "string"
          },
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "minimum": 1,
            "maximum": 100,
            "default": 50,
            "type": "integer"
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/TeamPresenceViewDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/payroll-locks": {
      "get": {
        "operationId": "PayrollLocksController_list",
        "summary": "List payroll period locks",
        "description": "**Capability:** `payroll.run` — an API key must carry this in its scope.",
        "tags": [
          "Payroll exports"
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/PayrollPeriodLockListResponseDto"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/reports": {
      "get": {
        "operationId": "PublicReportsController_listTypes",
        "summary": "List report types available to the caller",
        "description": "The closed report-type catalogue filtered by the caller’s capabilities and the tenant’s enabled modules. Types carrying person-level absence/health data are never available over the API.\n\n**Capability:** `reports.team` — an API key must carry this in its scope.",
        "tags": [
          "Reports"
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/PublicReportTypesResponseDto"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/reports/{type}": {
      "get": {
        "operationId": "PublicReportsController_generate",
        "summary": "Generate a report as a file",
        "description": "Renders one report type as PDF, XLSX or CSV for the inclusive period from–to (max 366 days). Snapshot-style types (hr headcount, qualification matrix, leave valuations) read the period end as their valuation date. The caller must hold the type’s capability; 403 report_type_not_public for types excluded from the API.\n\n**Capability:** `reports.team` — an API key must carry this in its scope.",
        "tags": [
          "Reports"
        ],
        "parameters": [
          {
            "name": "type",
            "required": true,
            "in": "path",
            "type": "string"
          },
          {
            "name": "from",
            "required": true,
            "in": "query",
            "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
            "type": "string"
          },
          {
            "name": "to",
            "required": true,
            "in": "query",
            "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
            "type": "string"
          },
          {
            "name": "format",
            "required": false,
            "in": "query",
            "default": "pdf",
            "type": "string",
            "enum": [
              "pdf",
              "xlsx",
              "csv"
            ]
          },
          {
            "name": "groupId",
            "required": false,
            "in": "query",
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
            "type": "string"
          },
          {
            "name": "locale",
            "required": false,
            "in": "query",
            "default": "fi",
            "type": "string",
            "enum": [
              "fi",
              "sv",
              "en"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Success."
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "404": {
            "description": "No such object in this organisation.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    },
    "/v1/team/approvals": {
      "get": {
        "operationId": "ApprovalsController_queue",
        "summary": "List items awaiting the caller’s approval decision",
        "description": "**Capability:** `worktime.supervise` — an API key must carry this in its scope.",
        "tags": [
          "Approvals"
        ],
        "parameters": [
          {
            "name": "cursor",
            "required": false,
            "in": "query",
            "type": "string"
          },
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "minimum": 1,
            "maximum": 100,
            "default": 50,
            "type": "integer"
          },
          {
            "name": "kind",
            "required": false,
            "in": "query",
            "type": "string",
            "enum": [
              "work_week",
              "expense",
              "trip",
              "leave",
              "swap",
              "training",
              "open_shift_claim",
              "leave_save"
            ]
          },
          {
            "name": "today",
            "required": true,
            "in": "query",
            "type": "string"
          },
          {
            "name": "lookbackDays",
            "required": false,
            "in": "query",
            "type": "number"
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "schema": {
              "$ref": "#/definitions/ApprovalQueueResponseDto"
            }
          },
          "400": {
            "description": "Malformed request: schema validation failed, a parameter value is out of range, or a required header is missing (`idempotency_key_required`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "401": {
            "description": "Missing, expired or revoked credentials — `invalid_token`, `api_key_expired`, `api_key_owner_inactive`.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "403": {
            "description": "Authenticated but not permitted: the key’s scope or the member’s capabilities do not cover the operation (`insufficient_role`), or the key is read-only (`read_only_key`).",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "429": {
            "description": "Rate limit exceeded for the key or for the organisation. Wait `Retry-After` seconds and retry.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          },
          "500": {
            "description": "Unexpected server error. Retry idempotent operations; quote `requestId` if it persists.",
            "schema": {
              "$ref": "#/definitions/Problem"
            }
          }
        }
      }
    }
  },
  "definitions": {
    "AuditEventPageResponseDto": {
      "type": "object",
      "properties": {
        "items": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "action": {
                "type": "string"
              },
              "entity": {
                "type": "string"
              },
              "entityId": {
                "type": "string"
              },
              "actorName": {
                "type": "string",
                "x-nullable": true
              },
              "viaApiKey": {
                "type": "boolean"
              },
              "occurredAt": {
                "type": "string",
                "format": "date-time",
                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
              }
            },
            "required": [
              "id",
              "action",
              "entity",
              "entityId",
              "actorName",
              "viaApiKey",
              "occurredAt"
            ]
          }
        },
        "pageInfo": {
          "type": "object",
          "properties": {
            "nextCursor": {
              "type": "string",
              "x-nullable": true
            },
            "hasMore": {
              "type": "boolean"
            }
          },
          "required": [
            "nextCursor",
            "hasMore"
          ]
        }
      },
      "required": [
        "items",
        "pageInfo"
      ]
    },
    "InitiateAttachmentDto": {
      "type": "object",
      "properties": {
        "ownerType": {
          "type": "string",
          "enum": [
            "expense",
            "trip",
            "employment",
            "employee_profile",
            "membership_skill",
            "checklist_run",
            "compliance_item",
            "membership",
            "absence_period",
            "task",
            "project",
            "purchase",
            "case_note",
            "training_participation",
            "safety_incident",
            "candidate",
            "whistleblowing_report",
            "deal",
            "quote",
            "service_request",
            "emergency_work_notice",
            "invoice"
          ]
        },
        "ownerId": {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
        },
        "originalName": {
          "type": "string",
          "minLength": 1,
          "maxLength": 255
        },
        "contentType": {
          "type": "string",
          "enum": [
            "image/jpeg",
            "image/png",
            "image/webp",
            "image/heic",
            "application/pdf",
            "application/msword",
            "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
            "application/vnd.ms-excel",
            "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
            "application/vnd.ms-powerpoint",
            "application/vnd.openxmlformats-officedocument.presentationml.presentation",
            "application/vnd.oasis.opendocument.text",
            "application/vnd.oasis.opendocument.spreadsheet",
            "application/vnd.oasis.opendocument.presentation",
            "text/csv",
            "text/plain"
          ]
        },
        "sizeBytes": {
          "type": "integer",
          "exclusiveMinimum": true,
          "maximum": 9007199254740991,
          "minimum": 0
        },
        "category": {
          "type": "string",
          "enum": [
            "contract",
            "certificate",
            "id_document",
            "payroll",
            "policy",
            "onboarding",
            "other",
            "offer",
            "plan",
            "photo",
            "minutes",
            "report"
          ]
        },
        "documentCategoryId": {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
        }
      },
      "required": [
        "ownerType",
        "ownerId",
        "originalName",
        "contentType",
        "sizeBytes"
      ]
    },
    "InitiateAttachmentResponseDto": {
      "type": "object",
      "properties": {
        "attachmentId": {
          "type": "string"
        },
        "upload": {
          "type": "object",
          "properties": {
            "url": {
              "type": "string"
            },
            "method": {
              "type": "string",
              "enum": [
                "PUT"
              ]
            },
            "headers": {
              "type": "object",
              "additionalProperties": {
                "type": "string"
              }
            },
            "expiresInSeconds": {
              "type": "integer",
              "exclusiveMinimum": true,
              "maximum": 9007199254740991,
              "minimum": 0
            }
          },
          "required": [
            "url",
            "method",
            "headers",
            "expiresInSeconds"
          ]
        }
      },
      "required": [
        "attachmentId",
        "upload"
      ]
    },
    "AttachmentViewDto": {
      "type": "object",
      "properties": {
        "id": {
          "type": "string"
        },
        "ownerType": {
          "type": "string",
          "enum": [
            "expense",
            "trip",
            "employment",
            "employee_profile",
            "membership_skill",
            "checklist_run",
            "compliance_item",
            "membership",
            "absence_period",
            "task",
            "project",
            "purchase",
            "case_note",
            "training_participation",
            "safety_incident",
            "candidate",
            "whistleblowing_report",
            "deal",
            "quote",
            "service_request",
            "emergency_work_notice",
            "invoice"
          ]
        },
        "ownerId": {
          "type": "string"
        },
        "originalName": {
          "type": "string"
        },
        "contentType": {
          "type": "string"
        },
        "sizeBytes": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991
        },
        "category": {
          "type": "string",
          "enum": [
            "contract",
            "certificate",
            "id_document",
            "payroll",
            "policy",
            "onboarding",
            "other",
            "offer",
            "plan",
            "photo",
            "minutes",
            "report",
            null
          ],
          "x-nullable": true
        },
        "documentCategoryId": {
          "type": "string",
          "x-nullable": true
        },
        "status": {
          "type": "string",
          "enum": [
            "pending",
            "scanning",
            "ready",
            "rejected"
          ]
        },
        "uploadedByMembershipId": {
          "type": "string",
          "x-nullable": true
        },
        "uploadedAt": {
          "type": "string",
          "x-nullable": true
        },
        "createdAt": {
          "type": "string"
        },
        "signingStatus": {
          "type": "string",
          "enum": [
            "none",
            "pending",
            "signed",
            "declined",
            "cancelled"
          ]
        },
        "signedAt": {
          "type": "string",
          "x-nullable": true
        }
      },
      "required": [
        "id",
        "ownerType",
        "ownerId",
        "originalName",
        "contentType",
        "sizeBytes",
        "category",
        "documentCategoryId",
        "status",
        "uploadedByMembershipId",
        "uploadedAt",
        "createdAt",
        "signingStatus",
        "signedAt"
      ]
    },
    "AttachmentListResponseDto": {
      "type": "object",
      "properties": {
        "attachments": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "ownerType": {
                "type": "string",
                "enum": [
                  "expense",
                  "trip",
                  "employment",
                  "employee_profile",
                  "membership_skill",
                  "checklist_run",
                  "compliance_item",
                  "membership",
                  "absence_period",
                  "task",
                  "project",
                  "purchase",
                  "case_note",
                  "training_participation",
                  "safety_incident",
                  "candidate",
                  "whistleblowing_report",
                  "deal",
                  "quote",
                  "service_request",
                  "emergency_work_notice",
                  "invoice"
                ]
              },
              "ownerId": {
                "type": "string"
              },
              "originalName": {
                "type": "string"
              },
              "contentType": {
                "type": "string"
              },
              "sizeBytes": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "category": {
                "type": "string",
                "enum": [
                  "contract",
                  "certificate",
                  "id_document",
                  "payroll",
                  "policy",
                  "onboarding",
                  "other",
                  "offer",
                  "plan",
                  "photo",
                  "minutes",
                  "report",
                  null
                ],
                "x-nullable": true
              },
              "documentCategoryId": {
                "type": "string",
                "x-nullable": true
              },
              "status": {
                "type": "string",
                "enum": [
                  "pending",
                  "scanning",
                  "ready",
                  "rejected"
                ]
              },
              "uploadedByMembershipId": {
                "type": "string",
                "x-nullable": true
              },
              "uploadedAt": {
                "type": "string",
                "x-nullable": true
              },
              "createdAt": {
                "type": "string"
              },
              "signingStatus": {
                "type": "string",
                "enum": [
                  "none",
                  "pending",
                  "signed",
                  "declined",
                  "cancelled"
                ]
              },
              "signedAt": {
                "type": "string",
                "x-nullable": true
              }
            },
            "required": [
              "id",
              "ownerType",
              "ownerId",
              "originalName",
              "contentType",
              "sizeBytes",
              "category",
              "documentCategoryId",
              "status",
              "uploadedByMembershipId",
              "uploadedAt",
              "createdAt",
              "signingStatus",
              "signedAt"
            ]
          }
        }
      },
      "required": [
        "attachments"
      ]
    },
    "AttachmentDownloadResponseDto": {
      "type": "object",
      "properties": {
        "url": {
          "type": "string"
        },
        "expiresInSeconds": {
          "type": "integer",
          "exclusiveMinimum": true,
          "maximum": 9007199254740991,
          "minimum": 0
        }
      },
      "required": [
        "url",
        "expiresInSeconds"
      ]
    },
    "WorkDayRangeResponseDto": {
      "type": "object",
      "properties": {
        "days": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "workDate": {
                "type": "string",
                "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
              },
              "status": {
                "type": "string",
                "enum": [
                  "proposed",
                  "draft",
                  "confirmed",
                  "approved",
                  "exported"
                ]
              },
              "startMinutes": {
                "type": "integer",
                "minimum": 0,
                "maximum": 1440,
                "x-nullable": true
              },
              "endMinutes": {
                "type": "integer",
                "minimum": 1,
                "maximum": 2880,
                "x-nullable": true
              },
              "breakMinutes": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "breaks": {
                "default": [],
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "x-nullable": true
                    },
                    "startMinutes": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991
                    },
                    "endMinutes": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991
                    },
                    "breakTypeId": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "x-nullable": true
                    },
                    "paidMinutes": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991
                    }
                  },
                  "required": [
                    "id",
                    "startMinutes",
                    "endMinutes",
                    "breakTypeId",
                    "paidMinutes"
                  ]
                }
              },
              "paidBreakMinutes": {
                "default": 0,
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "workMinutes": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "creditedMinutes": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "targetMinutes": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "appliedCreditMinutes": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "uncountedMinutes": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "rawDeltaMinutes": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "balanceDeltaMinutes": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "attentionThresholdMinutes": {
                "default": 15,
                "type": "integer",
                "minimum": 0,
                "maximum": 480
              },
              "runningBalanceMinutes": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "overtimeMinutes": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "dayType": {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "string"
                  },
                  "code": {
                    "type": "string",
                    "pattern": "^[a-z][a-z0-9_]{1,49}$"
                  },
                  "nameFi": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 100
                  },
                  "nameSv": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 100
                  },
                  "nameEn": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 100
                  }
                },
                "required": [
                  "id",
                  "code",
                  "nameFi",
                  "nameSv",
                  "nameEn"
                ],
                "x-nullable": true
              },
              "absencePeriod": {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "string",
                    "format": "uuid",
                    "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                  },
                  "status": {
                    "type": "string",
                    "enum": [
                      "draft",
                      "submitted",
                      "approved",
                      "rejected",
                      "cancelled",
                      "withdrawn"
                    ]
                  },
                  "workflowMode": {
                    "type": "string",
                    "enum": [
                      "request",
                      "notification",
                      "employer_assignment"
                    ]
                  },
                  "nameFi": {
                    "type": "string"
                  },
                  "nameSv": {
                    "type": "string"
                  },
                  "nameEn": {
                    "type": "string"
                  }
                },
                "required": [
                  "id",
                  "status",
                  "workflowMode",
                  "nameFi",
                  "nameSv",
                  "nameEn"
                ],
                "x-nullable": true
              },
              "sources": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "type": {
                      "type": "string",
                      "enum": [
                        "worktime-model",
                        "calendar-event",
                        "planned-shift",
                        "punch",
                        "learned-baseline"
                      ]
                    },
                    "versionId": {
                      "type": "string"
                    },
                    "eventId": {
                      "type": "string"
                    },
                    "shiftId": {
                      "type": "string"
                    },
                    "punchSessionId": {
                      "type": "string"
                    },
                    "weekday": {
                      "type": "integer",
                      "minimum": 1,
                      "maximum": 7
                    }
                  },
                  "required": [
                    "type"
                  ]
                }
              },
              "deviations": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "type": {
                      "type": "string",
                      "enum": [
                        "overlong-day",
                        "short-day",
                        "missing-break",
                        "missing-second-break",
                        "fragmented-break",
                        "break-at-day-edge",
                        "flex-limit-exceeded",
                        "outside-flex-window",
                        "outside-allowed-window",
                        "work-on-day-off",
                        "entry-over-max-duration",
                        "insufficient-daily-rest",
                        "insufficient-weekly-rest"
                      ]
                    },
                    "deltaMinutes": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991
                    },
                    "severity": {
                      "type": "string",
                      "enum": [
                        "advisory",
                        "info"
                      ]
                    }
                  },
                  "required": [
                    "type",
                    "deltaMinutes"
                  ]
                }
              },
              "overtimeDisposition": {
                "default": "flex",
                "type": "string",
                "enum": [
                  "flex",
                  "payout",
                  "ignore",
                  "bank"
                ]
              },
              "bankAccountTypeId": {
                "type": "string",
                "default": null,
                "x-nullable": true
              },
              "entries": {
                "default": [],
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "entryTypeId": {
                      "type": "string"
                    },
                    "entryTypeCode": {
                      "type": "string",
                      "pattern": "^[a-z][a-z0-9_]{1,49}$"
                    },
                    "startMinutes": {
                      "type": "integer",
                      "minimum": 0,
                      "maximum": 2879,
                      "x-nullable": true
                    },
                    "endMinutes": {
                      "type": "integer",
                      "minimum": 1,
                      "maximum": 2880,
                      "x-nullable": true
                    },
                    "durationMinutes": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991,
                      "default": null,
                      "x-nullable": true
                    },
                    "note": {
                      "type": "string",
                      "x-nullable": true
                    },
                    "billable": {
                      "type": "boolean"
                    },
                    "billingBaseMinutes": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991,
                      "default": null,
                      "x-nullable": true
                    },
                    "allocations": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "dimensionId": {
                            "type": "string"
                          },
                          "valueId": {
                            "type": "string"
                          },
                          "valueCode": {
                            "type": "string"
                          },
                          "valueName": {
                            "type": "string"
                          },
                          "weightBp": {
                            "type": "integer",
                            "minimum": -9007199254740991,
                            "maximum": 9007199254740991
                          }
                        },
                        "required": [
                          "dimensionId",
                          "valueId",
                          "valueCode",
                          "valueName",
                          "weightBp"
                        ]
                      }
                    }
                  },
                  "required": [
                    "id",
                    "entryTypeId",
                    "entryTypeCode",
                    "startMinutes",
                    "endMinutes",
                    "note",
                    "billable",
                    "allocations"
                  ]
                }
              },
              "proposedEntries": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "startMinutes": {
                      "type": "integer",
                      "minimum": 0,
                      "maximum": 1440
                    },
                    "endMinutes": {
                      "type": "integer",
                      "minimum": 1,
                      "maximum": 2880
                    },
                    "entryTypeId": {
                      "type": "string"
                    },
                    "billable": {
                      "type": "boolean"
                    },
                    "allocations": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "dimensionId": {
                            "type": "string"
                          },
                          "valueId": {
                            "type": "string"
                          },
                          "valueCode": {
                            "type": "string"
                          },
                          "valueName": {
                            "type": "string"
                          },
                          "weightBp": {
                            "default": 10000,
                            "type": "integer",
                            "minimum": -9007199254740991,
                            "maximum": 9007199254740991
                          },
                          "source": {
                            "type": "string",
                            "enum": [
                              "calendar",
                              "geofence",
                              "task",
                              "baseline",
                              "default"
                            ]
                          },
                          "confidence": {
                            "type": "string",
                            "enum": [
                              "high",
                              "medium",
                              "low"
                            ]
                          }
                        },
                        "required": [
                          "dimensionId",
                          "valueId",
                          "valueCode",
                          "valueName",
                          "source",
                          "confidence"
                        ]
                      }
                    },
                    "confidence": {
                      "type": "string",
                      "enum": [
                        "high",
                        "medium",
                        "low"
                      ]
                    }
                  },
                  "required": [
                    "startMinutes",
                    "endMinutes",
                    "entryTypeId",
                    "billable",
                    "allocations",
                    "confidence"
                  ]
                }
              },
              "expectedSource": {
                "type": "string",
                "x-nullable": true
              },
              "expectedWindow": {
                "type": "object",
                "properties": {
                  "startMinutes": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 1440
                  },
                  "endMinutes": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 1440
                  },
                  "breakMinutes": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 9007199254740991
                  }
                },
                "required": [
                  "startMinutes",
                  "endMinutes",
                  "breakMinutes"
                ],
                "x-nullable": true
              },
              "proposalDismissed": {
                "type": "boolean"
              },
              "updatedAt": {
                "type": "string",
                "default": null,
                "x-nullable": true
              },
              "returnReason": {
                "type": "string",
                "x-nullable": true
              },
              "confirmationOptional": {
                "type": "boolean"
              },
              "confirmedOnBehalf": {
                "type": "boolean"
              },
              "autoConfirmed": {
                "type": "boolean"
              },
              "confidence": {
                "type": "object",
                "properties": {
                  "level": {
                    "type": "string",
                    "enum": [
                      "high",
                      "medium",
                      "low"
                    ]
                  },
                  "reasons": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  }
                },
                "required": [
                  "level",
                  "reasons"
                ]
              },
              "supplements": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "supplementTypeId": {
                      "type": "string"
                    },
                    "supplementTypeCode": {
                      "type": "string",
                      "pattern": "^[a-z][a-z0-9_]{1,49}$"
                    },
                    "nameFi": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 100
                    },
                    "nameSv": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 100
                    },
                    "nameEn": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 100
                    },
                    "valueKind": {
                      "type": "string",
                      "enum": [
                        "flag",
                        "count",
                        "hours",
                        "amount"
                      ]
                    },
                    "unit": {
                      "type": "string",
                      "enum": [
                        "hours",
                        "pieces",
                        "days",
                        "decimal"
                      ]
                    },
                    "exportMode": {
                      "type": "string",
                      "enum": [
                        "passthrough",
                        "tesOnly"
                      ]
                    },
                    "quantity": {
                      "type": "number"
                    },
                    "startMinutes": {
                      "type": "integer",
                      "minimum": 0,
                      "maximum": 1440,
                      "x-nullable": true
                    },
                    "endMinutes": {
                      "type": "integer",
                      "minimum": 0,
                      "maximum": 1440,
                      "x-nullable": true
                    },
                    "comment": {
                      "type": "string",
                      "x-nullable": true
                    }
                  },
                  "required": [
                    "id",
                    "supplementTypeId",
                    "supplementTypeCode",
                    "nameFi",
                    "nameSv",
                    "nameEn",
                    "valueKind",
                    "unit",
                    "exportMode",
                    "quantity",
                    "startMinutes",
                    "endMinutes",
                    "comment"
                  ]
                }
              },
              "standby": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "periodId": {
                      "type": "string"
                    },
                    "standbyType": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        },
                        "code": {
                          "type": "string",
                          "pattern": "^[a-z][a-z0-9_]{1,49}$"
                        },
                        "nameFi": {
                          "type": "string",
                          "minLength": 1,
                          "maxLength": 100
                        },
                        "nameSv": {
                          "type": "string",
                          "minLength": 1,
                          "maxLength": 100
                        },
                        "nameEn": {
                          "type": "string",
                          "minLength": 1,
                          "maxLength": 100
                        },
                        "worktimeFraction": {
                          "type": "number",
                          "minimum": 0,
                          "maximum": 1
                        }
                      },
                      "required": [
                        "id",
                        "code",
                        "nameFi",
                        "nameSv",
                        "nameEn",
                        "worktimeFraction"
                      ]
                    },
                    "startMinutes": {
                      "type": "integer",
                      "minimum": 0,
                      "maximum": 1440
                    },
                    "endMinutes": {
                      "type": "integer",
                      "minimum": 1,
                      "maximum": 1440
                    }
                  },
                  "required": [
                    "periodId",
                    "standbyType",
                    "startMinutes",
                    "endMinutes"
                  ]
                }
              },
              "governingShiftType": {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "string",
                    "format": "uuid",
                    "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                  },
                  "nameFi": {
                    "type": "string"
                  },
                  "nameSv": {
                    "type": "string"
                  },
                  "nameEn": {
                    "type": "string"
                  },
                  "shortCode": {
                    "type": "string"
                  },
                  "color": {
                    "type": "string"
                  },
                  "source": {
                    "type": "string",
                    "enum": [
                      "plan",
                      "walk-up",
                      "rule",
                      "model-default",
                      "override"
                    ]
                  }
                },
                "required": [
                  "nameFi",
                  "nameSv",
                  "nameEn",
                  "shortCode",
                  "color"
                ]
              },
              "plannedShift": {
                "type": "object",
                "properties": {
                  "startMinutes": {
                    "type": "integer",
                    "minimum": -9007199254740991,
                    "maximum": 9007199254740991,
                    "x-nullable": true
                  },
                  "endMinutes": {
                    "type": "integer",
                    "minimum": -9007199254740991,
                    "maximum": 9007199254740991,
                    "x-nullable": true
                  },
                  "breakMinutes": {
                    "type": "integer",
                    "minimum": -9007199254740991,
                    "maximum": 9007199254740991
                  },
                  "targetMinutes": {
                    "type": "integer",
                    "minimum": -9007199254740991,
                    "maximum": 9007199254740991
                  },
                  "source": {
                    "type": "string",
                    "enum": [
                      "person-shift",
                      "group-shift"
                    ]
                  },
                  "shiftType": {
                    "type": "object",
                    "properties": {
                      "nameFi": {
                        "type": "string"
                      },
                      "nameSv": {
                        "type": "string"
                      },
                      "nameEn": {
                        "type": "string"
                      },
                      "shortCode": {
                        "type": "string"
                      },
                      "color": {
                        "type": "string"
                      }
                    },
                    "required": [
                      "nameFi",
                      "nameSv",
                      "nameEn",
                      "shortCode",
                      "color"
                    ],
                    "x-nullable": true
                  }
                },
                "required": [
                  "startMinutes",
                  "endMinutes",
                  "breakMinutes",
                  "targetMinutes",
                  "source",
                  "shiftType"
                ]
              }
            },
            "required": [
              "workDate",
              "status",
              "startMinutes",
              "endMinutes",
              "breakMinutes",
              "workMinutes",
              "creditedMinutes",
              "targetMinutes",
              "balanceDeltaMinutes",
              "runningBalanceMinutes",
              "overtimeMinutes",
              "dayType",
              "sources",
              "deviations",
              "expectedSource"
            ]
          }
        },
        "summary": {
          "type": "object",
          "properties": {
            "totalWorkMinutes": {
              "type": "integer",
              "minimum": -9007199254740991,
              "maximum": 9007199254740991
            },
            "totalTargetMinutes": {
              "type": "integer",
              "minimum": -9007199254740991,
              "maximum": 9007199254740991
            },
            "totalAppliedCreditMinutes": {
              "type": "integer",
              "minimum": -9007199254740991,
              "maximum": 9007199254740991
            },
            "totalUncountedMinutes": {
              "type": "integer",
              "minimum": -9007199254740991,
              "maximum": 9007199254740991
            },
            "totalPaidBreakMinutes": {
              "type": "integer",
              "minimum": -9007199254740991,
              "maximum": 9007199254740991
            },
            "totalUnpaidBreakMinutes": {
              "type": "integer",
              "minimum": -9007199254740991,
              "maximum": 9007199254740991
            },
            "totalUnitemisedBreakMinutes": {
              "type": "integer",
              "minimum": -9007199254740991,
              "maximum": 9007199254740991
            },
            "deltaMinutes": {
              "type": "integer",
              "minimum": -9007199254740991,
              "maximum": 9007199254740991
            },
            "recordedDeltaMinutes": {
              "type": "integer",
              "minimum": -9007199254740991,
              "maximum": 9007199254740991
            },
            "balanceBeforeMinutes": {
              "type": "integer",
              "minimum": -9007199254740991,
              "maximum": 9007199254740991
            },
            "projectedBalanceMinutes": {
              "type": "integer",
              "minimum": -9007199254740991,
              "maximum": 9007199254740991
            },
            "overtimeMinutes": {
              "type": "integer",
              "minimum": -9007199254740991,
              "maximum": 9007199254740991
            }
          },
          "required": [
            "totalWorkMinutes",
            "totalTargetMinutes",
            "deltaMinutes",
            "balanceBeforeMinutes",
            "projectedBalanceMinutes",
            "overtimeMinutes"
          ]
        },
        "worktimeRegime": {
          "default": "standard",
          "type": "string",
          "enum": [
            "standard",
            "flexwork",
            "period"
          ]
        },
        "currentWorktimePercentBp": {
          "type": "integer",
          "exclusiveMinimum": true,
          "maximum": 9007199254740991,
          "minimum": 0
        }
      },
      "required": [
        "days",
        "summary"
      ]
    },
    "WorkDayDetailResponseDto": {
      "type": "object",
      "properties": {
        "workDate": {
          "type": "string",
          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
        },
        "status": {
          "type": "string",
          "enum": [
            "proposed",
            "draft",
            "confirmed",
            "approved",
            "exported"
          ]
        },
        "startMinutes": {
          "type": "integer",
          "minimum": 0,
          "maximum": 1440,
          "x-nullable": true
        },
        "endMinutes": {
          "type": "integer",
          "minimum": 1,
          "maximum": 2880,
          "x-nullable": true
        },
        "breakMinutes": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991
        },
        "breaks": {
          "default": [],
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string",
                "format": "uuid",
                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                "x-nullable": true
              },
              "startMinutes": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "endMinutes": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "breakTypeId": {
                "type": "string",
                "format": "uuid",
                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                "x-nullable": true
              },
              "paidMinutes": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              }
            },
            "required": [
              "id",
              "startMinutes",
              "endMinutes",
              "breakTypeId",
              "paidMinutes"
            ]
          }
        },
        "paidBreakMinutes": {
          "default": 0,
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991
        },
        "workMinutes": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991
        },
        "creditedMinutes": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991
        },
        "targetMinutes": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991
        },
        "appliedCreditMinutes": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991
        },
        "uncountedMinutes": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991
        },
        "rawDeltaMinutes": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991
        },
        "balanceDeltaMinutes": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991
        },
        "attentionThresholdMinutes": {
          "default": 15,
          "type": "integer",
          "minimum": 0,
          "maximum": 480
        },
        "runningBalanceMinutes": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991
        },
        "overtimeMinutes": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991
        },
        "dayType": {
          "type": "object",
          "properties": {
            "id": {
              "type": "string"
            },
            "code": {
              "type": "string",
              "pattern": "^[a-z][a-z0-9_]{1,49}$"
            },
            "nameFi": {
              "type": "string",
              "minLength": 1,
              "maxLength": 100
            },
            "nameSv": {
              "type": "string",
              "minLength": 1,
              "maxLength": 100
            },
            "nameEn": {
              "type": "string",
              "minLength": 1,
              "maxLength": 100
            }
          },
          "required": [
            "id",
            "code",
            "nameFi",
            "nameSv",
            "nameEn"
          ],
          "x-nullable": true
        },
        "absencePeriod": {
          "type": "object",
          "properties": {
            "id": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            },
            "status": {
              "type": "string",
              "enum": [
                "draft",
                "submitted",
                "approved",
                "rejected",
                "cancelled",
                "withdrawn"
              ]
            },
            "workflowMode": {
              "type": "string",
              "enum": [
                "request",
                "notification",
                "employer_assignment"
              ]
            },
            "nameFi": {
              "type": "string"
            },
            "nameSv": {
              "type": "string"
            },
            "nameEn": {
              "type": "string"
            }
          },
          "required": [
            "id",
            "status",
            "workflowMode",
            "nameFi",
            "nameSv",
            "nameEn"
          ],
          "x-nullable": true
        },
        "sources": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "type": {
                "type": "string",
                "enum": [
                  "worktime-model",
                  "calendar-event",
                  "planned-shift",
                  "punch",
                  "learned-baseline"
                ]
              },
              "versionId": {
                "type": "string"
              },
              "eventId": {
                "type": "string"
              },
              "shiftId": {
                "type": "string"
              },
              "punchSessionId": {
                "type": "string"
              },
              "weekday": {
                "type": "integer",
                "minimum": 1,
                "maximum": 7
              }
            },
            "required": [
              "type"
            ]
          }
        },
        "deviations": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "type": {
                "type": "string",
                "enum": [
                  "overlong-day",
                  "short-day",
                  "missing-break",
                  "missing-second-break",
                  "fragmented-break",
                  "break-at-day-edge",
                  "flex-limit-exceeded",
                  "outside-flex-window",
                  "outside-allowed-window",
                  "work-on-day-off",
                  "entry-over-max-duration",
                  "insufficient-daily-rest",
                  "insufficient-weekly-rest"
                ]
              },
              "deltaMinutes": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "severity": {
                "type": "string",
                "enum": [
                  "advisory",
                  "info"
                ]
              }
            },
            "required": [
              "type",
              "deltaMinutes"
            ]
          }
        },
        "overtimeDisposition": {
          "default": "flex",
          "type": "string",
          "enum": [
            "flex",
            "payout",
            "ignore",
            "bank"
          ]
        },
        "bankAccountTypeId": {
          "type": "string",
          "default": null,
          "x-nullable": true
        },
        "entries": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "entryTypeId": {
                "type": "string"
              },
              "entryTypeCode": {
                "type": "string",
                "pattern": "^[a-z][a-z0-9_]{1,49}$"
              },
              "startMinutes": {
                "type": "integer",
                "minimum": 0,
                "maximum": 2879,
                "x-nullable": true
              },
              "endMinutes": {
                "type": "integer",
                "minimum": 1,
                "maximum": 2880,
                "x-nullable": true
              },
              "durationMinutes": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991,
                "default": null,
                "x-nullable": true
              },
              "note": {
                "type": "string",
                "x-nullable": true
              },
              "billable": {
                "type": "boolean"
              },
              "billingBaseMinutes": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991,
                "default": null,
                "x-nullable": true
              },
              "allocations": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "dimensionId": {
                      "type": "string"
                    },
                    "valueId": {
                      "type": "string"
                    },
                    "valueCode": {
                      "type": "string"
                    },
                    "valueName": {
                      "type": "string"
                    },
                    "weightBp": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991
                    }
                  },
                  "required": [
                    "dimensionId",
                    "valueId",
                    "valueCode",
                    "valueName",
                    "weightBp"
                  ]
                }
              }
            },
            "required": [
              "id",
              "entryTypeId",
              "entryTypeCode",
              "startMinutes",
              "endMinutes",
              "note",
              "billable",
              "allocations"
            ]
          }
        },
        "proposedEntries": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "startMinutes": {
                "type": "integer",
                "minimum": 0,
                "maximum": 1440
              },
              "endMinutes": {
                "type": "integer",
                "minimum": 1,
                "maximum": 2880
              },
              "entryTypeId": {
                "type": "string"
              },
              "billable": {
                "type": "boolean"
              },
              "allocations": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "dimensionId": {
                      "type": "string"
                    },
                    "valueId": {
                      "type": "string"
                    },
                    "valueCode": {
                      "type": "string"
                    },
                    "valueName": {
                      "type": "string"
                    },
                    "weightBp": {
                      "default": 10000,
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991
                    },
                    "source": {
                      "type": "string",
                      "enum": [
                        "calendar",
                        "geofence",
                        "task",
                        "baseline",
                        "default"
                      ]
                    },
                    "confidence": {
                      "type": "string",
                      "enum": [
                        "high",
                        "medium",
                        "low"
                      ]
                    }
                  },
                  "required": [
                    "dimensionId",
                    "valueId",
                    "valueCode",
                    "valueName",
                    "source",
                    "confidence"
                  ]
                }
              },
              "confidence": {
                "type": "string",
                "enum": [
                  "high",
                  "medium",
                  "low"
                ]
              }
            },
            "required": [
              "startMinutes",
              "endMinutes",
              "entryTypeId",
              "billable",
              "allocations",
              "confidence"
            ]
          }
        },
        "expectedSource": {
          "type": "string",
          "x-nullable": true
        },
        "expectedWindow": {
          "type": "object",
          "properties": {
            "startMinutes": {
              "type": "integer",
              "minimum": 0,
              "maximum": 1440
            },
            "endMinutes": {
              "type": "integer",
              "minimum": 0,
              "maximum": 1440
            },
            "breakMinutes": {
              "type": "integer",
              "minimum": 0,
              "maximum": 9007199254740991
            }
          },
          "required": [
            "startMinutes",
            "endMinutes",
            "breakMinutes"
          ],
          "x-nullable": true
        },
        "proposalDismissed": {
          "type": "boolean"
        },
        "updatedAt": {
          "type": "string",
          "default": null,
          "x-nullable": true
        },
        "returnReason": {
          "type": "string",
          "x-nullable": true
        },
        "confirmationOptional": {
          "type": "boolean"
        },
        "confirmedOnBehalf": {
          "type": "boolean"
        },
        "autoConfirmed": {
          "type": "boolean"
        },
        "confidence": {
          "type": "object",
          "properties": {
            "level": {
              "type": "string",
              "enum": [
                "high",
                "medium",
                "low"
              ]
            },
            "reasons": {
              "type": "array",
              "items": {
                "type": "string"
              }
            }
          },
          "required": [
            "level",
            "reasons"
          ]
        },
        "supplements": {
          "default": [],
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "supplementTypeId": {
                "type": "string"
              },
              "supplementTypeCode": {
                "type": "string",
                "pattern": "^[a-z][a-z0-9_]{1,49}$"
              },
              "nameFi": {
                "type": "string",
                "minLength": 1,
                "maxLength": 100
              },
              "nameSv": {
                "type": "string",
                "minLength": 1,
                "maxLength": 100
              },
              "nameEn": {
                "type": "string",
                "minLength": 1,
                "maxLength": 100
              },
              "valueKind": {
                "type": "string",
                "enum": [
                  "flag",
                  "count",
                  "hours",
                  "amount"
                ]
              },
              "unit": {
                "type": "string",
                "enum": [
                  "hours",
                  "pieces",
                  "days",
                  "decimal"
                ]
              },
              "exportMode": {
                "type": "string",
                "enum": [
                  "passthrough",
                  "tesOnly"
                ]
              },
              "quantity": {
                "type": "number"
              },
              "startMinutes": {
                "type": "integer",
                "minimum": 0,
                "maximum": 1440,
                "x-nullable": true
              },
              "endMinutes": {
                "type": "integer",
                "minimum": 0,
                "maximum": 1440,
                "x-nullable": true
              },
              "comment": {
                "type": "string",
                "x-nullable": true
              }
            },
            "required": [
              "id",
              "supplementTypeId",
              "supplementTypeCode",
              "nameFi",
              "nameSv",
              "nameEn",
              "valueKind",
              "unit",
              "exportMode",
              "quantity",
              "startMinutes",
              "endMinutes",
              "comment"
            ]
          }
        },
        "standby": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "periodId": {
                "type": "string"
              },
              "standbyType": {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "string"
                  },
                  "code": {
                    "type": "string",
                    "pattern": "^[a-z][a-z0-9_]{1,49}$"
                  },
                  "nameFi": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 100
                  },
                  "nameSv": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 100
                  },
                  "nameEn": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 100
                  },
                  "worktimeFraction": {
                    "type": "number",
                    "minimum": 0,
                    "maximum": 1
                  }
                },
                "required": [
                  "id",
                  "code",
                  "nameFi",
                  "nameSv",
                  "nameEn",
                  "worktimeFraction"
                ]
              },
              "startMinutes": {
                "type": "integer",
                "minimum": 0,
                "maximum": 1440
              },
              "endMinutes": {
                "type": "integer",
                "minimum": 1,
                "maximum": 1440
              }
            },
            "required": [
              "periodId",
              "standbyType",
              "startMinutes",
              "endMinutes"
            ]
          }
        },
        "governingShiftType": {
          "type": "object",
          "properties": {
            "id": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            },
            "nameFi": {
              "type": "string"
            },
            "nameSv": {
              "type": "string"
            },
            "nameEn": {
              "type": "string"
            },
            "shortCode": {
              "type": "string"
            },
            "color": {
              "type": "string"
            },
            "source": {
              "type": "string",
              "enum": [
                "plan",
                "walk-up",
                "rule",
                "model-default",
                "override"
              ]
            }
          },
          "required": [
            "nameFi",
            "nameSv",
            "nameEn",
            "shortCode",
            "color"
          ]
        },
        "plannedShift": {
          "type": "object",
          "properties": {
            "startMinutes": {
              "type": "integer",
              "minimum": -9007199254740991,
              "maximum": 9007199254740991,
              "x-nullable": true
            },
            "endMinutes": {
              "type": "integer",
              "minimum": -9007199254740991,
              "maximum": 9007199254740991,
              "x-nullable": true
            },
            "breakMinutes": {
              "type": "integer",
              "minimum": -9007199254740991,
              "maximum": 9007199254740991
            },
            "targetMinutes": {
              "type": "integer",
              "minimum": -9007199254740991,
              "maximum": 9007199254740991
            },
            "source": {
              "type": "string",
              "enum": [
                "person-shift",
                "group-shift"
              ]
            },
            "shiftType": {
              "type": "object",
              "properties": {
                "nameFi": {
                  "type": "string"
                },
                "nameSv": {
                  "type": "string"
                },
                "nameEn": {
                  "type": "string"
                },
                "shortCode": {
                  "type": "string"
                },
                "color": {
                  "type": "string"
                }
              },
              "required": [
                "nameFi",
                "nameSv",
                "nameEn",
                "shortCode",
                "color"
              ],
              "x-nullable": true
            }
          },
          "required": [
            "startMinutes",
            "endMinutes",
            "breakMinutes",
            "targetMinutes",
            "source",
            "shiftType"
          ]
        },
        "workDayId": {
          "type": "string",
          "x-nullable": true
        },
        "effectiveSettings": {
          "type": "object",
          "properties": {
            "breakDeductionMode": {
              "type": "string",
              "enum": [
                "none",
                "minimum",
                "fixed"
              ]
            },
            "breakThresholdMinutes": {
              "type": "number"
            },
            "breakThresholdBasis": {
              "type": "string",
              "enum": [
                "work",
                "span"
              ]
            },
            "minBreakMinutes": {
              "type": "number"
            },
            "paidCoffeeTotalMinutes": {
              "type": "number"
            },
            "paidCoffeeMaxCount": {
              "type": "number"
            },
            "flexWindowStartMinutes": {
              "type": "number",
              "x-nullable": true
            },
            "flexWindowEndMinutes": {
              "type": "number",
              "x-nullable": true
            },
            "dayFlexCapMinutes": {
              "type": "number",
              "x-nullable": true
            },
            "dayFlexFloorMinutes": {
              "type": "number",
              "x-nullable": true
            },
            "dailyRegularBasis": {
              "type": "string",
              "enum": [
                "target",
                "fixed"
              ]
            },
            "dailyRegularFixedMinutes": {
              "type": "number",
              "x-nullable": true
            },
            "dailyOt50Minutes": {
              "type": "number",
              "x-nullable": true
            },
            "flexRoundingMinutes": {
              "type": "number"
            },
            "openPunchAutoClose": {
              "type": "string",
              "enum": [
                "off",
                "boundary",
                "planned_end"
              ]
            },
            "punchRoundingMinutes": {
              "type": "number"
            },
            "punchGraceStartMinutes": {
              "type": "number"
            },
            "punchGraceEndMinutes": {
              "type": "number"
            },
            "trace": {
              "type": "object",
              "additionalProperties": {
                "type": "string"
              }
            }
          },
          "required": [
            "breakDeductionMode",
            "breakThresholdMinutes",
            "breakThresholdBasis",
            "minBreakMinutes",
            "paidCoffeeTotalMinutes",
            "paidCoffeeMaxCount",
            "flexWindowStartMinutes",
            "flexWindowEndMinutes",
            "dayFlexCapMinutes",
            "dayFlexFloorMinutes",
            "dailyRegularBasis",
            "dailyRegularFixedMinutes",
            "dailyOt50Minutes",
            "flexRoundingMinutes",
            "openPunchAutoClose",
            "punchRoundingMinutes",
            "punchGraceStartMinutes",
            "punchGraceEndMinutes",
            "trace"
          ]
        },
        "statutoryBasis": {
          "type": "boolean"
        },
        "worktimeRegime": {
          "type": "string",
          "enum": [
            "standard",
            "flexwork",
            "period"
          ]
        },
        "emergencyMinutes": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991
        },
        "openCorrectionRequest": {
          "type": "object",
          "properties": {
            "reason": {
              "type": "string"
            },
            "by": {
              "type": "string"
            },
            "requestedAt": {
              "type": "string"
            }
          },
          "required": [
            "reason",
            "by",
            "requestedAt"
          ],
          "default": null,
          "x-nullable": true
        },
        "shiftTypeOverride": {
          "type": "object",
          "properties": {
            "shiftTypeId": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          "required": [
            "shiftTypeId"
          ],
          "default": null,
          "x-nullable": true
        },
        "shiftTypeOverrideInvalid": {
          "type": "boolean"
        },
        "shiftTypeOverrideMode": {
          "type": "string",
          "enum": [
            "off",
            "manager",
            "employee"
          ]
        },
        "resolutionWindows": {
          "default": [],
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "shiftTypeId": {
                "type": "string",
                "format": "uuid",
                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
              },
              "nameFi": {
                "type": "string"
              },
              "nameSv": {
                "type": "string"
              },
              "nameEn": {
                "type": "string"
              },
              "shortCode": {
                "type": "string"
              },
              "color": {
                "type": "string"
              },
              "startMinutes": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "endMinutes": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "priority": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              }
            },
            "required": [
              "shiftTypeId",
              "nameFi",
              "nameSv",
              "nameEn",
              "shortCode",
              "color",
              "startMinutes",
              "endMinutes",
              "priority"
            ]
          }
        }
      },
      "required": [
        "workDate",
        "status",
        "startMinutes",
        "endMinutes",
        "breakMinutes",
        "workMinutes",
        "creditedMinutes",
        "targetMinutes",
        "balanceDeltaMinutes",
        "runningBalanceMinutes",
        "overtimeMinutes",
        "dayType",
        "sources",
        "deviations",
        "entries",
        "expectedSource",
        "workDayId"
      ]
    },
    "SetDayTypeDto": {
      "type": "object",
      "properties": {
        "dayTypeId": {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
          "x-nullable": true
        }
      },
      "required": [
        "dayTypeId"
      ]
    },
    "WorkDayViewDto": {
      "type": "object",
      "properties": {
        "workDate": {
          "type": "string",
          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
        },
        "status": {
          "type": "string",
          "enum": [
            "proposed",
            "draft",
            "confirmed",
            "approved",
            "exported"
          ]
        },
        "startMinutes": {
          "type": "integer",
          "minimum": 0,
          "maximum": 1440,
          "x-nullable": true
        },
        "endMinutes": {
          "type": "integer",
          "minimum": 1,
          "maximum": 2880,
          "x-nullable": true
        },
        "breakMinutes": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991
        },
        "breaks": {
          "default": [],
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string",
                "format": "uuid",
                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                "x-nullable": true
              },
              "startMinutes": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "endMinutes": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "breakTypeId": {
                "type": "string",
                "format": "uuid",
                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                "x-nullable": true
              },
              "paidMinutes": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              }
            },
            "required": [
              "id",
              "startMinutes",
              "endMinutes",
              "breakTypeId",
              "paidMinutes"
            ]
          }
        },
        "paidBreakMinutes": {
          "default": 0,
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991
        },
        "workMinutes": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991
        },
        "creditedMinutes": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991
        },
        "targetMinutes": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991
        },
        "appliedCreditMinutes": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991
        },
        "uncountedMinutes": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991
        },
        "rawDeltaMinutes": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991
        },
        "balanceDeltaMinutes": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991
        },
        "attentionThresholdMinutes": {
          "default": 15,
          "type": "integer",
          "minimum": 0,
          "maximum": 480
        },
        "runningBalanceMinutes": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991
        },
        "overtimeMinutes": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991
        },
        "dayType": {
          "type": "object",
          "properties": {
            "id": {
              "type": "string"
            },
            "code": {
              "type": "string",
              "pattern": "^[a-z][a-z0-9_]{1,49}$"
            },
            "nameFi": {
              "type": "string",
              "minLength": 1,
              "maxLength": 100
            },
            "nameSv": {
              "type": "string",
              "minLength": 1,
              "maxLength": 100
            },
            "nameEn": {
              "type": "string",
              "minLength": 1,
              "maxLength": 100
            }
          },
          "required": [
            "id",
            "code",
            "nameFi",
            "nameSv",
            "nameEn"
          ],
          "x-nullable": true
        },
        "absencePeriod": {
          "type": "object",
          "properties": {
            "id": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            },
            "status": {
              "type": "string",
              "enum": [
                "draft",
                "submitted",
                "approved",
                "rejected",
                "cancelled",
                "withdrawn"
              ]
            },
            "workflowMode": {
              "type": "string",
              "enum": [
                "request",
                "notification",
                "employer_assignment"
              ]
            },
            "nameFi": {
              "type": "string"
            },
            "nameSv": {
              "type": "string"
            },
            "nameEn": {
              "type": "string"
            }
          },
          "required": [
            "id",
            "status",
            "workflowMode",
            "nameFi",
            "nameSv",
            "nameEn"
          ],
          "x-nullable": true
        },
        "sources": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "type": {
                "type": "string",
                "enum": [
                  "worktime-model",
                  "calendar-event",
                  "planned-shift",
                  "punch",
                  "learned-baseline"
                ]
              },
              "versionId": {
                "type": "string"
              },
              "eventId": {
                "type": "string"
              },
              "shiftId": {
                "type": "string"
              },
              "punchSessionId": {
                "type": "string"
              },
              "weekday": {
                "type": "integer",
                "minimum": 1,
                "maximum": 7
              }
            },
            "required": [
              "type"
            ]
          }
        },
        "deviations": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "type": {
                "type": "string",
                "enum": [
                  "overlong-day",
                  "short-day",
                  "missing-break",
                  "missing-second-break",
                  "fragmented-break",
                  "break-at-day-edge",
                  "flex-limit-exceeded",
                  "outside-flex-window",
                  "outside-allowed-window",
                  "work-on-day-off",
                  "entry-over-max-duration",
                  "insufficient-daily-rest",
                  "insufficient-weekly-rest"
                ]
              },
              "deltaMinutes": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "severity": {
                "type": "string",
                "enum": [
                  "advisory",
                  "info"
                ]
              }
            },
            "required": [
              "type",
              "deltaMinutes"
            ]
          }
        },
        "overtimeDisposition": {
          "default": "flex",
          "type": "string",
          "enum": [
            "flex",
            "payout",
            "ignore",
            "bank"
          ]
        },
        "bankAccountTypeId": {
          "type": "string",
          "default": null,
          "x-nullable": true
        },
        "entries": {
          "default": [],
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "entryTypeId": {
                "type": "string"
              },
              "entryTypeCode": {
                "type": "string",
                "pattern": "^[a-z][a-z0-9_]{1,49}$"
              },
              "startMinutes": {
                "type": "integer",
                "minimum": 0,
                "maximum": 2879,
                "x-nullable": true
              },
              "endMinutes": {
                "type": "integer",
                "minimum": 1,
                "maximum": 2880,
                "x-nullable": true
              },
              "durationMinutes": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991,
                "default": null,
                "x-nullable": true
              },
              "note": {
                "type": "string",
                "x-nullable": true
              },
              "billable": {
                "type": "boolean"
              },
              "billingBaseMinutes": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991,
                "default": null,
                "x-nullable": true
              },
              "allocations": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "dimensionId": {
                      "type": "string"
                    },
                    "valueId": {
                      "type": "string"
                    },
                    "valueCode": {
                      "type": "string"
                    },
                    "valueName": {
                      "type": "string"
                    },
                    "weightBp": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991
                    }
                  },
                  "required": [
                    "dimensionId",
                    "valueId",
                    "valueCode",
                    "valueName",
                    "weightBp"
                  ]
                }
              }
            },
            "required": [
              "id",
              "entryTypeId",
              "entryTypeCode",
              "startMinutes",
              "endMinutes",
              "note",
              "billable",
              "allocations"
            ]
          }
        },
        "proposedEntries": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "startMinutes": {
                "type": "integer",
                "minimum": 0,
                "maximum": 1440
              },
              "endMinutes": {
                "type": "integer",
                "minimum": 1,
                "maximum": 2880
              },
              "entryTypeId": {
                "type": "string"
              },
              "billable": {
                "type": "boolean"
              },
              "allocations": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "dimensionId": {
                      "type": "string"
                    },
                    "valueId": {
                      "type": "string"
                    },
                    "valueCode": {
                      "type": "string"
                    },
                    "valueName": {
                      "type": "string"
                    },
                    "weightBp": {
                      "default": 10000,
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991
                    },
                    "source": {
                      "type": "string",
                      "enum": [
                        "calendar",
                        "geofence",
                        "task",
                        "baseline",
                        "default"
                      ]
                    },
                    "confidence": {
                      "type": "string",
                      "enum": [
                        "high",
                        "medium",
                        "low"
                      ]
                    }
                  },
                  "required": [
                    "dimensionId",
                    "valueId",
                    "valueCode",
                    "valueName",
                    "source",
                    "confidence"
                  ]
                }
              },
              "confidence": {
                "type": "string",
                "enum": [
                  "high",
                  "medium",
                  "low"
                ]
              }
            },
            "required": [
              "startMinutes",
              "endMinutes",
              "entryTypeId",
              "billable",
              "allocations",
              "confidence"
            ]
          }
        },
        "expectedSource": {
          "type": "string",
          "x-nullable": true
        },
        "expectedWindow": {
          "type": "object",
          "properties": {
            "startMinutes": {
              "type": "integer",
              "minimum": 0,
              "maximum": 1440
            },
            "endMinutes": {
              "type": "integer",
              "minimum": 0,
              "maximum": 1440
            },
            "breakMinutes": {
              "type": "integer",
              "minimum": 0,
              "maximum": 9007199254740991
            }
          },
          "required": [
            "startMinutes",
            "endMinutes",
            "breakMinutes"
          ],
          "x-nullable": true
        },
        "proposalDismissed": {
          "type": "boolean"
        },
        "updatedAt": {
          "type": "string",
          "default": null,
          "x-nullable": true
        },
        "returnReason": {
          "type": "string",
          "x-nullable": true
        },
        "confirmationOptional": {
          "type": "boolean"
        },
        "confirmedOnBehalf": {
          "type": "boolean"
        },
        "autoConfirmed": {
          "type": "boolean"
        },
        "confidence": {
          "type": "object",
          "properties": {
            "level": {
              "type": "string",
              "enum": [
                "high",
                "medium",
                "low"
              ]
            },
            "reasons": {
              "type": "array",
              "items": {
                "type": "string"
              }
            }
          },
          "required": [
            "level",
            "reasons"
          ]
        },
        "supplements": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "supplementTypeId": {
                "type": "string"
              },
              "supplementTypeCode": {
                "type": "string",
                "pattern": "^[a-z][a-z0-9_]{1,49}$"
              },
              "nameFi": {
                "type": "string",
                "minLength": 1,
                "maxLength": 100
              },
              "nameSv": {
                "type": "string",
                "minLength": 1,
                "maxLength": 100
              },
              "nameEn": {
                "type": "string",
                "minLength": 1,
                "maxLength": 100
              },
              "valueKind": {
                "type": "string",
                "enum": [
                  "flag",
                  "count",
                  "hours",
                  "amount"
                ]
              },
              "unit": {
                "type": "string",
                "enum": [
                  "hours",
                  "pieces",
                  "days",
                  "decimal"
                ]
              },
              "exportMode": {
                "type": "string",
                "enum": [
                  "passthrough",
                  "tesOnly"
                ]
              },
              "quantity": {
                "type": "number"
              },
              "startMinutes": {
                "type": "integer",
                "minimum": 0,
                "maximum": 1440,
                "x-nullable": true
              },
              "endMinutes": {
                "type": "integer",
                "minimum": 0,
                "maximum": 1440,
                "x-nullable": true
              },
              "comment": {
                "type": "string",
                "x-nullable": true
              }
            },
            "required": [
              "id",
              "supplementTypeId",
              "supplementTypeCode",
              "nameFi",
              "nameSv",
              "nameEn",
              "valueKind",
              "unit",
              "exportMode",
              "quantity",
              "startMinutes",
              "endMinutes",
              "comment"
            ]
          }
        },
        "standby": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "periodId": {
                "type": "string"
              },
              "standbyType": {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "string"
                  },
                  "code": {
                    "type": "string",
                    "pattern": "^[a-z][a-z0-9_]{1,49}$"
                  },
                  "nameFi": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 100
                  },
                  "nameSv": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 100
                  },
                  "nameEn": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 100
                  },
                  "worktimeFraction": {
                    "type": "number",
                    "minimum": 0,
                    "maximum": 1
                  }
                },
                "required": [
                  "id",
                  "code",
                  "nameFi",
                  "nameSv",
                  "nameEn",
                  "worktimeFraction"
                ]
              },
              "startMinutes": {
                "type": "integer",
                "minimum": 0,
                "maximum": 1440
              },
              "endMinutes": {
                "type": "integer",
                "minimum": 1,
                "maximum": 1440
              }
            },
            "required": [
              "periodId",
              "standbyType",
              "startMinutes",
              "endMinutes"
            ]
          }
        },
        "governingShiftType": {
          "type": "object",
          "properties": {
            "id": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            },
            "nameFi": {
              "type": "string"
            },
            "nameSv": {
              "type": "string"
            },
            "nameEn": {
              "type": "string"
            },
            "shortCode": {
              "type": "string"
            },
            "color": {
              "type": "string"
            },
            "source": {
              "type": "string",
              "enum": [
                "plan",
                "walk-up",
                "rule",
                "model-default",
                "override"
              ]
            }
          },
          "required": [
            "nameFi",
            "nameSv",
            "nameEn",
            "shortCode",
            "color"
          ]
        },
        "plannedShift": {
          "type": "object",
          "properties": {
            "startMinutes": {
              "type": "integer",
              "minimum": -9007199254740991,
              "maximum": 9007199254740991,
              "x-nullable": true
            },
            "endMinutes": {
              "type": "integer",
              "minimum": -9007199254740991,
              "maximum": 9007199254740991,
              "x-nullable": true
            },
            "breakMinutes": {
              "type": "integer",
              "minimum": -9007199254740991,
              "maximum": 9007199254740991
            },
            "targetMinutes": {
              "type": "integer",
              "minimum": -9007199254740991,
              "maximum": 9007199254740991
            },
            "source": {
              "type": "string",
              "enum": [
                "person-shift",
                "group-shift"
              ]
            },
            "shiftType": {
              "type": "object",
              "properties": {
                "nameFi": {
                  "type": "string"
                },
                "nameSv": {
                  "type": "string"
                },
                "nameEn": {
                  "type": "string"
                },
                "shortCode": {
                  "type": "string"
                },
                "color": {
                  "type": "string"
                }
              },
              "required": [
                "nameFi",
                "nameSv",
                "nameEn",
                "shortCode",
                "color"
              ],
              "x-nullable": true
            }
          },
          "required": [
            "startMinutes",
            "endMinutes",
            "breakMinutes",
            "targetMinutes",
            "source",
            "shiftType"
          ]
        }
      },
      "required": [
        "workDate",
        "status",
        "startMinutes",
        "endMinutes",
        "breakMinutes",
        "workMinutes",
        "creditedMinutes",
        "targetMinutes",
        "balanceDeltaMinutes",
        "runningBalanceMinutes",
        "overtimeMinutes",
        "dayType",
        "sources",
        "deviations",
        "expectedSource"
      ]
    },
    "SetWorkEntriesDto": {
      "type": "object",
      "properties": {
        "entries": {
          "minItems": 1,
          "maxItems": 20,
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "entryTypeId": {
                "type": "string",
                "format": "uuid",
                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
              },
              "startMinutes": {
                "type": "integer",
                "minimum": 0,
                "maximum": 2879
              },
              "endMinutes": {
                "type": "integer",
                "minimum": 1,
                "maximum": 2880
              },
              "durationMinutes": {
                "type": "integer",
                "minimum": 1,
                "maximum": 1440
              },
              "note": {
                "type": "string",
                "maxLength": 200
              },
              "billable": {
                "default": false,
                "type": "boolean"
              },
              "billingBaseMinutes": {
                "type": "integer",
                "minimum": 0,
                "maximum": 1440,
                "x-nullable": true
              },
              "allocations": {
                "default": [],
                "maxItems": 10,
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "dimensionId": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    },
                    "valueId": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    },
                    "weightBp": {
                      "default": 10000,
                      "type": "integer",
                      "minimum": 1,
                      "maximum": 10000
                    }
                  },
                  "required": [
                    "dimensionId",
                    "valueId"
                  ]
                }
              },
              "taskId": {
                "type": "string",
                "format": "uuid",
                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                "x-nullable": true
              }
            },
            "required": [
              "entryTypeId"
            ]
          }
        },
        "breaks": {
          "maxItems": 20,
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "startMinutes": {
                "type": "integer",
                "minimum": 0,
                "maximum": 2880
              },
              "endMinutes": {
                "type": "integer",
                "minimum": 1,
                "maximum": 2880
              },
              "breakTypeId": {
                "type": "string",
                "format": "uuid",
                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                "x-nullable": true
              }
            },
            "required": [
              "startMinutes",
              "endMinutes"
            ]
          }
        },
        "expectedUpdatedAt": {
          "type": "string"
        }
      },
      "required": [
        "entries"
      ]
    },
    "BalanceResponseDto": {
      "type": "object",
      "properties": {
        "totalMinutes": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991
        },
        "runningMinutes": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991
        },
        "todayMinutes": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991
        },
        "isProvisional": {
          "type": "boolean"
        },
        "asOf": {
          "type": "string",
          "format": "date-time",
          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
        },
        "unrecordedDayCount": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991
        },
        "oldestUnrecordedDate": {
          "type": "string",
          "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
          "x-nullable": true
        },
        "flexStatus": {
          "type": "string",
          "enum": [
            "within-limits",
            "over-max",
            "under-min"
          ]
        },
        "flexMinMinutes": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991
        },
        "flexMaxMinutes": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991
        },
        "trend": {
          "type": "object",
          "properties": {
            "direction": {
              "type": "string",
              "enum": [
                "toward-max",
                "toward-min",
                "flat"
              ]
            },
            "ratePerDayMinutes": {
              "type": "integer",
              "minimum": -9007199254740991,
              "maximum": 9007199254740991
            },
            "daysToCap": {
              "type": "integer",
              "minimum": -9007199254740991,
              "maximum": 9007199254740991,
              "x-nullable": true
            }
          },
          "required": [
            "direction",
            "ratePerDayMinutes",
            "daysToCap"
          ]
        }
      },
      "required": [
        "totalMinutes",
        "runningMinutes",
        "todayMinutes",
        "isProvisional",
        "asOf",
        "unrecordedDayCount",
        "oldestUnrecordedDate",
        "flexStatus",
        "flexMinMinutes",
        "flexMaxMinutes"
      ]
    },
    "StaffGroupListResponseDto": {
      "type": "object",
      "properties": {
        "groups": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "code": {
                "type": "string"
              },
              "nameFi": {
                "type": "string"
              },
              "nameSv": {
                "type": "string"
              },
              "nameEn": {
                "type": "string"
              },
              "sortOrder": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "active": {
                "type": "boolean"
              },
              "criteria": {
                "type": "object",
                "properties": {
                  "payType": {
                    "type": "string",
                    "enum": [
                      "monthly",
                      "hourly"
                    ]
                  },
                  "employmentType": {
                    "type": "string",
                    "enum": [
                      "permanent",
                      "fixed_term"
                    ]
                  },
                  "worktimeModelIds": {
                    "minItems": 1,
                    "maxItems": 200,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    }
                  },
                  "planningUnitIds": {
                    "minItems": 1,
                    "maxItems": 200,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    }
                  },
                  "employerIds": {
                    "minItems": 1,
                    "maxItems": 200,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    }
                  },
                  "roles": {
                    "minItems": 1,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "enum": [
                        "employee",
                        "manager",
                        "admin",
                        "payroll",
                        "hr"
                      ]
                    }
                  },
                  "includeMembershipIds": {
                    "minItems": 1,
                    "maxItems": 2000,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    }
                  },
                  "excludeMembershipIds": {
                    "minItems": 1,
                    "maxItems": 2000,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    }
                  }
                },
                "additionalProperties": false
              },
              "memberCount": {
                "type": "integer",
                "minimum": 0,
                "maximum": 9007199254740991
              },
              "createdAt": {
                "type": "string"
              },
              "updatedAt": {
                "type": "string"
              }
            },
            "required": [
              "id",
              "code",
              "nameFi",
              "nameSv",
              "nameEn",
              "sortOrder",
              "active",
              "criteria",
              "memberCount",
              "createdAt",
              "updatedAt"
            ]
          }
        }
      },
      "required": [
        "groups"
      ]
    },
    "ConfirmWorkDayDto": {
      "type": "object",
      "properties": {
        "startMinutes": {
          "type": "integer",
          "minimum": 0,
          "maximum": 1440
        },
        "endMinutes": {
          "type": "integer",
          "minimum": 1,
          "maximum": 2880
        },
        "breakMinutes": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991
        },
        "overtimeDisposition": {
          "type": "string",
          "enum": [
            "flex",
            "payout",
            "ignore",
            "bank"
          ]
        },
        "bankAccountTypeId": {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
          "x-nullable": true
        }
      }
    },
    "ConfirmWorkDayResponseDto": {
      "type": "object",
      "properties": {
        "workDate": {
          "type": "string",
          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
        },
        "status": {
          "type": "string",
          "enum": [
            "proposed",
            "draft",
            "confirmed",
            "approved",
            "exported"
          ]
        }
      },
      "required": [
        "workDate",
        "status"
      ]
    },
    "WorkDayActionResponseDto": {
      "type": "object",
      "properties": {
        "status": {
          "type": "string",
          "enum": [
            "proposed",
            "draft",
            "confirmed",
            "approved",
            "exported"
          ]
        },
        "warnings": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "code": {
                "type": "string"
              },
              "params": {
                "default": {},
                "type": "object",
                "additionalProperties": {
                  "type": "string"
                }
              }
            },
            "required": [
              "code"
            ]
          }
        }
      },
      "required": [
        "status"
      ]
    },
    "RangeActionDto": {
      "type": "object",
      "properties": {
        "from": {
          "type": "string",
          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
        },
        "to": {
          "type": "string",
          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
        }
      },
      "required": [
        "from",
        "to"
      ]
    },
    "RangeActionResponseDto": {
      "type": "object",
      "properties": {
        "actedCount": {
          "type": "integer",
          "minimum": 0,
          "maximum": 9007199254740991
        },
        "skippedCount": {
          "type": "integer",
          "minimum": 0,
          "maximum": 9007199254740991
        },
        "skipped": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "workDate": {
                "type": "string",
                "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
              },
              "code": {
                "type": "string"
              }
            },
            "required": [
              "workDate",
              "code"
            ]
          }
        }
      },
      "required": [
        "actedCount",
        "skippedCount",
        "skipped"
      ]
    },
    "ApproveWorkDayDto": {
      "type": "object",
      "properties": {
        "overtimeDisposition": {
          "type": "string",
          "enum": [
            "flex",
            "payout",
            "ignore",
            "bank"
          ]
        },
        "bankAccountTypeId": {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
          "x-nullable": true
        }
      },
      "default": {}
    },
    "ApproveWorkDaysBatchDto": {
      "type": "object",
      "properties": {
        "items": {
          "minItems": 1,
          "maxItems": 500,
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "workDayId": {
                "type": "string",
                "format": "uuid",
                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
              },
              "overtimeDisposition": {
                "type": "string",
                "enum": [
                  "flex",
                  "payout",
                  "ignore",
                  "bank"
                ]
              },
              "bankAccountTypeId": {
                "type": "string",
                "format": "uuid",
                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                "x-nullable": true
              }
            },
            "required": [
              "workDayId"
            ]
          }
        }
      },
      "required": [
        "items"
      ]
    },
    "ApproveWorkDaysBatchResponseDto": {
      "type": "object",
      "properties": {
        "actedCount": {
          "type": "integer",
          "minimum": 0,
          "maximum": 9007199254740991
        },
        "skippedCount": {
          "type": "integer",
          "minimum": 0,
          "maximum": 9007199254740991
        },
        "skipped": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "workDayId": {
                "type": "string",
                "format": "uuid",
                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
              },
              "code": {
                "type": "string"
              }
            },
            "required": [
              "workDayId",
              "code"
            ]
          }
        }
      },
      "required": [
        "actedCount",
        "skippedCount",
        "skipped"
      ]
    },
    "ReturnWorkDaysBatchDto": {
      "type": "object",
      "properties": {
        "workDayIds": {
          "minItems": 1,
          "maxItems": 500,
          "type": "array",
          "items": {
            "type": "string",
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
          }
        },
        "reason": {
          "type": "string",
          "minLength": 3,
          "maxLength": 500
        }
      },
      "required": [
        "workDayIds",
        "reason"
      ]
    },
    "ReturnWorkDaysBatchResponseDto": {
      "type": "object",
      "properties": {
        "actedCount": {
          "type": "integer",
          "minimum": 0,
          "maximum": 9007199254740991
        },
        "skippedCount": {
          "type": "integer",
          "minimum": 0,
          "maximum": 9007199254740991
        },
        "skipped": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "workDayId": {
                "type": "string",
                "format": "uuid",
                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
              },
              "code": {
                "type": "string"
              }
            },
            "required": [
              "workDayId",
              "code"
            ]
          }
        }
      },
      "required": [
        "actedCount",
        "skippedCount",
        "skipped"
      ]
    },
    "ReturnWorkDayDto": {
      "type": "object",
      "properties": {
        "reason": {
          "type": "string",
          "minLength": 3,
          "maxLength": 500
        }
      },
      "required": [
        "reason"
      ]
    },
    "WebhookEndpointListResponseDto": {
      "type": "object",
      "properties": {
        "endpoints": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "url": {
                "type": "string"
              },
              "format": {
                "type": "string",
                "enum": [
                  "json",
                  "slack",
                  "teams"
                ]
              },
              "events": {
                "type": "array",
                "items": {
                  "type": "string",
                  "enum": [
                    "quote.decided",
                    "batch.created",
                    "status_update.posted",
                    "deal.won",
                    "lead.created",
                    "workday.approved",
                    "export_batch.created",
                    "export_batch.delivered",
                    "export_batch.delivery_failed",
                    "absence.submitted",
                    "absence.decided",
                    "shift.published",
                    "invoice.issued",
                    "invoice.credited",
                    "invoice.dispatched",
                    "invoice.delivered",
                    "invoice.delivery_failed",
                    "payment.recorded",
                    "payment.allocated",
                    "payment.imported",
                    "invoice.overdue",
                    "invoice.drafts_ready",
                    "recurring_plan.run_completed",
                    "batch.delivered",
                    "workday.confirmed",
                    "workday.returned",
                    "workday.corrected",
                    "workday.unapproved",
                    "absence.cancelled",
                    "absence.certificate_provided",
                    "shift.changed",
                    "open_shift.claimed",
                    "open_shift.claim_decided",
                    "shift_swap.proposed",
                    "shift_swap.decided",
                    "export_batch.cancelled",
                    "payroll_period.locked",
                    "payroll_period.lock_lifted",
                    "member.created",
                    "member.invited",
                    "member.deactivated",
                    "employment.terminated",
                    "task.created",
                    "task.status_changed",
                    "task.approval_responded",
                    "quote.sent",
                    "quote.accepted",
                    "deal.lost",
                    "deal.stage_changed",
                    "lead.converted",
                    "intake.received",
                    "change_order.approved",
                    "project.created",
                    "project.closed",
                    "contact.anonymized",
                    "lead.anonymized",
                    "invoice.paid",
                    "customer.created",
                    "customer.updated",
                    "project.updated",
                    "member.updated",
                    "shift.unpublished"
                  ]
                }
              },
              "locale": {
                "type": "string",
                "enum": [
                  "fi",
                  "sv",
                  "en"
                ]
              },
              "hasSecret": {
                "type": "boolean"
              },
              "active": {
                "type": "boolean"
              },
              "createdAt": {
                "type": "string",
                "format": "date-time",
                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
              }
            },
            "required": [
              "id",
              "url",
              "format",
              "events",
              "locale",
              "hasSecret",
              "active",
              "createdAt"
            ]
          }
        }
      },
      "required": [
        "endpoints"
      ]
    },
    "CreateWebhookEndpointDto": {
      "type": "object",
      "properties": {
        "url": {
          "type": "string",
          "maxLength": 500,
          "format": "uri"
        },
        "format": {
          "default": "json",
          "type": "string",
          "enum": [
            "json",
            "slack",
            "teams"
          ]
        },
        "events": {
          "minItems": 1,
          "type": "array",
          "items": {
            "type": "string",
            "enum": [
              "quote.decided",
              "batch.created",
              "status_update.posted",
              "deal.won",
              "lead.created",
              "workday.approved",
              "export_batch.created",
              "export_batch.delivered",
              "export_batch.delivery_failed",
              "absence.submitted",
              "absence.decided",
              "shift.published",
              "invoice.issued",
              "invoice.credited",
              "invoice.dispatched",
              "invoice.delivered",
              "invoice.delivery_failed",
              "payment.recorded",
              "payment.allocated",
              "payment.imported",
              "invoice.overdue",
              "invoice.drafts_ready",
              "recurring_plan.run_completed",
              "batch.delivered",
              "workday.confirmed",
              "workday.returned",
              "workday.corrected",
              "workday.unapproved",
              "absence.cancelled",
              "absence.certificate_provided",
              "shift.changed",
              "open_shift.claimed",
              "open_shift.claim_decided",
              "shift_swap.proposed",
              "shift_swap.decided",
              "export_batch.cancelled",
              "payroll_period.locked",
              "payroll_period.lock_lifted",
              "member.created",
              "member.invited",
              "member.deactivated",
              "employment.terminated",
              "task.created",
              "task.status_changed",
              "task.approval_responded",
              "quote.sent",
              "quote.accepted",
              "deal.lost",
              "deal.stage_changed",
              "lead.converted",
              "intake.received",
              "change_order.approved",
              "project.created",
              "project.closed",
              "contact.anonymized",
              "lead.anonymized",
              "invoice.paid",
              "customer.created",
              "customer.updated",
              "project.updated",
              "member.updated",
              "shift.unpublished"
            ]
          }
        },
        "locale": {
          "default": "fi",
          "type": "string",
          "enum": [
            "fi",
            "sv",
            "en"
          ]
        }
      },
      "required": [
        "url",
        "events"
      ]
    },
    "CreateWebhookEndpointResponseDto": {
      "type": "object",
      "properties": {
        "id": {
          "type": "string"
        },
        "secret": {
          "type": "string",
          "x-nullable": true
        }
      },
      "required": [
        "id",
        "secret"
      ]
    },
    "UpdateWebhookEndpointDto": {
      "type": "object",
      "properties": {
        "url": {
          "type": "string",
          "maxLength": 500,
          "format": "uri"
        },
        "events": {
          "minItems": 1,
          "type": "array",
          "items": {
            "type": "string",
            "enum": [
              "quote.decided",
              "batch.created",
              "status_update.posted",
              "deal.won",
              "lead.created",
              "workday.approved",
              "export_batch.created",
              "export_batch.delivered",
              "export_batch.delivery_failed",
              "absence.submitted",
              "absence.decided",
              "shift.published",
              "invoice.issued",
              "invoice.credited",
              "invoice.dispatched",
              "invoice.delivered",
              "invoice.delivery_failed",
              "payment.recorded",
              "payment.allocated",
              "payment.imported",
              "invoice.overdue",
              "invoice.drafts_ready",
              "recurring_plan.run_completed",
              "batch.delivered",
              "workday.confirmed",
              "workday.returned",
              "workday.corrected",
              "workday.unapproved",
              "absence.cancelled",
              "absence.certificate_provided",
              "shift.changed",
              "open_shift.claimed",
              "open_shift.claim_decided",
              "shift_swap.proposed",
              "shift_swap.decided",
              "export_batch.cancelled",
              "payroll_period.locked",
              "payroll_period.lock_lifted",
              "member.created",
              "member.invited",
              "member.deactivated",
              "employment.terminated",
              "task.created",
              "task.status_changed",
              "task.approval_responded",
              "quote.sent",
              "quote.accepted",
              "deal.lost",
              "deal.stage_changed",
              "lead.converted",
              "intake.received",
              "change_order.approved",
              "project.created",
              "project.closed",
              "contact.anonymized",
              "lead.anonymized",
              "invoice.paid",
              "customer.created",
              "customer.updated",
              "project.updated",
              "member.updated",
              "shift.unpublished"
            ]
          }
        },
        "locale": {
          "type": "string",
          "enum": [
            "fi",
            "sv",
            "en"
          ]
        },
        "active": {
          "type": "boolean"
        }
      }
    },
    "WebhookOkResponseDto": {
      "type": "object",
      "properties": {
        "ok": {
          "type": "boolean"
        }
      },
      "required": [
        "ok"
      ]
    },
    "RotateWebhookSecretResponseDto": {
      "type": "object",
      "properties": {
        "secret": {
          "type": "string"
        }
      },
      "required": [
        "secret"
      ]
    },
    "WebhookDeliveryPageResponseDto": {
      "type": "object",
      "properties": {
        "items": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "event": {
                "type": "string"
              },
              "integrationEventId": {
                "type": "string",
                "x-nullable": true
              },
              "status": {
                "type": "string",
                "enum": [
                  "pending",
                  "delivered",
                  "failed",
                  "dead_letter"
                ]
              },
              "attempts": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "lastError": {
                "type": "string",
                "x-nullable": true
              },
              "httpStatus": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991,
                "x-nullable": true
              },
              "nextAttemptAt": {
                "type": "string",
                "format": "date-time",
                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$",
                "x-nullable": true
              },
              "createdAt": {
                "type": "string",
                "format": "date-time",
                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
              },
              "deliveredAt": {
                "type": "string",
                "format": "date-time",
                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$",
                "x-nullable": true
              }
            },
            "required": [
              "id",
              "event",
              "integrationEventId",
              "status",
              "attempts",
              "lastError",
              "httpStatus",
              "nextAttemptAt",
              "createdAt",
              "deliveredAt"
            ]
          }
        },
        "pageInfo": {
          "type": "object",
          "properties": {
            "nextCursor": {
              "type": "string",
              "x-nullable": true
            },
            "hasMore": {
              "type": "boolean"
            }
          },
          "required": [
            "nextCursor",
            "hasMore"
          ]
        }
      },
      "required": [
        "items",
        "pageInfo"
      ]
    },
    "IntegrationEventPageResponseDto": {
      "type": "object",
      "properties": {
        "items": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "event": {
                "type": "string",
                "enum": [
                  "quote.decided",
                  "batch.created",
                  "status_update.posted",
                  "deal.won",
                  "lead.created",
                  "workday.approved",
                  "export_batch.created",
                  "export_batch.delivered",
                  "export_batch.delivery_failed",
                  "absence.submitted",
                  "absence.decided",
                  "shift.published",
                  "invoice.issued",
                  "invoice.credited",
                  "invoice.dispatched",
                  "invoice.delivered",
                  "invoice.delivery_failed",
                  "payment.recorded",
                  "payment.allocated",
                  "payment.imported",
                  "invoice.overdue",
                  "invoice.drafts_ready",
                  "recurring_plan.run_completed",
                  "batch.delivered",
                  "workday.confirmed",
                  "workday.returned",
                  "workday.corrected",
                  "workday.unapproved",
                  "absence.cancelled",
                  "absence.certificate_provided",
                  "shift.changed",
                  "open_shift.claimed",
                  "open_shift.claim_decided",
                  "shift_swap.proposed",
                  "shift_swap.decided",
                  "export_batch.cancelled",
                  "payroll_period.locked",
                  "payroll_period.lock_lifted",
                  "member.created",
                  "member.invited",
                  "member.deactivated",
                  "employment.terminated",
                  "task.created",
                  "task.status_changed",
                  "task.approval_responded",
                  "quote.sent",
                  "quote.accepted",
                  "deal.lost",
                  "deal.stage_changed",
                  "lead.converted",
                  "intake.received",
                  "change_order.approved",
                  "project.created",
                  "project.closed",
                  "contact.anonymized",
                  "lead.anonymized",
                  "invoice.paid",
                  "customer.created",
                  "customer.updated",
                  "project.updated",
                  "member.updated",
                  "shift.unpublished"
                ]
              },
              "payload": {
                "type": "object",
                "additionalProperties": {}
              },
              "createdAt": {
                "type": "string",
                "format": "date-time",
                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
              }
            },
            "required": [
              "id",
              "event",
              "payload",
              "createdAt"
            ]
          }
        },
        "pageInfo": {
          "type": "object",
          "properties": {
            "nextCursor": {
              "type": "string",
              "x-nullable": true
            },
            "hasMore": {
              "type": "boolean"
            }
          },
          "required": [
            "nextCursor",
            "hasMore"
          ]
        }
      },
      "required": [
        "items",
        "pageInfo"
      ]
    },
    "WebhookEventCatalogResponseDto": {
      "type": "object",
      "properties": {
        "events": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "event": {
                "type": "string",
                "enum": [
                  "quote.decided",
                  "batch.created",
                  "status_update.posted",
                  "deal.won",
                  "lead.created",
                  "workday.approved",
                  "export_batch.created",
                  "export_batch.delivered",
                  "export_batch.delivery_failed",
                  "absence.submitted",
                  "absence.decided",
                  "shift.published",
                  "invoice.issued",
                  "invoice.credited",
                  "invoice.dispatched",
                  "invoice.delivered",
                  "invoice.delivery_failed",
                  "payment.recorded",
                  "payment.allocated",
                  "payment.imported",
                  "invoice.overdue",
                  "invoice.drafts_ready",
                  "recurring_plan.run_completed",
                  "batch.delivered",
                  "workday.confirmed",
                  "workday.returned",
                  "workday.corrected",
                  "workday.unapproved",
                  "absence.cancelled",
                  "absence.certificate_provided",
                  "shift.changed",
                  "open_shift.claimed",
                  "open_shift.claim_decided",
                  "shift_swap.proposed",
                  "shift_swap.decided",
                  "export_batch.cancelled",
                  "payroll_period.locked",
                  "payroll_period.lock_lifted",
                  "member.created",
                  "member.invited",
                  "member.deactivated",
                  "employment.terminated",
                  "task.created",
                  "task.status_changed",
                  "task.approval_responded",
                  "quote.sent",
                  "quote.accepted",
                  "deal.lost",
                  "deal.stage_changed",
                  "lead.converted",
                  "intake.received",
                  "change_order.approved",
                  "project.created",
                  "project.closed",
                  "contact.anonymized",
                  "lead.anonymized",
                  "invoice.paid",
                  "customer.created",
                  "customer.updated",
                  "project.updated",
                  "member.updated",
                  "shift.unpublished"
                ]
              },
              "capabilities": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "payloadSchema": {
                "type": "object",
                "additionalProperties": {}
              }
            },
            "required": [
              "event",
              "capabilities",
              "payloadSchema"
            ]
          }
        }
      },
      "required": [
        "events"
      ]
    },
    "MeEntitlementsResponseDto": {
      "type": "object",
      "properties": {
        "modules": {
          "type": "array",
          "items": {
            "type": "string",
            "enum": [
              "shift_planning",
              "travel_expense",
              "hr",
              "project_management",
              "crm"
            ]
          }
        },
        "tenantModules": {
          "type": "array",
          "items": {
            "type": "string",
            "enum": [
              "shift_planning",
              "travel_expense",
              "hr",
              "project_management",
              "crm"
            ]
          }
        },
        "activatedModules": {
          "type": "array",
          "items": {
            "type": "string",
            "enum": [
              "shift_planning",
              "travel_expense",
              "hr",
              "project_management",
              "crm"
            ]
          }
        },
        "tenantFeatures": {
          "type": "object",
          "properties": {
            "announcementsEnabled": {
              "type": "boolean"
            },
            "leaveAllowAdvance": {
              "type": "boolean"
            },
            "supplementsEnabled": {
              "type": "boolean"
            },
            "presenceBoardEnabled": {
              "type": "boolean"
            },
            "punchDevicesEnabled": {
              "type": "boolean"
            },
            "punchClockEnabled": {
              "type": "boolean"
            },
            "punchSitesEnabled": {
              "type": "boolean"
            },
            "automationEnabled": {
              "type": "boolean"
            },
            "autonomousSchedulingEnabled": {
              "type": "boolean"
            },
            "demandForecastEnabled": {
              "type": "boolean"
            },
            "rotationsEnabled": {
              "type": "boolean"
            },
            "standbyEnabled": {
              "type": "boolean"
            },
            "shiftMessagesEnabled": {
              "type": "boolean"
            },
            "openShiftsEnabled": {
              "type": "boolean"
            },
            "openShiftsCrossUnit": {
              "type": "boolean"
            },
            "shiftSwapsEnabled": {
              "type": "boolean"
            },
            "drivingTimeEnabled": {
              "type": "boolean"
            },
            "billingBaseEnabled": {
              "type": "boolean"
            },
            "entryBillableEnabled": {
              "type": "boolean"
            },
            "calendarSyncEnabled": {
              "type": "boolean"
            },
            "calendarFeedEnabled": {
              "type": "boolean"
            },
            "mileageEnabled": {
              "type": "boolean"
            },
            "perDiemEnabled": {
              "type": "boolean"
            },
            "foreignTravelEnabled": {
              "type": "boolean"
            },
            "travelExportEnabled": {
              "type": "boolean"
            },
            "expenseBillingEnabled": {
              "type": "boolean"
            },
            "receiptRequiredEnabled": {
              "type": "boolean"
            },
            "travelTwoStepApprovalEnabled": {
              "type": "boolean"
            },
            "workplaceClassificationEnabled": {
              "type": "boolean"
            },
            "tasksEnabled": {
              "type": "boolean"
            },
            "projectTimelineEnabled": {
              "type": "boolean"
            },
            "projectWorkloadEnabled": {
              "type": "boolean"
            },
            "projectQuotesEnabled": {
              "type": "boolean"
            },
            "projectEconomyEnabled": {
              "type": "boolean"
            },
            "projectBillingEnabled": {
              "type": "boolean"
            },
            "projectIntakeEnabled": {
              "type": "boolean"
            },
            "crmLeadsEnabled": {
              "type": "boolean"
            },
            "crmAutomationsEnabled": {
              "type": "boolean"
            },
            "crmEmailDropboxEnabled": {
              "type": "boolean"
            },
            "crmMailboxSyncEnabled": {
              "type": "boolean"
            },
            "skillSelfAssessmentEnabled": {
              "type": "boolean"
            },
            "hrRecruitingEnabled": {
              "type": "boolean"
            },
            "hrDevelopmentEnabled": {
              "type": "boolean"
            },
            "hrTrainingEnabled": {
              "type": "boolean"
            },
            "hrSafetyEnabled": {
              "type": "boolean"
            },
            "hrWhistleblowingEnabled": {
              "type": "boolean"
            },
            "hrServiceRequestsEnabled": {
              "type": "boolean"
            },
            "pulseEnabled": {
              "type": "boolean"
            },
            "managerCanRecordSkills": {
              "type": "boolean"
            },
            "managerCanAddCandidates": {
              "type": "boolean"
            },
            "managerCanReadTerms": {
              "type": "boolean"
            },
            "managerActOnBehalf": {
              "type": "boolean"
            },
            "managerProjectsAccess": {
              "type": "boolean"
            },
            "managerCrmAccess": {
              "type": "boolean"
            }
          },
          "required": [
            "announcementsEnabled",
            "leaveAllowAdvance",
            "supplementsEnabled",
            "presenceBoardEnabled",
            "punchDevicesEnabled",
            "punchClockEnabled",
            "punchSitesEnabled",
            "automationEnabled",
            "autonomousSchedulingEnabled",
            "demandForecastEnabled",
            "rotationsEnabled",
            "standbyEnabled",
            "shiftMessagesEnabled",
            "openShiftsEnabled",
            "openShiftsCrossUnit",
            "shiftSwapsEnabled",
            "drivingTimeEnabled",
            "billingBaseEnabled",
            "entryBillableEnabled",
            "calendarSyncEnabled",
            "calendarFeedEnabled",
            "mileageEnabled",
            "perDiemEnabled",
            "foreignTravelEnabled",
            "travelExportEnabled",
            "expenseBillingEnabled",
            "receiptRequiredEnabled",
            "travelTwoStepApprovalEnabled",
            "workplaceClassificationEnabled",
            "tasksEnabled",
            "projectTimelineEnabled",
            "projectWorkloadEnabled",
            "projectQuotesEnabled",
            "projectEconomyEnabled",
            "projectBillingEnabled",
            "projectIntakeEnabled",
            "crmLeadsEnabled",
            "crmAutomationsEnabled",
            "crmEmailDropboxEnabled",
            "crmMailboxSyncEnabled",
            "skillSelfAssessmentEnabled",
            "hrRecruitingEnabled",
            "hrDevelopmentEnabled",
            "hrTrainingEnabled",
            "hrSafetyEnabled",
            "hrWhistleblowingEnabled",
            "hrServiceRequestsEnabled",
            "pulseEnabled",
            "managerCanRecordSkills",
            "managerCanAddCandidates",
            "managerCanReadTerms",
            "managerActOnBehalf",
            "managerProjectsAccess",
            "managerCrmAccess"
          ]
        },
        "crmSeat": {
          "type": "boolean"
        },
        "worktimeMode": {
          "type": "string",
          "enum": [
            "office",
            "shift",
            "mixed"
          ]
        },
        "hasTes": {
          "type": "boolean"
        },
        "capabilities": {
          "type": "array",
          "items": {
            "type": "string",
            "enum": [
              "worktime.supervise",
              "scheduling.plan",
              "scheduling.admin",
              "projects.manage",
              "projects.read",
              "crm.use",
              "crm.admin",
              "hr.manage",
              "hr.record",
              "payroll.run",
              "reports.team",
              "members.manage",
              "comms.announce",
              "integrations.manage",
              "org.admin"
            ]
          }
        }
      },
      "required": [
        "modules",
        "tenantModules",
        "activatedModules",
        "tenantFeatures",
        "crmSeat",
        "worktimeMode",
        "hasTes",
        "capabilities"
      ]
    },
    "TripIdResponseDto": {
      "type": "object",
      "properties": {
        "id": {
          "type": "string"
        }
      },
      "required": [
        "id"
      ]
    },
    "TripOkResponseDto": {
      "type": "object",
      "properties": {
        "ok": {
          "type": "boolean"
        }
      },
      "required": [
        "ok"
      ]
    },
    "TripListResponseDto": {
      "type": "object",
      "properties": {
        "items": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "membershipId": {
                "type": "string"
              },
              "memberName": {
                "type": "string"
              },
              "purpose": {
                "type": "string"
              },
              "destination": {
                "type": "string"
              },
              "scope": {
                "type": "string",
                "enum": [
                  "domestic",
                  "foreign"
                ]
              },
              "startAt": {
                "type": "string",
                "format": "date-time",
                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
              },
              "endAt": {
                "type": "string",
                "format": "date-time",
                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
              },
              "status": {
                "type": "string",
                "enum": [
                  "draft",
                  "submitted",
                  "reviewed",
                  "approved"
                ]
              },
              "returnReason": {
                "type": "string",
                "x-nullable": true
              },
              "transportMode": {
                "type": "string",
                "enum": [
                  "own_car",
                  "company_car",
                  "public",
                  "plane",
                  "ship",
                  "other",
                  null
                ],
                "x-nullable": true
              },
              "valueName": {
                "type": "string",
                "x-nullable": true
              },
              "dimensionValueId": {
                "type": "string",
                "x-nullable": true
              },
              "allocations": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "dimensionId": {
                      "type": "string"
                    },
                    "valueId": {
                      "type": "string"
                    },
                    "valueName": {
                      "type": "string",
                      "x-nullable": true
                    }
                  },
                  "required": [
                    "dimensionId",
                    "valueId",
                    "valueName"
                  ]
                }
              },
              "billable": {
                "type": "boolean"
              },
              "taxFreeTotalCents": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "payableTotalCents": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "taxableTotalCents": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "reimbursableTotalCents": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "exportedAt": {
                "type": "string",
                "format": "date-time",
                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$",
                "x-nullable": true
              },
              "submittedAt": {
                "type": "string",
                "format": "date-time",
                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$",
                "x-nullable": true
              }
            },
            "required": [
              "id",
              "membershipId",
              "memberName",
              "purpose",
              "destination",
              "scope",
              "startAt",
              "endAt",
              "status",
              "returnReason",
              "transportMode",
              "valueName",
              "dimensionValueId",
              "allocations",
              "billable",
              "taxFreeTotalCents",
              "payableTotalCents",
              "taxableTotalCents",
              "reimbursableTotalCents",
              "exportedAt",
              "submittedAt"
            ]
          }
        },
        "pageInfo": {
          "type": "object",
          "properties": {
            "nextCursor": {
              "type": "string",
              "x-nullable": true
            },
            "hasMore": {
              "type": "boolean"
            }
          },
          "required": [
            "nextCursor",
            "hasMore"
          ]
        }
      },
      "required": [
        "items",
        "pageInfo"
      ]
    },
    "CreateTripDto": {
      "type": "object",
      "properties": {
        "purpose": {
          "type": "string",
          "minLength": 1,
          "maxLength": 200
        },
        "destination": {
          "type": "string",
          "maxLength": 200
        },
        "scope": {
          "type": "string",
          "enum": [
            "domestic",
            "foreign"
          ]
        },
        "startAt": {
          "type": "string",
          "format": "date-time",
          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
        },
        "endAt": {
          "type": "string",
          "format": "date-time",
          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
        },
        "countryCode": {
          "type": "string",
          "pattern": "^[A-Za-z]{2}(-[A-Za-z0-9]{2,3})?$"
        },
        "dimensionValueId": {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
          "x-nullable": true
        },
        "allocations": {
          "maxItems": 20,
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "dimensionId": {
                "type": "string",
                "format": "uuid",
                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
              },
              "valueId": {
                "type": "string",
                "format": "uuid",
                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
              }
            },
            "required": [
              "dimensionId",
              "valueId"
            ]
          }
        },
        "billable": {
          "type": "boolean"
        },
        "reimbursable": {
          "type": "boolean"
        },
        "transportMode": {
          "type": "string",
          "enum": [
            "own_car",
            "company_car",
            "public",
            "plane",
            "ship",
            "other",
            null
          ],
          "x-nullable": true
        }
      },
      "required": [
        "purpose",
        "startAt",
        "endAt"
      ]
    },
    "TripViewDto": {
      "type": "object",
      "properties": {
        "id": {
          "type": "string"
        },
        "membershipId": {
          "type": "string"
        },
        "memberName": {
          "type": "string"
        },
        "purpose": {
          "type": "string"
        },
        "destination": {
          "type": "string"
        },
        "scope": {
          "type": "string",
          "enum": [
            "domestic",
            "foreign"
          ]
        },
        "startAt": {
          "type": "string",
          "format": "date-time",
          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
        },
        "endAt": {
          "type": "string",
          "format": "date-time",
          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
        },
        "status": {
          "type": "string",
          "enum": [
            "draft",
            "submitted",
            "reviewed",
            "approved"
          ]
        },
        "returnReason": {
          "type": "string",
          "x-nullable": true
        },
        "transportMode": {
          "type": "string",
          "enum": [
            "own_car",
            "company_car",
            "public",
            "plane",
            "ship",
            "other",
            null
          ],
          "x-nullable": true
        },
        "valueName": {
          "type": "string",
          "x-nullable": true
        },
        "dimensionValueId": {
          "type": "string",
          "x-nullable": true
        },
        "allocations": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "dimensionId": {
                "type": "string"
              },
              "valueId": {
                "type": "string"
              },
              "valueName": {
                "type": "string",
                "x-nullable": true
              }
            },
            "required": [
              "dimensionId",
              "valueId",
              "valueName"
            ]
          }
        },
        "billable": {
          "type": "boolean"
        },
        "taxFreeTotalCents": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991
        },
        "payableTotalCents": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991
        },
        "taxableTotalCents": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991
        },
        "reimbursableTotalCents": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991
        },
        "exportedAt": {
          "type": "string",
          "format": "date-time",
          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$",
          "x-nullable": true
        },
        "submittedAt": {
          "type": "string",
          "format": "date-time",
          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$",
          "x-nullable": true
        },
        "reimbursable": {
          "type": "boolean"
        },
        "reviewedAt": {
          "type": "string",
          "format": "date-time",
          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$",
          "x-nullable": true
        },
        "approvedAt": {
          "type": "string",
          "format": "date-time",
          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$",
          "x-nullable": true
        },
        "returnedAt": {
          "type": "string",
          "format": "date-time",
          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$",
          "x-nullable": true
        },
        "legs": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "countryCode": {
                "type": "string",
                "pattern": "^[A-Za-z]{2}(-[A-Za-z0-9]{2,3})?$"
              },
              "startAt": {
                "type": "string",
                "format": "date-time",
                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
              },
              "aboard": {
                "type": "boolean"
              }
            },
            "required": [
              "startAt"
            ]
          }
        },
        "days": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "dayIndex": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "windowStart": {
                "type": "string",
                "format": "date-time",
                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
              },
              "windowEnd": {
                "type": "string",
                "format": "date-time",
                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
              },
              "durationMinutes": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "countryCode": {
                "type": "string"
              },
              "rateCountryCode": {
                "type": "string"
              },
              "countryOverride": {
                "type": "boolean"
              },
              "freeMeals": {
                "type": "integer",
                "minimum": 0,
                "maximum": 2
              },
              "freeLodging": {
                "type": "boolean"
              },
              "nightAllowanceClaimed": {
                "type": "boolean"
              },
              "nightAllowanceEligible": {
                "type": "boolean"
              },
              "note": {
                "type": "string",
                "x-nullable": true
              },
              "dimensionValueId": {
                "type": "string",
                "x-nullable": true
              },
              "allocations": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "dimensionId": {
                      "type": "string"
                    },
                    "valueId": {
                      "type": "string"
                    },
                    "valueName": {
                      "type": "string",
                      "x-nullable": true
                    }
                  },
                  "required": [
                    "dimensionId",
                    "valueId",
                    "valueName"
                  ]
                }
              },
              "effectiveAllocations": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "dimensionId": {
                      "type": "string"
                    },
                    "valueId": {
                      "type": "string"
                    },
                    "valueName": {
                      "type": "string",
                      "x-nullable": true
                    }
                  },
                  "required": [
                    "dimensionId",
                    "valueId",
                    "valueName"
                  ]
                }
              },
              "billable": {
                "type": "boolean"
              },
              "reimbursable": {
                "type": "boolean"
              },
              "level": {
                "type": "string",
                "enum": [
                  "full",
                  "partial",
                  "none"
                ]
              },
              "perDiemBaseCents": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "perDiemCapCents": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "mealReductionCents": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "nightAllowanceCents": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "perDiemPaidCents": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "nightAllowancePaidCents": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              }
            },
            "required": [
              "id",
              "dayIndex",
              "windowStart",
              "windowEnd",
              "durationMinutes",
              "countryCode",
              "rateCountryCode",
              "countryOverride",
              "freeMeals",
              "freeLodging",
              "nightAllowanceClaimed",
              "nightAllowanceEligible",
              "note",
              "dimensionValueId",
              "allocations",
              "effectiveAllocations",
              "billable",
              "reimbursable",
              "level",
              "perDiemBaseCents",
              "perDiemCapCents",
              "mealReductionCents",
              "nightAllowanceCents",
              "perDiemPaidCents",
              "nightAllowancePaidCents"
            ]
          }
        },
        "lines": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "membershipId": {
                "type": "string"
              },
              "memberName": {
                "type": "string"
              },
              "expenseDate": {
                "type": "string",
                "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
              },
              "type": {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "string"
                  },
                  "code": {
                    "type": "string"
                  },
                  "nameFi": {
                    "type": "string"
                  },
                  "nameSv": {
                    "type": "string"
                  },
                  "nameEn": {
                    "type": "string"
                  },
                  "kind": {
                    "type": "string",
                    "enum": [
                      "actual",
                      "unit_rate",
                      "tes"
                    ]
                  },
                  "unit": {
                    "type": "string",
                    "enum": [
                      "piece",
                      "km",
                      "day"
                    ]
                  }
                },
                "required": [
                  "id",
                  "code",
                  "nameFi",
                  "nameSv",
                  "nameEn",
                  "kind",
                  "unit"
                ]
              },
              "description": {
                "type": "string",
                "x-nullable": true
              },
              "quantity": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991,
                "x-nullable": true
              },
              "amountCents": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "vatCents": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991,
                "x-nullable": true
              },
              "vatBreakdown": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "rateBps": {
                      "type": "integer",
                      "minimum": 0,
                      "maximum": 10000
                    },
                    "grossCents": {
                      "type": "integer",
                      "minimum": 0,
                      "maximum": 9007199254740991
                    },
                    "vatCents": {
                      "type": "integer",
                      "minimum": 0,
                      "maximum": 9007199254740991
                    }
                  },
                  "required": [
                    "rateBps",
                    "grossCents",
                    "vatCents"
                  ]
                },
                "x-nullable": true
              },
              "paidBy": {
                "type": "string",
                "enum": [
                  "company",
                  "employee"
                ]
              },
              "reimbursable": {
                "type": "boolean"
              },
              "billable": {
                "type": "boolean"
              },
              "billableAmountCents": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991,
                "x-nullable": true
              },
              "billingMode": {
                "type": "string",
                "enum": [
                  "billable_amount",
                  "cost",
                  "cost_multiplier",
                  "manual"
                ]
              },
              "billingMultiplierPermille": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991,
                "x-nullable": true
              },
              "dimensionValueId": {
                "type": "string",
                "x-nullable": true
              },
              "valueName": {
                "type": "string",
                "x-nullable": true
              },
              "allocations": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "dimensionId": {
                      "type": "string"
                    },
                    "valueId": {
                      "type": "string"
                    },
                    "valueName": {
                      "type": "string",
                      "x-nullable": true
                    }
                  },
                  "required": [
                    "dimensionId",
                    "valueId",
                    "valueName"
                  ]
                }
              },
              "status": {
                "type": "string",
                "enum": [
                  "draft",
                  "submitted",
                  "reviewed",
                  "approved"
                ]
              },
              "submittedAt": {
                "type": "string",
                "format": "date-time",
                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$",
                "x-nullable": true
              },
              "returnReason": {
                "type": "string",
                "x-nullable": true
              },
              "tripId": {
                "type": "string",
                "x-nullable": true
              },
              "tripDayId": {
                "type": "string",
                "x-nullable": true
              },
              "maxTaxFreeCents": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991,
                "x-nullable": true
              },
              "originalCurrency": {
                "type": "string",
                "x-nullable": true
              },
              "originalAmountCents": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991,
                "x-nullable": true
              },
              "mileage": {
                "type": "object",
                "properties": {
                  "kmHundredths": {
                    "type": "integer",
                    "minimum": -9007199254740991,
                    "maximum": 9007199254740991
                  },
                  "fromText": {
                    "type": "string",
                    "x-nullable": true
                  },
                  "toText": {
                    "type": "string",
                    "x-nullable": true
                  },
                  "roundTrip": {
                    "type": "boolean"
                  },
                  "additions": {
                    "type": "object",
                    "properties": {
                      "passengers": {
                        "type": "integer",
                        "minimum": 0,
                        "maximum": 9
                      },
                      "trailer": {
                        "type": "boolean"
                      },
                      "caravan": {
                        "type": "boolean"
                      },
                      "heavyLoad": {
                        "type": "boolean"
                      },
                      "machine": {
                        "type": "boolean"
                      },
                      "dog": {
                        "type": "boolean"
                      },
                      "forest": {
                        "type": "boolean"
                      }
                    },
                    "x-nullable": true
                  },
                  "source": {
                    "type": "string",
                    "enum": [
                      "manual",
                      "route",
                      "odometer",
                      "gps"
                    ]
                  },
                  "route": {
                    "type": "object",
                    "properties": {
                      "fromPlace": {
                        "type": "object",
                        "properties": {
                          "text": {
                            "type": "string",
                            "minLength": 1,
                            "maxLength": 160
                          },
                          "lat": {
                            "type": "number",
                            "minimum": -90,
                            "maximum": 90
                          },
                          "lon": {
                            "type": "number",
                            "minimum": -180,
                            "maximum": 180
                          }
                        },
                        "required": [
                          "text"
                        ]
                      },
                      "toPlace": {
                        "type": "object",
                        "properties": {
                          "text": {
                            "type": "string",
                            "minLength": 1,
                            "maxLength": 160
                          },
                          "lat": {
                            "type": "number",
                            "minimum": -90,
                            "maximum": 90
                          },
                          "lon": {
                            "type": "number",
                            "minimum": -180,
                            "maximum": 180
                          }
                        },
                        "required": [
                          "text"
                        ]
                      },
                      "waypoints": {
                        "maxItems": 15,
                        "type": "array",
                        "items": {
                          "type": "object",
                          "properties": {
                            "text": {
                              "type": "string",
                              "minLength": 1,
                              "maxLength": 160
                            },
                            "lat": {
                              "type": "number",
                              "minimum": -90,
                              "maximum": 90
                            },
                            "lon": {
                              "type": "number",
                              "minimum": -180,
                              "maximum": 180
                            }
                          },
                          "required": [
                            "text"
                          ]
                        }
                      },
                      "computedKmHundredths": {
                        "type": "integer",
                        "minimum": 0,
                        "maximum": 9007199254740991
                      },
                      "provider": {
                        "type": "string",
                        "maxLength": 40
                      },
                      "alternativeIndex": {
                        "type": "integer",
                        "minimum": 0,
                        "maximum": 9007199254740991
                      }
                    },
                    "required": [
                      "fromPlace",
                      "toPlace",
                      "computedKmHundredths"
                    ],
                    "x-nullable": true
                  },
                  "odometer": {
                    "type": "object",
                    "properties": {
                      "startKm": {
                        "type": "integer",
                        "minimum": 0,
                        "maximum": 9007199254740991
                      },
                      "endKm": {
                        "type": "integer",
                        "minimum": 0,
                        "maximum": 9007199254740991
                      }
                    },
                    "required": [
                      "startKm",
                      "endKm"
                    ],
                    "x-nullable": true
                  },
                  "vehicleId": {
                    "type": "string",
                    "x-nullable": true
                  }
                },
                "required": [
                  "kmHundredths",
                  "fromText",
                  "toText",
                  "roundTrip",
                  "additions",
                  "source",
                  "route",
                  "odometer",
                  "vehicleId"
                ],
                "x-nullable": true
              },
              "policyFlags": {
                "type": "array",
                "items": {
                  "type": "string",
                  "enum": [
                    "over_limit",
                    "receipt_required",
                    "project_required",
                    "meal_allowance_with_per_diem",
                    "possible_duplicate"
                  ]
                }
              },
              "hasReceipt": {
                "type": "boolean"
              },
              "exportedAt": {
                "type": "string",
                "x-nullable": true
              },
              "policyMaxPerExpenseCents": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991,
                "x-nullable": true
              }
            },
            "required": [
              "id",
              "membershipId",
              "memberName",
              "expenseDate",
              "type",
              "description",
              "quantity",
              "amountCents",
              "vatCents",
              "vatBreakdown",
              "paidBy",
              "reimbursable",
              "billable",
              "billableAmountCents",
              "dimensionValueId",
              "valueName",
              "allocations",
              "status",
              "submittedAt",
              "returnReason",
              "tripId",
              "tripDayId",
              "maxTaxFreeCents",
              "originalCurrency",
              "originalAmountCents",
              "mileage",
              "policyFlags",
              "hasReceipt",
              "exportedAt",
              "policyMaxPerExpenseCents"
            ]
          }
        }
      },
      "required": [
        "id",
        "membershipId",
        "memberName",
        "purpose",
        "destination",
        "scope",
        "startAt",
        "endAt",
        "status",
        "returnReason",
        "transportMode",
        "valueName",
        "dimensionValueId",
        "allocations",
        "billable",
        "taxFreeTotalCents",
        "payableTotalCents",
        "taxableTotalCents",
        "reimbursableTotalCents",
        "exportedAt",
        "submittedAt",
        "reimbursable",
        "reviewedAt",
        "approvedAt",
        "returnedAt",
        "legs",
        "days",
        "lines"
      ]
    },
    "UpdateTripDto": {
      "type": "object",
      "properties": {
        "purpose": {
          "type": "string",
          "minLength": 1,
          "maxLength": 200
        },
        "destination": {
          "type": "string",
          "maxLength": 200
        },
        "scope": {
          "type": "string",
          "enum": [
            "domestic",
            "foreign"
          ]
        },
        "startAt": {
          "type": "string",
          "format": "date-time",
          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
        },
        "endAt": {
          "type": "string",
          "format": "date-time",
          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
        },
        "countryCode": {
          "type": "string",
          "pattern": "^[A-Za-z]{2}(-[A-Za-z0-9]{2,3})?$"
        },
        "dimensionValueId": {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
          "x-nullable": true
        },
        "allocations": {
          "maxItems": 20,
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "dimensionId": {
                "type": "string",
                "format": "uuid",
                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
              },
              "valueId": {
                "type": "string",
                "format": "uuid",
                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
              }
            },
            "required": [
              "dimensionId",
              "valueId"
            ]
          }
        },
        "billable": {
          "type": "boolean"
        },
        "reimbursable": {
          "type": "boolean"
        },
        "transportMode": {
          "type": "string",
          "enum": [
            "own_car",
            "company_car",
            "public",
            "plane",
            "ship",
            "other",
            null
          ],
          "x-nullable": true
        },
        "legs": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "countryCode": {
                "type": "string",
                "pattern": "^[A-Za-z]{2}(-[A-Za-z0-9]{2,3})?$"
              },
              "startAt": {
                "type": "string",
                "format": "date-time",
                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
              },
              "aboard": {
                "type": "boolean"
              }
            },
            "required": [
              "startAt"
            ]
          }
        }
      }
    },
    "UpdateTripResponseDto": {
      "type": "object",
      "properties": {
        "ok": {
          "type": "boolean"
        },
        "attributionPropagated": {
          "type": "integer",
          "minimum": 0,
          "maximum": 9007199254740991
        },
        "attributionLocked": {
          "type": "integer",
          "minimum": 0,
          "maximum": 9007199254740991
        }
      },
      "required": [
        "ok",
        "attributionPropagated",
        "attributionLocked"
      ]
    },
    "UpdateTripDayDto": {
      "type": "object",
      "properties": {
        "countryCode": {
          "type": "string",
          "pattern": "^[A-Za-z]{2}(-[A-Za-z0-9]{2,3})?$",
          "x-nullable": true
        },
        "freeMeals": {
          "type": "integer",
          "minimum": 0,
          "maximum": 2
        },
        "freeLodging": {
          "type": "boolean"
        },
        "nightAllowanceClaimed": {
          "type": "boolean"
        },
        "note": {
          "type": "string",
          "maxLength": 500,
          "x-nullable": true
        },
        "dimensionValueId": {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
          "x-nullable": true
        },
        "allocations": {
          "maxItems": 20,
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "dimensionId": {
                "type": "string",
                "format": "uuid",
                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
              },
              "valueId": {
                "type": "string",
                "format": "uuid",
                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
              }
            },
            "required": [
              "dimensionId",
              "valueId"
            ]
          }
        },
        "billable": {
          "type": "boolean"
        },
        "reimbursable": {
          "type": "boolean"
        }
      }
    },
    "ReturnTripDto": {
      "type": "object",
      "properties": {
        "reason": {
          "type": "string",
          "minLength": 1,
          "maxLength": 500
        }
      },
      "required": [
        "reason"
      ]
    },
    "ProjectListResponseDto": {
      "type": "object",
      "properties": {
        "items": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "code": {
                "type": "string"
              },
              "name": {
                "type": "string"
              },
              "dimensionValueId": {
                "type": "string"
              },
              "customerId": {
                "type": "string",
                "x-nullable": true
              },
              "customerName": {
                "type": "string",
                "x-nullable": true
              },
              "contactId": {
                "type": "string",
                "x-nullable": true
              },
              "contactName": {
                "type": "string",
                "x-nullable": true
              },
              "ownerMembershipId": {
                "type": "string",
                "x-nullable": true
              },
              "ownerName": {
                "type": "string",
                "x-nullable": true
              },
              "status": {
                "type": "string",
                "enum": [
                  "draft",
                  "active",
                  "on_hold",
                  "closed"
                ]
              },
              "billingModel": {
                "type": "string",
                "enum": [
                  "time_materials",
                  "fixed_price",
                  "non_billable",
                  "retainer"
                ]
              },
              "defaultBillable": {
                "type": "boolean"
              },
              "startDate": {
                "type": "string",
                "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
                "x-nullable": true
              },
              "endDate": {
                "type": "string",
                "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
                "x-nullable": true
              },
              "budgetMinutes": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991,
                "x-nullable": true
              },
              "budgetAmountCents": {
                "type": "integer",
                "minimum": 0,
                "maximum": 9007199254740991,
                "x-nullable": true
              },
              "billingRoundingMinutes": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991,
                "x-nullable": true
              },
              "contractAmountCents": {
                "type": "integer",
                "minimum": 0,
                "maximum": 9007199254740991,
                "x-nullable": true
              },
              "retainerQuotaMinutes": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991,
                "x-nullable": true
              },
              "purchaseBillingMultiplierPermille": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991,
                "x-nullable": true
              },
              "taskTimeTracking": {
                "type": "string",
                "enum": [
                  "off",
                  "optional",
                  "required"
                ]
              },
              "memberTaskVisibility": {
                "type": "string",
                "enum": [
                  "assigned_only",
                  "project_members"
                ]
              },
              "taskAutoArchiveDays": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991,
                "x-nullable": true
              },
              "updatedAt": {
                "type": "string"
              }
            },
            "required": [
              "id",
              "code",
              "name",
              "dimensionValueId",
              "customerId",
              "customerName",
              "contactId",
              "contactName",
              "ownerMembershipId",
              "ownerName",
              "status",
              "billingModel",
              "defaultBillable",
              "startDate",
              "endDate",
              "budgetMinutes",
              "budgetAmountCents",
              "billingRoundingMinutes",
              "contractAmountCents",
              "retainerQuotaMinutes",
              "taskTimeTracking",
              "memberTaskVisibility",
              "taskAutoArchiveDays",
              "updatedAt"
            ]
          }
        },
        "pageInfo": {
          "type": "object",
          "properties": {
            "nextCursor": {
              "type": "string",
              "x-nullable": true
            },
            "hasMore": {
              "type": "boolean"
            }
          },
          "required": [
            "nextCursor",
            "hasMore"
          ]
        }
      },
      "required": [
        "items",
        "pageInfo"
      ]
    },
    "ProjectOkResponseDto": {
      "type": "object",
      "properties": {
        "ok": {
          "type": "boolean"
        }
      },
      "required": [
        "ok"
      ]
    },
    "ProjectReportResponseDto": {
      "type": "object",
      "properties": {
        "from": {
          "type": "string",
          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
        },
        "to": {
          "type": "string",
          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
        },
        "includesCost": {
          "type": "boolean"
        },
        "rows": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "projectId": {
                "type": "string"
              },
              "code": {
                "type": "string"
              },
              "name": {
                "type": "string"
              },
              "customerId": {
                "type": "string",
                "x-nullable": true
              },
              "customerName": {
                "type": "string",
                "x-nullable": true
              },
              "ownerMembershipId": {
                "type": "string",
                "x-nullable": true
              },
              "ownerName": {
                "type": "string",
                "x-nullable": true
              },
              "status": {
                "type": "string",
                "enum": [
                  "draft",
                  "active",
                  "on_hold",
                  "closed"
                ]
              },
              "billingModel": {
                "type": "string",
                "enum": [
                  "time_materials",
                  "fixed_price",
                  "non_billable",
                  "retainer"
                ]
              },
              "startDate": {
                "type": "string",
                "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
                "x-nullable": true
              },
              "endDate": {
                "type": "string",
                "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
                "x-nullable": true
              },
              "health": {
                "type": "string",
                "enum": [
                  "on_track",
                  "at_risk",
                  "over_budget",
                  "no_data"
                ]
              },
              "minutes": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "billableMinutes": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "lifetimeMinutes": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "revenueBasis": {
                "type": "string",
                "enum": [
                  "worked",
                  "invoiced"
                ]
              },
              "revenueCents": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991,
                "x-nullable": true
              },
              "contractValueCents": {
                "type": "integer",
                "minimum": 0,
                "maximum": 9007199254740991,
                "x-nullable": true
              },
              "approvedChangeOrderCents": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "invoicedLifetimeCents": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991,
                "x-nullable": true
              },
              "costCents": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991,
                "x-nullable": true
              },
              "marginCents": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991,
                "x-nullable": true
              },
              "marginPct": {
                "type": "number",
                "x-nullable": true
              },
              "expenseCostCents": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991,
                "x-nullable": true
              },
              "expenseRevenueCents": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "purchaseCostCents": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991,
                "x-nullable": true
              },
              "purchaseRevenueCents": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "unpricedBillableMinutes": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "uncostedMinutes": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991,
                "x-nullable": true
              },
              "budgetMinutes": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991,
                "x-nullable": true
              },
              "budgetAmountCents": {
                "type": "integer",
                "minimum": 0,
                "maximum": 9007199254740991,
                "x-nullable": true
              },
              "budgetMinutesUsedPct": {
                "type": "number",
                "x-nullable": true
              },
              "budgetAmountUsedPct": {
                "type": "number",
                "x-nullable": true
              },
              "openTaskCount": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "overdueTaskCount": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "healthReasons": {
                "type": "array",
                "items": {
                  "type": "string",
                  "enum": [
                    "over_budget",
                    "past_end",
                    "near_budget",
                    "thin_margin",
                    "losing",
                    "tasks_overdue"
                  ]
                }
              },
              "statusUpdate": {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "string"
                  },
                  "rag": {
                    "type": "string",
                    "enum": [
                      "on_track",
                      "at_risk",
                      "off_track"
                    ]
                  },
                  "note": {
                    "type": "string"
                  },
                  "authorName": {
                    "type": "string",
                    "x-nullable": true
                  },
                  "createdAt": {
                    "type": "string",
                    "format": "date-time",
                    "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
                  }
                },
                "required": [
                  "id",
                  "rag",
                  "note",
                  "authorName",
                  "createdAt"
                ],
                "x-nullable": true
              },
              "situation": {
                "type": "string",
                "enum": [
                  "on_track",
                  "at_risk",
                  "off_track",
                  "none"
                ]
              },
              "situationSource": {
                "type": "string",
                "enum": [
                  "update",
                  "computed"
                ]
              }
            },
            "required": [
              "projectId",
              "code",
              "name",
              "customerId",
              "customerName",
              "ownerMembershipId",
              "ownerName",
              "status",
              "billingModel",
              "startDate",
              "endDate",
              "health",
              "minutes",
              "billableMinutes",
              "lifetimeMinutes",
              "revenueBasis",
              "revenueCents",
              "contractValueCents",
              "approvedChangeOrderCents",
              "invoicedLifetimeCents",
              "costCents",
              "marginCents",
              "marginPct",
              "expenseCostCents",
              "expenseRevenueCents",
              "purchaseCostCents",
              "purchaseRevenueCents",
              "unpricedBillableMinutes",
              "uncostedMinutes",
              "budgetMinutes",
              "budgetAmountCents",
              "budgetMinutesUsedPct",
              "budgetAmountUsedPct",
              "openTaskCount",
              "overdueTaskCount",
              "healthReasons",
              "statusUpdate",
              "situation",
              "situationSource"
            ]
          }
        },
        "totals": {
          "type": "object",
          "properties": {
            "minutes": {
              "type": "integer",
              "minimum": -9007199254740991,
              "maximum": 9007199254740991
            },
            "billableMinutes": {
              "type": "integer",
              "minimum": -9007199254740991,
              "maximum": 9007199254740991
            },
            "revenueCents": {
              "type": "integer",
              "minimum": -9007199254740991,
              "maximum": 9007199254740991,
              "x-nullable": true
            },
            "costCents": {
              "type": "integer",
              "minimum": -9007199254740991,
              "maximum": 9007199254740991,
              "x-nullable": true
            },
            "marginCents": {
              "type": "integer",
              "minimum": -9007199254740991,
              "maximum": 9007199254740991,
              "x-nullable": true
            },
            "marginPct": {
              "type": "number",
              "x-nullable": true
            }
          },
          "required": [
            "minutes",
            "billableMinutes",
            "revenueCents",
            "costCents",
            "marginCents",
            "marginPct"
          ]
        },
        "unassignedMinutes": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991
        },
        "tesCost": {
          "type": "object",
          "properties": {
            "periodLabourCostCents": {
              "type": "integer",
              "minimum": -9007199254740991,
              "maximum": 9007199254740991
            },
            "flatLabourCostCents": {
              "type": "integer",
              "minimum": -9007199254740991,
              "maximum": 9007199254740991
            },
            "unweightedComponents": {
              "type": "array",
              "items": {
                "type": "string"
              }
            }
          },
          "required": [
            "periodLabourCostCents",
            "flatLabourCostCents",
            "unweightedComponents"
          ],
          "x-nullable": true
        }
      },
      "required": [
        "from",
        "to",
        "includesCost",
        "rows",
        "totals",
        "unassignedMinutes"
      ]
    },
    "CreateProjectDto": {
      "type": "object",
      "properties": {
        "code": {
          "type": "string",
          "pattern": "^[a-z0-9][a-z0-9_-]{0,49}$"
        },
        "name": {
          "type": "string",
          "minLength": 1,
          "maxLength": 200
        },
        "customerId": {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
          "x-nullable": true
        },
        "contactId": {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
          "x-nullable": true
        },
        "ownerMembershipId": {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
          "x-nullable": true
        },
        "billingModel": {
          "default": "time_materials",
          "type": "string",
          "enum": [
            "time_materials",
            "fixed_price",
            "non_billable",
            "retainer"
          ]
        },
        "defaultBillable": {
          "default": true,
          "type": "boolean"
        },
        "startDate": {
          "type": "string",
          "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
          "x-nullable": true
        },
        "endDate": {
          "type": "string",
          "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
          "x-nullable": true
        },
        "budgetMinutes": {
          "type": "integer",
          "minimum": 0,
          "maximum": 9007199254740991,
          "x-nullable": true
        },
        "budgetAmountCents": {
          "type": "integer",
          "minimum": 0,
          "maximum": 9007199254740991,
          "x-nullable": true
        },
        "billingRoundingMinutes": {
          "type": "integer",
          "minimum": 0,
          "maximum": 480,
          "x-nullable": true
        },
        "contractAmountCents": {
          "type": "integer",
          "minimum": 0,
          "maximum": 9007199254740991,
          "x-nullable": true
        },
        "retainerQuotaMinutes": {
          "type": "integer",
          "minimum": 0,
          "maximum": 9007199254740991,
          "x-nullable": true
        },
        "purchaseBillingMultiplierPermille": {
          "type": "integer",
          "minimum": 0,
          "maximum": 100000,
          "x-nullable": true
        },
        "template": {
          "type": "object",
          "properties": {
            "templateId": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            },
            "roleAssignments": {
              "default": [],
              "maxItems": 50,
              "type": "array",
              "items": {
                "type": "object",
                "properties": {
                  "roleKey": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 40
                  },
                  "membershipId": {
                    "type": "string",
                    "format": "uuid",
                    "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                  }
                },
                "required": [
                  "roleKey",
                  "membershipId"
                ]
              }
            }
          },
          "required": [
            "templateId"
          ]
        }
      },
      "required": [
        "code",
        "name"
      ]
    },
    "ProjectIdResponseDto": {
      "type": "object",
      "properties": {
        "id": {
          "type": "string"
        }
      },
      "required": [
        "id"
      ]
    },
    "UpdateProjectDto": {
      "type": "object",
      "properties": {
        "name": {
          "type": "string",
          "minLength": 1,
          "maxLength": 200
        },
        "customerId": {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
          "x-nullable": true
        },
        "contactId": {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
          "x-nullable": true
        },
        "ownerMembershipId": {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
          "x-nullable": true
        },
        "status": {
          "type": "string",
          "enum": [
            "draft",
            "active",
            "on_hold",
            "closed"
          ]
        },
        "billingModel": {
          "type": "string",
          "enum": [
            "time_materials",
            "fixed_price",
            "non_billable",
            "retainer"
          ]
        },
        "defaultBillable": {
          "type": "boolean"
        },
        "startDate": {
          "type": "string",
          "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
          "x-nullable": true
        },
        "endDate": {
          "type": "string",
          "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
          "x-nullable": true
        },
        "budgetMinutes": {
          "type": "integer",
          "minimum": 0,
          "maximum": 9007199254740991,
          "x-nullable": true
        },
        "budgetAmountCents": {
          "type": "integer",
          "minimum": 0,
          "maximum": 9007199254740991,
          "x-nullable": true
        },
        "billingRoundingMinutes": {
          "type": "integer",
          "minimum": 0,
          "maximum": 480,
          "x-nullable": true
        },
        "contractAmountCents": {
          "type": "integer",
          "minimum": 0,
          "maximum": 9007199254740991,
          "x-nullable": true
        },
        "retainerQuotaMinutes": {
          "type": "integer",
          "minimum": 0,
          "maximum": 9007199254740991,
          "x-nullable": true
        },
        "purchaseBillingMultiplierPermille": {
          "type": "integer",
          "minimum": 0,
          "maximum": 100000,
          "x-nullable": true
        },
        "taskTimeTracking": {
          "type": "string",
          "enum": [
            "off",
            "optional",
            "required"
          ]
        },
        "memberTaskVisibility": {
          "type": "string",
          "enum": [
            "assigned_only",
            "project_members"
          ]
        },
        "taskAutoArchiveDays": {
          "type": "integer",
          "minimum": 1,
          "maximum": 365,
          "x-nullable": true
        },
        "expectedUpdatedAt": {
          "type": "string"
        }
      }
    },
    "ProjectStatusUpdateListResponseDto": {
      "type": "object",
      "properties": {
        "items": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "rag": {
                "type": "string",
                "enum": [
                  "on_track",
                  "at_risk",
                  "off_track"
                ]
              },
              "note": {
                "type": "string"
              },
              "authorName": {
                "type": "string",
                "x-nullable": true
              },
              "createdAt": {
                "type": "string",
                "format": "date-time",
                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
              }
            },
            "required": [
              "id",
              "rag",
              "note",
              "authorName",
              "createdAt"
            ]
          }
        },
        "pageInfo": {
          "type": "object",
          "properties": {
            "nextCursor": {
              "type": "string",
              "x-nullable": true
            },
            "hasMore": {
              "type": "boolean"
            }
          },
          "required": [
            "nextCursor",
            "hasMore"
          ]
        }
      },
      "required": [
        "items",
        "pageInfo"
      ]
    },
    "CreateProjectStatusUpdateDto": {
      "type": "object",
      "properties": {
        "rag": {
          "type": "string",
          "enum": [
            "on_track",
            "at_risk",
            "off_track"
          ]
        },
        "note": {
          "type": "string",
          "minLength": 1,
          "maxLength": 2000
        }
      },
      "required": [
        "rag",
        "note"
      ]
    },
    "ProjectStatusUpdateViewDto": {
      "type": "object",
      "properties": {
        "id": {
          "type": "string"
        },
        "rag": {
          "type": "string",
          "enum": [
            "on_track",
            "at_risk",
            "off_track"
          ]
        },
        "note": {
          "type": "string"
        },
        "authorName": {
          "type": "string",
          "x-nullable": true
        },
        "createdAt": {
          "type": "string",
          "format": "date-time",
          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
        }
      },
      "required": [
        "id",
        "rag",
        "note",
        "authorName",
        "createdAt"
      ]
    },
    "ProjectInstallmentListResponseDto": {
      "type": "object",
      "properties": {
        "items": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "projectId": {
                "type": "string"
              },
              "sortOrder": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "title": {
                "type": "string"
              },
              "amountCents": {
                "type": "integer",
                "minimum": 0,
                "maximum": 9007199254740991
              },
              "dueDate": {
                "type": "string",
                "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
                "x-nullable": true
              },
              "milestoneId": {
                "type": "string",
                "x-nullable": true
              },
              "milestoneName": {
                "type": "string",
                "x-nullable": true
              },
              "status": {
                "type": "string",
                "enum": [
                  "draft",
                  "ready",
                  "draft_invoice",
                  "invoiced"
                ]
              },
              "readyAt": {
                "type": "string",
                "x-nullable": true
              },
              "invoiceBatchId": {
                "type": "string",
                "x-nullable": true
              },
              "invoicedAt": {
                "type": "string",
                "x-nullable": true
              },
              "updatedAt": {
                "type": "string"
              }
            },
            "required": [
              "id",
              "projectId",
              "sortOrder",
              "title",
              "amountCents",
              "dueDate",
              "milestoneId",
              "milestoneName",
              "status",
              "readyAt",
              "invoiceBatchId",
              "invoicedAt",
              "updatedAt"
            ]
          }
        },
        "contractAmountCents": {
          "type": "integer",
          "minimum": 0,
          "maximum": 9007199254740991,
          "x-nullable": true
        },
        "totalCents": {
          "type": "integer",
          "minimum": 0,
          "maximum": 9007199254740991
        },
        "invoicedCents": {
          "type": "integer",
          "minimum": 0,
          "maximum": 9007199254740991
        },
        "draftInvoiceCents": {
          "default": 0,
          "type": "integer",
          "minimum": 0,
          "maximum": 9007199254740991
        },
        "readyCents": {
          "type": "integer",
          "minimum": 0,
          "maximum": 9007199254740991
        }
      },
      "required": [
        "items",
        "contractAmountCents",
        "totalCents",
        "invoicedCents",
        "readyCents"
      ]
    },
    "ProjectPurchaseListResponseDto": {
      "type": "object",
      "properties": {
        "items": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "projectId": {
                "type": "string"
              },
              "phaseId": {
                "type": "string",
                "x-nullable": true
              },
              "phaseName": {
                "type": "string",
                "x-nullable": true
              },
              "date": {
                "type": "string",
                "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
              },
              "supplierName": {
                "type": "string",
                "x-nullable": true
              },
              "description": {
                "type": "string"
              },
              "category": {
                "type": "string",
                "enum": [
                  "material",
                  "subcontracting",
                  "rental",
                  "other"
                ]
              },
              "quantity": {
                "type": "number"
              },
              "unit": {
                "type": "string"
              },
              "unitCostCents": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "totalCostCents": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "billable": {
                "type": "boolean"
              },
              "unitSellCents": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991,
                "x-nullable": true
              },
              "totalSellCents": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991,
                "x-nullable": true
              },
              "billingMode": {
                "type": "string",
                "enum": [
                  "billable_amount",
                  "cost",
                  "cost_multiplier",
                  "manual"
                ]
              },
              "billingMultiplierPermille": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991,
                "x-nullable": true
              },
              "status": {
                "type": "string",
                "enum": [
                  "draft",
                  "approved"
                ]
              },
              "approvedAt": {
                "type": "string",
                "x-nullable": true
              },
              "invoiceBatchId": {
                "type": "string",
                "x-nullable": true
              },
              "updatedAt": {
                "type": "string"
              }
            },
            "required": [
              "id",
              "projectId",
              "phaseId",
              "phaseName",
              "date",
              "supplierName",
              "description",
              "category",
              "quantity",
              "unit",
              "unitCostCents",
              "totalCostCents",
              "billable",
              "unitSellCents",
              "totalSellCents",
              "status",
              "approvedAt",
              "invoiceBatchId",
              "updatedAt"
            ]
          }
        },
        "totalCostCents": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991
        },
        "totalSellCents": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991
        },
        "invoicedSellCents": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991
        },
        "byCategory": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "category": {
                "type": "string",
                "enum": [
                  "material",
                  "subcontracting",
                  "rental",
                  "other"
                ]
              },
              "costCents": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "sellCents": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              }
            },
            "required": [
              "category",
              "costCents",
              "sellCents"
            ]
          }
        },
        "suppliers": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "purchaseBillingMultiplierPermille": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991,
          "x-nullable": true
        }
      },
      "required": [
        "items",
        "totalCostCents",
        "totalSellCents",
        "invoicedSellCents",
        "byCategory",
        "suppliers",
        "purchaseBillingMultiplierPermille"
      ]
    },
    "ProjectActivityResponseDto": {
      "type": "object",
      "properties": {
        "projectId": {
          "type": "string"
        },
        "from": {
          "type": "string",
          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
        },
        "to": {
          "type": "string",
          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
        },
        "totalMinutes": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991
        },
        "billableMinutes": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991
        },
        "entries": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "workEntryId": {
                "type": "string"
              },
              "workDate": {
                "type": "string",
                "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
              },
              "memberName": {
                "type": "string"
              },
              "valueId": {
                "type": "string"
              },
              "valueName": {
                "type": "string"
              },
              "minutes": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "billable": {
                "type": "boolean"
              },
              "status": {
                "type": "string",
                "enum": [
                  "draft",
                  "confirmed",
                  "approved",
                  "exported"
                ]
              },
              "canReattribute": {
                "type": "boolean"
              }
            },
            "required": [
              "workEntryId",
              "workDate",
              "memberName",
              "valueId",
              "valueName",
              "minutes",
              "billable",
              "status",
              "canReattribute"
            ]
          }
        },
        "truncated": {
          "type": "boolean"
        }
      },
      "required": [
        "projectId",
        "from",
        "to",
        "totalMinutes",
        "billableMinutes",
        "entries",
        "truncated"
      ]
    },
    "ProjectPhaseListResponseDto": {
      "type": "object",
      "properties": {
        "phases": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "code": {
                "type": "string"
              },
              "name": {
                "type": "string"
              },
              "status": {
                "type": "string",
                "enum": [
                  "planned",
                  "active",
                  "done"
                ]
              },
              "sortOrder": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "dimensionValueId": {
                "type": "string"
              },
              "startDate": {
                "type": "string",
                "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
                "x-nullable": true
              },
              "endDate": {
                "type": "string",
                "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
                "x-nullable": true
              },
              "budgetMinutes": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991,
                "x-nullable": true
              },
              "budgetAmountCents": {
                "type": "integer",
                "minimum": 0,
                "maximum": 9007199254740991,
                "x-nullable": true
              },
              "actualMinutes": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "budgetMinutesUsedPct": {
                "type": "number",
                "x-nullable": true
              },
              "actualCostCents": {
                "type": "integer",
                "minimum": 0,
                "maximum": 9007199254740991,
                "x-nullable": true
              },
              "budgetAmountUsedPct": {
                "type": "number",
                "x-nullable": true
              }
            },
            "required": [
              "id",
              "code",
              "name",
              "status",
              "sortOrder",
              "dimensionValueId",
              "startDate",
              "endDate",
              "budgetMinutes",
              "budgetAmountCents",
              "actualMinutes",
              "budgetMinutesUsedPct",
              "actualCostCents",
              "budgetAmountUsedPct"
            ]
          }
        }
      },
      "required": [
        "phases"
      ]
    },
    "CreateExportBatchDto": {
      "type": "object",
      "properties": {
        "from": {
          "type": "string",
          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
        },
        "to": {
          "type": "string",
          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
        },
        "groupId": {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
        },
        "force": {
          "type": "boolean"
        },
        "forceReason": {
          "type": "string",
          "minLength": 1,
          "maxLength": 500
        },
        "includeCarryover": {
          "type": "boolean"
        }
      },
      "required": [
        "from",
        "to"
      ]
    },
    "ExportBatchViewDto": {
      "type": "object",
      "properties": {
        "id": {
          "type": "string"
        },
        "periodStart": {
          "type": "string",
          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
        },
        "periodEnd": {
          "type": "string",
          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
        },
        "createdAt": {
          "type": "string"
        },
        "dayCount": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991
        },
        "groupId": {
          "type": "string",
          "x-nullable": true
        },
        "deliveries": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "targetId": {
                "type": "string"
              },
              "targetName": {
                "type": "string"
              },
              "transport": {
                "type": "string",
                "enum": [
                  "download",
                  "http",
                  "sftp",
                  "netvisor"
                ]
              },
              "status": {
                "type": "string",
                "enum": [
                  "pending",
                  "delivering",
                  "delivered",
                  "failed"
                ]
              },
              "deliveredAt": {
                "type": "string",
                "x-nullable": true
              },
              "attempts": {
                "type": "integer",
                "minimum": 0,
                "maximum": 9007199254740991
              }
            },
            "required": [
              "targetId",
              "targetName",
              "transport",
              "status",
              "deliveredAt",
              "attempts"
            ]
          }
        },
        "lastDeliveredAt": {
          "type": "string",
          "x-nullable": true
        },
        "canceledAt": {
          "type": "string",
          "x-nullable": true
        }
      },
      "required": [
        "id",
        "periodStart",
        "periodEnd",
        "createdAt",
        "dayCount",
        "groupId",
        "deliveries",
        "lastDeliveredAt",
        "canceledAt"
      ]
    },
    "ExportPreflightResponseDto": {
      "type": "object",
      "properties": {
        "exportableDayCount": {
          "type": "integer",
          "minimum": 0,
          "maximum": 9007199254740991
        },
        "unmappedBuckets": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "activeTargetCount": {
          "type": "integer",
          "minimum": 0,
          "maximum": 9007199254740991
        },
        "targetCoverage": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "targetId": {
                "type": "string"
              },
              "targetName": {
                "type": "string"
              },
              "personCount": {
                "type": "integer",
                "minimum": 0,
                "maximum": 9007199254740991
              },
              "unmappedBuckets": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "identifierKind": {
                "type": "string",
                "enum": [
                  "email",
                  "employee_number",
                  "ssn"
                ]
              },
              "missingIdentifierNames": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            },
            "required": [
              "targetId",
              "targetName",
              "personCount",
              "unmappedBuckets",
              "identifierKind",
              "missingIdentifierNames"
            ]
          }
        },
        "uncoveredPersonCount": {
          "type": "integer",
          "minimum": 0,
          "maximum": 9007199254740991
        },
        "unapprovedDayCount": {
          "type": "integer",
          "minimum": 0,
          "maximum": 9007199254740991
        },
        "draftDayCount": {
          "type": "integer",
          "minimum": 0,
          "maximum": 9007199254740991
        },
        "missingDayCount": {
          "type": "integer",
          "minimum": 0,
          "maximum": 9007199254740991
        },
        "incompleteMembers": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "membershipId": {
                "type": "string"
              },
              "displayName": {
                "type": "string"
              },
              "missingDayCount": {
                "type": "integer",
                "minimum": 0,
                "maximum": 9007199254740991
              },
              "draftDayCount": {
                "type": "integer",
                "minimum": 0,
                "maximum": 9007199254740991
              },
              "unapprovedDayCount": {
                "type": "integer",
                "minimum": 0,
                "maximum": 9007199254740991
              }
            },
            "required": [
              "membershipId",
              "displayName",
              "missingDayCount",
              "draftDayCount",
              "unapprovedDayCount"
            ]
          }
        },
        "incompleteMemberTotal": {
          "type": "integer",
          "minimum": 0,
          "maximum": 9007199254740991
        },
        "carryoverDayCount": {
          "type": "integer",
          "minimum": 0,
          "maximum": 9007199254740991
        },
        "warnings": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "code": {
                "type": "string"
              },
              "params": {
                "default": {},
                "type": "object",
                "additionalProperties": {
                  "type": "string"
                }
              }
            },
            "required": [
              "code"
            ]
          }
        },
        "exceptions": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "membershipId": {
                "type": "string"
              },
              "memberName": {
                "type": "string"
              },
              "ruleName": {
                "type": "string"
              },
              "date": {
                "type": "string"
              },
              "code": {
                "type": "string"
              },
              "message": {
                "type": "string"
              }
            },
            "required": [
              "membershipId",
              "memberName",
              "ruleName",
              "date",
              "code",
              "message"
            ]
          }
        },
        "premiumBandConflicts": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "bandCode": {
                "type": "string"
              },
              "kind": {
                "type": "string",
                "enum": [
                  "evening",
                  "night",
                  "saturday",
                  "sunday",
                  "other"
                ]
              },
              "tesPayCodes": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "suppressedMinutes": {
                "type": "integer",
                "minimum": 0,
                "maximum": 9007199254740991
              },
              "dayCount": {
                "type": "integer",
                "minimum": 0,
                "maximum": 9007199254740991
              },
              "memberCount": {
                "type": "integer",
                "minimum": 0,
                "maximum": 9007199254740991
              }
            },
            "required": [
              "bandCode",
              "kind",
              "tesPayCodes",
              "suppressedMinutes",
              "dayCount",
              "memberCount"
            ]
          }
        }
      },
      "required": [
        "exportableDayCount",
        "unmappedBuckets",
        "activeTargetCount",
        "targetCoverage",
        "uncoveredPersonCount",
        "unapprovedDayCount",
        "draftDayCount",
        "missingDayCount",
        "incompleteMembers",
        "incompleteMemberTotal",
        "carryoverDayCount",
        "exceptions"
      ]
    },
    "ExportBatchListResponseDto": {
      "type": "object",
      "properties": {
        "items": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "periodStart": {
                "type": "string",
                "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
              },
              "periodEnd": {
                "type": "string",
                "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
              },
              "createdAt": {
                "type": "string"
              },
              "dayCount": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "groupId": {
                "type": "string",
                "x-nullable": true
              },
              "deliveries": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "targetId": {
                      "type": "string"
                    },
                    "targetName": {
                      "type": "string"
                    },
                    "transport": {
                      "type": "string",
                      "enum": [
                        "download",
                        "http",
                        "sftp",
                        "netvisor"
                      ]
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "pending",
                        "delivering",
                        "delivered",
                        "failed"
                      ]
                    },
                    "deliveredAt": {
                      "type": "string",
                      "x-nullable": true
                    },
                    "attempts": {
                      "type": "integer",
                      "minimum": 0,
                      "maximum": 9007199254740991
                    }
                  },
                  "required": [
                    "targetId",
                    "targetName",
                    "transport",
                    "status",
                    "deliveredAt",
                    "attempts"
                  ]
                }
              },
              "lastDeliveredAt": {
                "type": "string",
                "x-nullable": true
              },
              "canceledAt": {
                "type": "string",
                "x-nullable": true
              }
            },
            "required": [
              "id",
              "periodStart",
              "periodEnd",
              "createdAt",
              "dayCount",
              "groupId",
              "deliveries",
              "lastDeliveredAt",
              "canceledAt"
            ]
          }
        },
        "pageInfo": {
          "type": "object",
          "properties": {
            "nextCursor": {
              "type": "string",
              "x-nullable": true
            },
            "hasMore": {
              "type": "boolean"
            }
          },
          "required": [
            "nextCursor",
            "hasMore"
          ]
        }
      },
      "required": [
        "items",
        "pageInfo"
      ]
    },
    "CalculationRunResponseDto": {
      "type": "object",
      "properties": {
        "batchId": {
          "type": "string"
        },
        "calculationRunId": {
          "type": "string",
          "x-nullable": true
        },
        "engineVersion": {
          "type": "string",
          "x-nullable": true
        },
        "periodStart": {
          "type": "string",
          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
        },
        "periodEnd": {
          "type": "string",
          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
        },
        "createdAt": {
          "type": "string"
        },
        "persons": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "membershipId": {
                "type": "string"
              },
              "displayName": {
                "type": "string"
              },
              "components": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "componentCode": {
                      "type": "string"
                    },
                    "kind": {
                      "type": "string",
                      "enum": [
                        "base",
                        "additional",
                        "overtime",
                        "premium",
                        "absence",
                        "accrual",
                        "supplement",
                        "uncounted",
                        "work_equivalent"
                      ]
                    },
                    "rule": {
                      "type": "string",
                      "enum": [
                        "normal_work",
                        "additional_work",
                        "daily_overtime_50",
                        "daily_overtime_100",
                        "weekly_overtime_50",
                        "weekly_overtime_100",
                        "period_overtime_50",
                        "period_overtime_100",
                        "period_additional",
                        "period_uncompensated",
                        "sub_period_premium_100",
                        "sunday_work",
                        "holiday_work",
                        "holiday_compensation",
                        "premium_band",
                        "standby",
                        "day_absence",
                        "partial_absence",
                        "tes_time_band",
                        "tes_formula",
                        "supplement",
                        "clock_window_uncounted",
                        "type_cap_uncounted",
                        "type_cap_unpaid_first",
                        "worktime_fraction_uncounted",
                        "prep_work",
                        "wrap_work",
                        "balance_overflow_payout",
                        "balance_cut_payout",
                        "overtime_rounding"
                      ]
                    },
                    "totalMinutes": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991
                    },
                    "count": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991,
                      "x-nullable": true
                    },
                    "rateCents": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991,
                      "x-nullable": true
                    },
                    "mapped": {
                      "type": "boolean"
                    },
                    "payCode": {
                      "type": "string",
                      "x-nullable": true
                    },
                    "payCodeName": {
                      "type": "string",
                      "x-nullable": true
                    },
                    "nameFi": {
                      "type": "string",
                      "x-nullable": true
                    },
                    "nameSv": {
                      "type": "string",
                      "x-nullable": true
                    },
                    "nameEn": {
                      "type": "string",
                      "x-nullable": true
                    },
                    "contributions": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "workDate": {
                            "type": "string",
                            "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
                          },
                          "minutes": {
                            "type": "integer",
                            "minimum": -9007199254740991,
                            "maximum": 9007199254740991
                          },
                          "grain": {
                            "type": "string",
                            "enum": [
                              "day",
                              "week",
                              "period"
                            ]
                          },
                          "inputs": {
                            "type": "object",
                            "additionalProperties": {
                              "type": "number"
                            }
                          },
                          "allocation": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "properties": {
                                "dimensionCode": {
                                  "type": "string"
                                },
                                "valueCode": {
                                  "type": "string"
                                },
                                "valueName": {
                                  "type": "string"
                                },
                                "minutes": {
                                  "type": "integer",
                                  "minimum": -9007199254740991,
                                  "maximum": 9007199254740991
                                }
                              },
                              "required": [
                                "dimensionCode",
                                "valueCode",
                                "valueName",
                                "minutes"
                              ]
                            }
                          }
                        },
                        "required": [
                          "workDate",
                          "minutes",
                          "grain",
                          "inputs",
                          "allocation"
                        ]
                      }
                    }
                  },
                  "required": [
                    "componentCode",
                    "kind",
                    "rule",
                    "totalMinutes",
                    "count",
                    "rateCents",
                    "mapped",
                    "payCode",
                    "payCodeName",
                    "nameFi",
                    "nameSv",
                    "nameEn",
                    "contributions"
                  ]
                }
              }
            },
            "required": [
              "membershipId",
              "displayName",
              "components"
            ]
          }
        }
      },
      "required": [
        "batchId",
        "calculationRunId",
        "engineVersion",
        "periodStart",
        "periodEnd",
        "createdAt",
        "persons"
      ]
    },
    "CancelExportBatchDto": {
      "type": "object",
      "properties": {
        "reason": {
          "type": "string",
          "minLength": 3,
          "maxLength": 500
        }
      },
      "required": [
        "reason"
      ]
    },
    "CancelExportBatchResponseDto": {
      "type": "object",
      "properties": {
        "id": {
          "type": "string"
        },
        "canceledAt": {
          "type": "string"
        },
        "reversedDayCount": {
          "type": "integer",
          "minimum": 0,
          "maximum": 9007199254740991
        }
      },
      "required": [
        "id",
        "canceledAt",
        "reversedDayCount"
      ]
    },
    "WorkDayDetailRangeResponseDto": {
      "type": "object",
      "properties": {
        "days": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "workDate": {
                "type": "string",
                "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
              },
              "status": {
                "type": "string",
                "enum": [
                  "proposed",
                  "draft",
                  "confirmed",
                  "approved",
                  "exported"
                ]
              },
              "startMinutes": {
                "type": "integer",
                "minimum": 0,
                "maximum": 1440,
                "x-nullable": true
              },
              "endMinutes": {
                "type": "integer",
                "minimum": 1,
                "maximum": 2880,
                "x-nullable": true
              },
              "breakMinutes": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "breaks": {
                "default": [],
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "x-nullable": true
                    },
                    "startMinutes": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991
                    },
                    "endMinutes": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991
                    },
                    "breakTypeId": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "x-nullable": true
                    },
                    "paidMinutes": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991
                    }
                  },
                  "required": [
                    "id",
                    "startMinutes",
                    "endMinutes",
                    "breakTypeId",
                    "paidMinutes"
                  ]
                }
              },
              "paidBreakMinutes": {
                "default": 0,
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "workMinutes": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "creditedMinutes": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "targetMinutes": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "appliedCreditMinutes": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "uncountedMinutes": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "rawDeltaMinutes": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "balanceDeltaMinutes": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "attentionThresholdMinutes": {
                "default": 15,
                "type": "integer",
                "minimum": 0,
                "maximum": 480
              },
              "runningBalanceMinutes": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "overtimeMinutes": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "dayType": {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "string"
                  },
                  "code": {
                    "type": "string",
                    "pattern": "^[a-z][a-z0-9_]{1,49}$"
                  },
                  "nameFi": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 100
                  },
                  "nameSv": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 100
                  },
                  "nameEn": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 100
                  }
                },
                "required": [
                  "id",
                  "code",
                  "nameFi",
                  "nameSv",
                  "nameEn"
                ],
                "x-nullable": true
              },
              "absencePeriod": {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "string",
                    "format": "uuid",
                    "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                  },
                  "status": {
                    "type": "string",
                    "enum": [
                      "draft",
                      "submitted",
                      "approved",
                      "rejected",
                      "cancelled",
                      "withdrawn"
                    ]
                  },
                  "workflowMode": {
                    "type": "string",
                    "enum": [
                      "request",
                      "notification",
                      "employer_assignment"
                    ]
                  },
                  "nameFi": {
                    "type": "string"
                  },
                  "nameSv": {
                    "type": "string"
                  },
                  "nameEn": {
                    "type": "string"
                  }
                },
                "required": [
                  "id",
                  "status",
                  "workflowMode",
                  "nameFi",
                  "nameSv",
                  "nameEn"
                ],
                "x-nullable": true
              },
              "sources": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "type": {
                      "type": "string",
                      "enum": [
                        "worktime-model",
                        "calendar-event",
                        "planned-shift",
                        "punch",
                        "learned-baseline"
                      ]
                    },
                    "versionId": {
                      "type": "string"
                    },
                    "eventId": {
                      "type": "string"
                    },
                    "shiftId": {
                      "type": "string"
                    },
                    "punchSessionId": {
                      "type": "string"
                    },
                    "weekday": {
                      "type": "integer",
                      "minimum": 1,
                      "maximum": 7
                    }
                  },
                  "required": [
                    "type"
                  ]
                }
              },
              "deviations": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "type": {
                      "type": "string",
                      "enum": [
                        "overlong-day",
                        "short-day",
                        "missing-break",
                        "missing-second-break",
                        "fragmented-break",
                        "break-at-day-edge",
                        "flex-limit-exceeded",
                        "outside-flex-window",
                        "outside-allowed-window",
                        "work-on-day-off",
                        "entry-over-max-duration",
                        "insufficient-daily-rest",
                        "insufficient-weekly-rest"
                      ]
                    },
                    "deltaMinutes": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991
                    },
                    "severity": {
                      "type": "string",
                      "enum": [
                        "advisory",
                        "info"
                      ]
                    }
                  },
                  "required": [
                    "type",
                    "deltaMinutes"
                  ]
                }
              },
              "overtimeDisposition": {
                "default": "flex",
                "type": "string",
                "enum": [
                  "flex",
                  "payout",
                  "ignore",
                  "bank"
                ]
              },
              "bankAccountTypeId": {
                "type": "string",
                "default": null,
                "x-nullable": true
              },
              "entries": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "entryTypeId": {
                      "type": "string"
                    },
                    "entryTypeCode": {
                      "type": "string",
                      "pattern": "^[a-z][a-z0-9_]{1,49}$"
                    },
                    "startMinutes": {
                      "type": "integer",
                      "minimum": 0,
                      "maximum": 2879,
                      "x-nullable": true
                    },
                    "endMinutes": {
                      "type": "integer",
                      "minimum": 1,
                      "maximum": 2880,
                      "x-nullable": true
                    },
                    "durationMinutes": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991,
                      "default": null,
                      "x-nullable": true
                    },
                    "note": {
                      "type": "string",
                      "x-nullable": true
                    },
                    "billable": {
                      "type": "boolean"
                    },
                    "billingBaseMinutes": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991,
                      "default": null,
                      "x-nullable": true
                    },
                    "allocations": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "dimensionId": {
                            "type": "string"
                          },
                          "valueId": {
                            "type": "string"
                          },
                          "valueCode": {
                            "type": "string"
                          },
                          "valueName": {
                            "type": "string"
                          },
                          "weightBp": {
                            "type": "integer",
                            "minimum": -9007199254740991,
                            "maximum": 9007199254740991
                          }
                        },
                        "required": [
                          "dimensionId",
                          "valueId",
                          "valueCode",
                          "valueName",
                          "weightBp"
                        ]
                      }
                    }
                  },
                  "required": [
                    "id",
                    "entryTypeId",
                    "entryTypeCode",
                    "startMinutes",
                    "endMinutes",
                    "note",
                    "billable",
                    "allocations"
                  ]
                }
              },
              "proposedEntries": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "startMinutes": {
                      "type": "integer",
                      "minimum": 0,
                      "maximum": 1440
                    },
                    "endMinutes": {
                      "type": "integer",
                      "minimum": 1,
                      "maximum": 2880
                    },
                    "entryTypeId": {
                      "type": "string"
                    },
                    "billable": {
                      "type": "boolean"
                    },
                    "allocations": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "dimensionId": {
                            "type": "string"
                          },
                          "valueId": {
                            "type": "string"
                          },
                          "valueCode": {
                            "type": "string"
                          },
                          "valueName": {
                            "type": "string"
                          },
                          "weightBp": {
                            "default": 10000,
                            "type": "integer",
                            "minimum": -9007199254740991,
                            "maximum": 9007199254740991
                          },
                          "source": {
                            "type": "string",
                            "enum": [
                              "calendar",
                              "geofence",
                              "task",
                              "baseline",
                              "default"
                            ]
                          },
                          "confidence": {
                            "type": "string",
                            "enum": [
                              "high",
                              "medium",
                              "low"
                            ]
                          }
                        },
                        "required": [
                          "dimensionId",
                          "valueId",
                          "valueCode",
                          "valueName",
                          "source",
                          "confidence"
                        ]
                      }
                    },
                    "confidence": {
                      "type": "string",
                      "enum": [
                        "high",
                        "medium",
                        "low"
                      ]
                    }
                  },
                  "required": [
                    "startMinutes",
                    "endMinutes",
                    "entryTypeId",
                    "billable",
                    "allocations",
                    "confidence"
                  ]
                }
              },
              "expectedSource": {
                "type": "string",
                "x-nullable": true
              },
              "expectedWindow": {
                "type": "object",
                "properties": {
                  "startMinutes": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 1440
                  },
                  "endMinutes": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 1440
                  },
                  "breakMinutes": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 9007199254740991
                  }
                },
                "required": [
                  "startMinutes",
                  "endMinutes",
                  "breakMinutes"
                ],
                "x-nullable": true
              },
              "proposalDismissed": {
                "type": "boolean"
              },
              "updatedAt": {
                "type": "string",
                "default": null,
                "x-nullable": true
              },
              "returnReason": {
                "type": "string",
                "x-nullable": true
              },
              "confirmationOptional": {
                "type": "boolean"
              },
              "confirmedOnBehalf": {
                "type": "boolean"
              },
              "autoConfirmed": {
                "type": "boolean"
              },
              "confidence": {
                "type": "object",
                "properties": {
                  "level": {
                    "type": "string",
                    "enum": [
                      "high",
                      "medium",
                      "low"
                    ]
                  },
                  "reasons": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  }
                },
                "required": [
                  "level",
                  "reasons"
                ]
              },
              "supplements": {
                "default": [],
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "supplementTypeId": {
                      "type": "string"
                    },
                    "supplementTypeCode": {
                      "type": "string",
                      "pattern": "^[a-z][a-z0-9_]{1,49}$"
                    },
                    "nameFi": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 100
                    },
                    "nameSv": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 100
                    },
                    "nameEn": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 100
                    },
                    "valueKind": {
                      "type": "string",
                      "enum": [
                        "flag",
                        "count",
                        "hours",
                        "amount"
                      ]
                    },
                    "unit": {
                      "type": "string",
                      "enum": [
                        "hours",
                        "pieces",
                        "days",
                        "decimal"
                      ]
                    },
                    "exportMode": {
                      "type": "string",
                      "enum": [
                        "passthrough",
                        "tesOnly"
                      ]
                    },
                    "quantity": {
                      "type": "number"
                    },
                    "startMinutes": {
                      "type": "integer",
                      "minimum": 0,
                      "maximum": 1440,
                      "x-nullable": true
                    },
                    "endMinutes": {
                      "type": "integer",
                      "minimum": 0,
                      "maximum": 1440,
                      "x-nullable": true
                    },
                    "comment": {
                      "type": "string",
                      "x-nullable": true
                    }
                  },
                  "required": [
                    "id",
                    "supplementTypeId",
                    "supplementTypeCode",
                    "nameFi",
                    "nameSv",
                    "nameEn",
                    "valueKind",
                    "unit",
                    "exportMode",
                    "quantity",
                    "startMinutes",
                    "endMinutes",
                    "comment"
                  ]
                }
              },
              "standby": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "periodId": {
                      "type": "string"
                    },
                    "standbyType": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        },
                        "code": {
                          "type": "string",
                          "pattern": "^[a-z][a-z0-9_]{1,49}$"
                        },
                        "nameFi": {
                          "type": "string",
                          "minLength": 1,
                          "maxLength": 100
                        },
                        "nameSv": {
                          "type": "string",
                          "minLength": 1,
                          "maxLength": 100
                        },
                        "nameEn": {
                          "type": "string",
                          "minLength": 1,
                          "maxLength": 100
                        },
                        "worktimeFraction": {
                          "type": "number",
                          "minimum": 0,
                          "maximum": 1
                        }
                      },
                      "required": [
                        "id",
                        "code",
                        "nameFi",
                        "nameSv",
                        "nameEn",
                        "worktimeFraction"
                      ]
                    },
                    "startMinutes": {
                      "type": "integer",
                      "minimum": 0,
                      "maximum": 1440
                    },
                    "endMinutes": {
                      "type": "integer",
                      "minimum": 1,
                      "maximum": 1440
                    }
                  },
                  "required": [
                    "periodId",
                    "standbyType",
                    "startMinutes",
                    "endMinutes"
                  ]
                }
              },
              "governingShiftType": {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "string",
                    "format": "uuid",
                    "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                  },
                  "nameFi": {
                    "type": "string"
                  },
                  "nameSv": {
                    "type": "string"
                  },
                  "nameEn": {
                    "type": "string"
                  },
                  "shortCode": {
                    "type": "string"
                  },
                  "color": {
                    "type": "string"
                  },
                  "source": {
                    "type": "string",
                    "enum": [
                      "plan",
                      "walk-up",
                      "rule",
                      "model-default",
                      "override"
                    ]
                  }
                },
                "required": [
                  "nameFi",
                  "nameSv",
                  "nameEn",
                  "shortCode",
                  "color"
                ]
              },
              "plannedShift": {
                "type": "object",
                "properties": {
                  "startMinutes": {
                    "type": "integer",
                    "minimum": -9007199254740991,
                    "maximum": 9007199254740991,
                    "x-nullable": true
                  },
                  "endMinutes": {
                    "type": "integer",
                    "minimum": -9007199254740991,
                    "maximum": 9007199254740991,
                    "x-nullable": true
                  },
                  "breakMinutes": {
                    "type": "integer",
                    "minimum": -9007199254740991,
                    "maximum": 9007199254740991
                  },
                  "targetMinutes": {
                    "type": "integer",
                    "minimum": -9007199254740991,
                    "maximum": 9007199254740991
                  },
                  "source": {
                    "type": "string",
                    "enum": [
                      "person-shift",
                      "group-shift"
                    ]
                  },
                  "shiftType": {
                    "type": "object",
                    "properties": {
                      "nameFi": {
                        "type": "string"
                      },
                      "nameSv": {
                        "type": "string"
                      },
                      "nameEn": {
                        "type": "string"
                      },
                      "shortCode": {
                        "type": "string"
                      },
                      "color": {
                        "type": "string"
                      }
                    },
                    "required": [
                      "nameFi",
                      "nameSv",
                      "nameEn",
                      "shortCode",
                      "color"
                    ],
                    "x-nullable": true
                  }
                },
                "required": [
                  "startMinutes",
                  "endMinutes",
                  "breakMinutes",
                  "targetMinutes",
                  "source",
                  "shiftType"
                ]
              },
              "workDayId": {
                "type": "string",
                "x-nullable": true
              },
              "effectiveSettings": {
                "type": "object",
                "properties": {
                  "breakDeductionMode": {
                    "type": "string",
                    "enum": [
                      "none",
                      "minimum",
                      "fixed"
                    ]
                  },
                  "breakThresholdMinutes": {
                    "type": "number"
                  },
                  "breakThresholdBasis": {
                    "type": "string",
                    "enum": [
                      "work",
                      "span"
                    ]
                  },
                  "minBreakMinutes": {
                    "type": "number"
                  },
                  "paidCoffeeTotalMinutes": {
                    "type": "number"
                  },
                  "paidCoffeeMaxCount": {
                    "type": "number"
                  },
                  "flexWindowStartMinutes": {
                    "type": "number",
                    "x-nullable": true
                  },
                  "flexWindowEndMinutes": {
                    "type": "number",
                    "x-nullable": true
                  },
                  "dayFlexCapMinutes": {
                    "type": "number",
                    "x-nullable": true
                  },
                  "dayFlexFloorMinutes": {
                    "type": "number",
                    "x-nullable": true
                  },
                  "dailyRegularBasis": {
                    "type": "string",
                    "enum": [
                      "target",
                      "fixed"
                    ]
                  },
                  "dailyRegularFixedMinutes": {
                    "type": "number",
                    "x-nullable": true
                  },
                  "dailyOt50Minutes": {
                    "type": "number",
                    "x-nullable": true
                  },
                  "flexRoundingMinutes": {
                    "type": "number"
                  },
                  "openPunchAutoClose": {
                    "type": "string",
                    "enum": [
                      "off",
                      "boundary",
                      "planned_end"
                    ]
                  },
                  "punchRoundingMinutes": {
                    "type": "number"
                  },
                  "punchGraceStartMinutes": {
                    "type": "number"
                  },
                  "punchGraceEndMinutes": {
                    "type": "number"
                  },
                  "trace": {
                    "type": "object",
                    "additionalProperties": {
                      "type": "string"
                    }
                  }
                },
                "required": [
                  "breakDeductionMode",
                  "breakThresholdMinutes",
                  "breakThresholdBasis",
                  "minBreakMinutes",
                  "paidCoffeeTotalMinutes",
                  "paidCoffeeMaxCount",
                  "flexWindowStartMinutes",
                  "flexWindowEndMinutes",
                  "dayFlexCapMinutes",
                  "dayFlexFloorMinutes",
                  "dailyRegularBasis",
                  "dailyRegularFixedMinutes",
                  "dailyOt50Minutes",
                  "flexRoundingMinutes",
                  "openPunchAutoClose",
                  "punchRoundingMinutes",
                  "punchGraceStartMinutes",
                  "punchGraceEndMinutes",
                  "trace"
                ]
              },
              "statutoryBasis": {
                "type": "boolean"
              },
              "worktimeRegime": {
                "type": "string",
                "enum": [
                  "standard",
                  "flexwork",
                  "period"
                ]
              },
              "emergencyMinutes": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "openCorrectionRequest": {
                "type": "object",
                "properties": {
                  "reason": {
                    "type": "string"
                  },
                  "by": {
                    "type": "string"
                  },
                  "requestedAt": {
                    "type": "string"
                  }
                },
                "required": [
                  "reason",
                  "by",
                  "requestedAt"
                ],
                "default": null,
                "x-nullable": true
              },
              "shiftTypeOverride": {
                "type": "object",
                "properties": {
                  "shiftTypeId": {
                    "type": "string",
                    "format": "uuid",
                    "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                  }
                },
                "required": [
                  "shiftTypeId"
                ],
                "default": null,
                "x-nullable": true
              },
              "shiftTypeOverrideInvalid": {
                "type": "boolean"
              },
              "shiftTypeOverrideMode": {
                "type": "string",
                "enum": [
                  "off",
                  "manager",
                  "employee"
                ]
              },
              "resolutionWindows": {
                "default": [],
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "shiftTypeId": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    },
                    "nameFi": {
                      "type": "string"
                    },
                    "nameSv": {
                      "type": "string"
                    },
                    "nameEn": {
                      "type": "string"
                    },
                    "shortCode": {
                      "type": "string"
                    },
                    "color": {
                      "type": "string"
                    },
                    "startMinutes": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991
                    },
                    "endMinutes": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991
                    },
                    "priority": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991
                    }
                  },
                  "required": [
                    "shiftTypeId",
                    "nameFi",
                    "nameSv",
                    "nameEn",
                    "shortCode",
                    "color",
                    "startMinutes",
                    "endMinutes",
                    "priority"
                  ]
                }
              }
            },
            "required": [
              "workDate",
              "status",
              "startMinutes",
              "endMinutes",
              "breakMinutes",
              "workMinutes",
              "creditedMinutes",
              "targetMinutes",
              "balanceDeltaMinutes",
              "runningBalanceMinutes",
              "overtimeMinutes",
              "dayType",
              "sources",
              "deviations",
              "entries",
              "expectedSource",
              "workDayId"
            ]
          }
        }
      },
      "required": [
        "days"
      ]
    },
    "TeamBatchEntriesDto": {
      "type": "object",
      "properties": {
        "membershipIds": {
          "minItems": 1,
          "type": "array",
          "items": {
            "type": "string",
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
          }
        },
        "entries": {
          "minItems": 1,
          "maxItems": 20,
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "entryTypeId": {
                "type": "string",
                "format": "uuid",
                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
              },
              "startMinutes": {
                "type": "integer",
                "minimum": 0,
                "maximum": 2879
              },
              "endMinutes": {
                "type": "integer",
                "minimum": 1,
                "maximum": 2880
              },
              "durationMinutes": {
                "type": "integer",
                "minimum": 1,
                "maximum": 1440
              },
              "note": {
                "type": "string",
                "maxLength": 200
              },
              "billable": {
                "default": false,
                "type": "boolean"
              },
              "billingBaseMinutes": {
                "type": "integer",
                "minimum": 0,
                "maximum": 1440,
                "x-nullable": true
              },
              "allocations": {
                "default": [],
                "maxItems": 10,
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "dimensionId": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    },
                    "valueId": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    },
                    "weightBp": {
                      "default": 10000,
                      "type": "integer",
                      "minimum": 1,
                      "maximum": 10000
                    }
                  },
                  "required": [
                    "dimensionId",
                    "valueId"
                  ]
                }
              },
              "taskId": {
                "type": "string",
                "format": "uuid",
                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                "x-nullable": true
              }
            },
            "required": [
              "entryTypeId"
            ]
          }
        },
        "breaks": {
          "maxItems": 20,
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "startMinutes": {
                "type": "integer",
                "minimum": 0,
                "maximum": 2880
              },
              "endMinutes": {
                "type": "integer",
                "minimum": 1,
                "maximum": 2880
              },
              "breakTypeId": {
                "type": "string",
                "format": "uuid",
                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                "x-nullable": true
              }
            },
            "required": [
              "startMinutes",
              "endMinutes"
            ]
          }
        },
        "dayTypeId": {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
        }
      },
      "required": [
        "membershipIds"
      ]
    },
    "TeamBatchEntriesResponseDto": {
      "type": "object",
      "properties": {
        "actedCount": {
          "type": "integer",
          "minimum": 0,
          "maximum": 9007199254740991
        },
        "skippedCount": {
          "type": "integer",
          "minimum": 0,
          "maximum": 9007199254740991
        },
        "skipped": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "membershipId": {
                "type": "string",
                "format": "uuid",
                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
              },
              "code": {
                "type": "string"
              }
            },
            "required": [
              "membershipId",
              "code"
            ]
          }
        }
      },
      "required": [
        "actedCount",
        "skippedCount",
        "skipped"
      ]
    },
    "WorkDayRegisterPageResponseDto": {
      "type": "object",
      "properties": {
        "items": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "membershipId": {
                "type": "string"
              },
              "workDate": {
                "type": "string",
                "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
              },
              "status": {
                "type": "string",
                "enum": [
                  "draft",
                  "confirmed",
                  "approved",
                  "exported"
                ]
              },
              "startMinutes": {
                "type": "integer",
                "minimum": 0,
                "maximum": 1440,
                "x-nullable": true
              },
              "endMinutes": {
                "type": "integer",
                "minimum": 1,
                "maximum": 2880,
                "x-nullable": true
              },
              "breakMinutes": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "workedMinutes": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "creditedMinutes": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "dayTypeId": {
                "type": "string",
                "x-nullable": true
              },
              "expectedTargetMinutes": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991,
                "x-nullable": true
              },
              "exportBatchId": {
                "type": "string",
                "x-nullable": true
              },
              "updatedAt": {
                "type": "string",
                "format": "date-time",
                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
              }
            },
            "required": [
              "id",
              "membershipId",
              "workDate",
              "status",
              "startMinutes",
              "endMinutes",
              "breakMinutes",
              "workedMinutes",
              "creditedMinutes",
              "dayTypeId",
              "expectedTargetMinutes",
              "exportBatchId",
              "updatedAt"
            ]
          }
        },
        "pageInfo": {
          "type": "object",
          "properties": {
            "nextCursor": {
              "type": "string",
              "x-nullable": true
            },
            "hasMore": {
              "type": "boolean"
            }
          },
          "required": [
            "nextCursor",
            "hasMore"
          ]
        }
      },
      "required": [
        "items",
        "pageInfo"
      ]
    },
    "ContactListResponseDto": {
      "type": "object",
      "properties": {
        "contacts": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "customerId": {
                "type": "string"
              },
              "firstName": {
                "type": "string",
                "x-nullable": true
              },
              "lastName": {
                "type": "string",
                "x-nullable": true
              },
              "title": {
                "type": "string",
                "x-nullable": true
              },
              "email": {
                "type": "string",
                "x-nullable": true
              },
              "phone": {
                "type": "string",
                "x-nullable": true
              },
              "role": {
                "type": "string",
                "x-nullable": true
              },
              "isPrimary": {
                "type": "boolean"
              },
              "notes": {
                "type": "string",
                "x-nullable": true
              },
              "active": {
                "type": "boolean"
              },
              "anonymizedAt": {
                "type": "string",
                "x-nullable": true
              },
              "createdAt": {
                "type": "string"
              },
              "updatedAt": {
                "type": "string"
              }
            },
            "required": [
              "id",
              "customerId",
              "firstName",
              "lastName",
              "title",
              "email",
              "phone",
              "role",
              "isPrimary",
              "notes",
              "active",
              "anonymizedAt",
              "createdAt",
              "updatedAt"
            ]
          }
        }
      },
      "required": [
        "contacts"
      ]
    },
    "CreateContactDto": {
      "type": "object",
      "properties": {
        "firstName": {
          "type": "string",
          "minLength": 1,
          "maxLength": 100
        },
        "lastName": {
          "type": "string",
          "minLength": 1,
          "maxLength": 100
        },
        "title": {
          "type": "string",
          "maxLength": 100
        },
        "email": {
          "type": "string",
          "maxLength": 200,
          "format": "email",
          "pattern": "^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"
        },
        "phone": {
          "type": "string",
          "maxLength": 50
        },
        "role": {
          "type": "string",
          "maxLength": 100
        },
        "isPrimary": {
          "type": "boolean"
        },
        "notes": {
          "type": "string",
          "maxLength": 4000
        }
      },
      "required": [
        "firstName",
        "lastName"
      ]
    },
    "ContactViewDto": {
      "type": "object",
      "properties": {
        "id": {
          "type": "string"
        },
        "customerId": {
          "type": "string"
        },
        "firstName": {
          "type": "string",
          "x-nullable": true
        },
        "lastName": {
          "type": "string",
          "x-nullable": true
        },
        "title": {
          "type": "string",
          "x-nullable": true
        },
        "email": {
          "type": "string",
          "x-nullable": true
        },
        "phone": {
          "type": "string",
          "x-nullable": true
        },
        "role": {
          "type": "string",
          "x-nullable": true
        },
        "isPrimary": {
          "type": "boolean"
        },
        "notes": {
          "type": "string",
          "x-nullable": true
        },
        "active": {
          "type": "boolean"
        },
        "anonymizedAt": {
          "type": "string",
          "x-nullable": true
        },
        "createdAt": {
          "type": "string"
        },
        "updatedAt": {
          "type": "string"
        }
      },
      "required": [
        "id",
        "customerId",
        "firstName",
        "lastName",
        "title",
        "email",
        "phone",
        "role",
        "isPrimary",
        "notes",
        "active",
        "anonymizedAt",
        "createdAt",
        "updatedAt"
      ]
    },
    "UpdateContactDto": {
      "type": "object",
      "properties": {
        "firstName": {
          "type": "string",
          "minLength": 1,
          "maxLength": 100
        },
        "lastName": {
          "type": "string",
          "minLength": 1,
          "maxLength": 100
        },
        "title": {
          "type": "string",
          "maxLength": 100,
          "x-nullable": true
        },
        "email": {
          "type": "string",
          "maxLength": 200,
          "format": "email",
          "pattern": "^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$",
          "x-nullable": true
        },
        "phone": {
          "type": "string",
          "maxLength": 50,
          "x-nullable": true
        },
        "role": {
          "type": "string",
          "maxLength": 100,
          "x-nullable": true
        },
        "isPrimary": {
          "type": "boolean"
        },
        "notes": {
          "type": "string",
          "maxLength": 4000,
          "x-nullable": true
        },
        "active": {
          "type": "boolean"
        },
        "expectedUpdatedAt": {
          "type": "string"
        }
      }
    },
    "Customer360ViewDto": {
      "type": "object",
      "properties": {
        "customerId": {
          "type": "string"
        },
        "contacts": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "customerId": {
                "type": "string"
              },
              "firstName": {
                "type": "string",
                "x-nullable": true
              },
              "lastName": {
                "type": "string",
                "x-nullable": true
              },
              "title": {
                "type": "string",
                "x-nullable": true
              },
              "email": {
                "type": "string",
                "x-nullable": true
              },
              "phone": {
                "type": "string",
                "x-nullable": true
              },
              "role": {
                "type": "string",
                "x-nullable": true
              },
              "isPrimary": {
                "type": "boolean"
              },
              "notes": {
                "type": "string",
                "x-nullable": true
              },
              "active": {
                "type": "boolean"
              },
              "anonymizedAt": {
                "type": "string",
                "x-nullable": true
              },
              "createdAt": {
                "type": "string"
              },
              "updatedAt": {
                "type": "string"
              }
            },
            "required": [
              "id",
              "customerId",
              "firstName",
              "lastName",
              "title",
              "email",
              "phone",
              "role",
              "isPrimary",
              "notes",
              "active",
              "anonymizedAt",
              "createdAt",
              "updatedAt"
            ]
          }
        },
        "tags": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "name": {
                "type": "string"
              },
              "color": {
                "type": "string",
                "x-nullable": true
              }
            },
            "required": [
              "id",
              "name",
              "color"
            ]
          }
        },
        "metrics": {
          "type": "object",
          "properties": {
            "openPipelineCents": {
              "type": "integer",
              "minimum": -9007199254740991,
              "maximum": 9007199254740991
            },
            "wonCents12mo": {
              "type": "integer",
              "minimum": -9007199254740991,
              "maximum": 9007199254740991
            },
            "lostCents12mo": {
              "type": "integer",
              "minimum": -9007199254740991,
              "maximum": 9007199254740991
            },
            "invoicedLifetimeCents": {
              "type": "integer",
              "minimum": -9007199254740991,
              "maximum": 9007199254740991
            },
            "marginLifetimeCents": {
              "type": "integer",
              "minimum": -9007199254740991,
              "maximum": 9007199254740991,
              "x-nullable": true
            },
            "lastActivityAt": {
              "type": "string",
              "x-nullable": true
            },
            "arOpenCents": {
              "type": "integer",
              "minimum": -9007199254740991,
              "maximum": 9007199254740991,
              "x-nullable": true
            },
            "arOverdueCents": {
              "type": "integer",
              "minimum": -9007199254740991,
              "maximum": 9007199254740991,
              "x-nullable": true
            },
            "lifetimeMinutes": {
              "type": "integer",
              "minimum": -9007199254740991,
              "maximum": 9007199254740991,
              "x-nullable": true
            }
          },
          "required": [
            "openPipelineCents",
            "wonCents12mo",
            "lostCents12mo",
            "invoicedLifetimeCents",
            "marginLifetimeCents",
            "lastActivityAt",
            "arOpenCents",
            "arOverdueCents",
            "lifetimeMinutes"
          ]
        },
        "openDeals": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "customerId": {
                "type": "string"
              },
              "contactId": {
                "type": "string",
                "x-nullable": true
              },
              "pipelineId": {
                "type": "string"
              },
              "stageId": {
                "type": "string"
              },
              "title": {
                "type": "string"
              },
              "valueCents": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991,
                "x-nullable": true
              },
              "probabilityPercent": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991,
                "x-nullable": true
              },
              "effectiveProbabilityPercent": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "expectedCloseDate": {
                "type": "string",
                "x-nullable": true
              },
              "ownerMembershipId": {
                "type": "string"
              },
              "ownerName": {
                "type": "string",
                "x-nullable": true
              },
              "customerName": {
                "type": "string",
                "x-nullable": true
              },
              "status": {
                "type": "string",
                "enum": [
                  "open",
                  "won",
                  "lost"
                ]
              },
              "lostReasonId": {
                "type": "string",
                "x-nullable": true
              },
              "lostComment": {
                "type": "string",
                "x-nullable": true
              },
              "wonAt": {
                "type": "string",
                "x-nullable": true
              },
              "lostAt": {
                "type": "string",
                "x-nullable": true
              },
              "sourceLeadId": {
                "type": "string",
                "x-nullable": true
              },
              "projectId": {
                "type": "string",
                "x-nullable": true
              },
              "projectName": {
                "type": "string",
                "x-nullable": true
              },
              "nextActivityAt": {
                "type": "string",
                "x-nullable": true
              },
              "stageEnteredAt": {
                "type": "string"
              },
              "stale": {
                "type": "boolean"
              },
              "tagIds": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "createdAt": {
                "type": "string"
              },
              "updatedAt": {
                "type": "string"
              }
            },
            "required": [
              "id",
              "customerId",
              "contactId",
              "pipelineId",
              "stageId",
              "title",
              "valueCents",
              "probabilityPercent",
              "effectiveProbabilityPercent",
              "expectedCloseDate",
              "ownerMembershipId",
              "ownerName",
              "customerName",
              "status",
              "lostReasonId",
              "lostComment",
              "wonAt",
              "lostAt",
              "sourceLeadId",
              "projectId",
              "projectName",
              "nextActivityAt",
              "stageEnteredAt",
              "stale",
              "tagIds",
              "createdAt",
              "updatedAt"
            ]
          }
        },
        "recentActivities": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "customerId": {
                "type": "string",
                "x-nullable": true
              },
              "customerName": {
                "type": "string",
                "x-nullable": true
              },
              "contactId": {
                "type": "string",
                "x-nullable": true
              },
              "dealId": {
                "type": "string",
                "x-nullable": true
              },
              "leadId": {
                "type": "string",
                "x-nullable": true
              },
              "projectId": {
                "type": "string",
                "x-nullable": true
              },
              "projectName": {
                "type": "string",
                "x-nullable": true
              },
              "type": {
                "type": "string",
                "enum": [
                  "call",
                  "meeting",
                  "email",
                  "note",
                  "task"
                ]
              },
              "subject": {
                "type": "string"
              },
              "body": {
                "type": "string",
                "x-nullable": true
              },
              "dueAt": {
                "type": "string",
                "x-nullable": true
              },
              "doneAt": {
                "type": "string",
                "x-nullable": true
              },
              "ownerMembershipId": {
                "type": "string"
              },
              "createdByMembershipId": {
                "type": "string",
                "x-nullable": true
              },
              "createdAt": {
                "type": "string"
              },
              "updatedAt": {
                "type": "string"
              }
            },
            "required": [
              "id",
              "customerId",
              "customerName",
              "contactId",
              "dealId",
              "leadId",
              "projectId",
              "projectName",
              "type",
              "subject",
              "body",
              "dueAt",
              "doneAt",
              "ownerMembershipId",
              "createdByMembershipId",
              "createdAt",
              "updatedAt"
            ]
          }
        },
        "timelineItems": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "type": {
                "type": "string",
                "enum": [
                  "quote_sent",
                  "quote_accepted",
                  "quote_declined",
                  "deal_won",
                  "deal_lost",
                  "deal_reopened",
                  "project_status"
                ]
              },
              "at": {
                "type": "string"
              },
              "title": {
                "type": "string"
              },
              "amountCents": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991,
                "x-nullable": true
              }
            },
            "required": [
              "id",
              "type",
              "at",
              "title",
              "amountCents"
            ]
          }
        }
      },
      "required": [
        "customerId",
        "contacts",
        "tags",
        "metrics",
        "openDeals",
        "recentActivities",
        "timelineItems"
      ]
    },
    "LeadPageResponseDto": {
      "type": "object",
      "properties": {
        "items": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "title": {
                "type": "string"
              },
              "companyName": {
                "type": "string",
                "x-nullable": true
              },
              "businessId": {
                "type": "string",
                "x-nullable": true
              },
              "personName": {
                "type": "string",
                "x-nullable": true
              },
              "email": {
                "type": "string",
                "x-nullable": true
              },
              "phone": {
                "type": "string",
                "x-nullable": true
              },
              "source": {
                "type": "string",
                "enum": [
                  "manual",
                  "intake",
                  "import",
                  "website",
                  "referral",
                  "other"
                ]
              },
              "notes": {
                "type": "string",
                "x-nullable": true
              },
              "ownerMembershipId": {
                "type": "string",
                "x-nullable": true
              },
              "status": {
                "type": "string",
                "enum": [
                  "new",
                  "working",
                  "converted",
                  "discarded"
                ]
              },
              "discardReason": {
                "type": "string",
                "x-nullable": true
              },
              "convertedDealId": {
                "type": "string",
                "x-nullable": true
              },
              "convertedCustomerId": {
                "type": "string",
                "x-nullable": true
              },
              "anonymizedAt": {
                "type": "string",
                "x-nullable": true
              },
              "createdAt": {
                "type": "string"
              },
              "updatedAt": {
                "type": "string"
              }
            },
            "required": [
              "id",
              "title",
              "companyName",
              "businessId",
              "personName",
              "email",
              "phone",
              "source",
              "notes",
              "ownerMembershipId",
              "status",
              "discardReason",
              "convertedDealId",
              "convertedCustomerId",
              "anonymizedAt",
              "createdAt",
              "updatedAt"
            ]
          }
        },
        "pageInfo": {
          "type": "object",
          "properties": {
            "nextCursor": {
              "type": "string",
              "x-nullable": true
            },
            "hasMore": {
              "type": "boolean"
            }
          },
          "required": [
            "nextCursor",
            "hasMore"
          ]
        }
      },
      "required": [
        "items",
        "pageInfo"
      ]
    },
    "CreateLeadDto": {
      "type": "object",
      "properties": {
        "title": {
          "type": "string",
          "minLength": 1,
          "maxLength": 200
        },
        "companyName": {
          "type": "string",
          "maxLength": 200
        },
        "businessId": {
          "type": "string",
          "maxLength": 20
        },
        "personName": {
          "type": "string",
          "maxLength": 200
        },
        "email": {
          "type": "string",
          "maxLength": 200,
          "format": "email",
          "pattern": "^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"
        },
        "phone": {
          "type": "string",
          "maxLength": 50
        },
        "source": {
          "default": "manual",
          "type": "string",
          "enum": [
            "manual",
            "intake",
            "import",
            "website",
            "referral",
            "other"
          ]
        },
        "notes": {
          "type": "string",
          "maxLength": 4000
        },
        "ownerMembershipId": {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
        }
      },
      "required": [
        "title"
      ]
    },
    "LeadViewDto": {
      "type": "object",
      "properties": {
        "id": {
          "type": "string"
        },
        "title": {
          "type": "string"
        },
        "companyName": {
          "type": "string",
          "x-nullable": true
        },
        "businessId": {
          "type": "string",
          "x-nullable": true
        },
        "personName": {
          "type": "string",
          "x-nullable": true
        },
        "email": {
          "type": "string",
          "x-nullable": true
        },
        "phone": {
          "type": "string",
          "x-nullable": true
        },
        "source": {
          "type": "string",
          "enum": [
            "manual",
            "intake",
            "import",
            "website",
            "referral",
            "other"
          ]
        },
        "notes": {
          "type": "string",
          "x-nullable": true
        },
        "ownerMembershipId": {
          "type": "string",
          "x-nullable": true
        },
        "status": {
          "type": "string",
          "enum": [
            "new",
            "working",
            "converted",
            "discarded"
          ]
        },
        "discardReason": {
          "type": "string",
          "x-nullable": true
        },
        "convertedDealId": {
          "type": "string",
          "x-nullable": true
        },
        "convertedCustomerId": {
          "type": "string",
          "x-nullable": true
        },
        "anonymizedAt": {
          "type": "string",
          "x-nullable": true
        },
        "createdAt": {
          "type": "string"
        },
        "updatedAt": {
          "type": "string"
        }
      },
      "required": [
        "id",
        "title",
        "companyName",
        "businessId",
        "personName",
        "email",
        "phone",
        "source",
        "notes",
        "ownerMembershipId",
        "status",
        "discardReason",
        "convertedDealId",
        "convertedCustomerId",
        "anonymizedAt",
        "createdAt",
        "updatedAt"
      ]
    },
    "UpdateLeadDto": {
      "type": "object",
      "properties": {
        "title": {
          "type": "string",
          "minLength": 1,
          "maxLength": 200
        },
        "companyName": {
          "type": "string",
          "maxLength": 200,
          "x-nullable": true
        },
        "businessId": {
          "type": "string",
          "maxLength": 20,
          "x-nullable": true
        },
        "personName": {
          "type": "string",
          "maxLength": 200,
          "x-nullable": true
        },
        "email": {
          "type": "string",
          "maxLength": 200,
          "format": "email",
          "pattern": "^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$",
          "x-nullable": true
        },
        "phone": {
          "type": "string",
          "maxLength": 50,
          "x-nullable": true
        },
        "source": {
          "type": "string",
          "enum": [
            "manual",
            "intake",
            "import",
            "website",
            "referral",
            "other"
          ]
        },
        "notes": {
          "type": "string",
          "maxLength": 4000,
          "x-nullable": true
        },
        "ownerMembershipId": {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
          "x-nullable": true
        },
        "expectedUpdatedAt": {
          "type": "string"
        }
      }
    },
    "ConvertLeadDto": {
      "type": "object",
      "properties": {
        "customerId": {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
        },
        "newCustomerCode": {
          "type": "string",
          "pattern": "^[a-z0-9][a-z0-9_-]{0,49}$"
        },
        "newCustomerName": {
          "type": "string",
          "minLength": 1,
          "maxLength": 200
        },
        "pipelineId": {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
        },
        "dealTitle": {
          "type": "string",
          "minLength": 1,
          "maxLength": 200
        },
        "valueCents": {
          "type": "integer",
          "minimum": 0,
          "maximum": 2000000000
        },
        "ownerMembershipId": {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
        }
      },
      "required": [
        "dealTitle"
      ]
    },
    "ConvertLeadResponseDto": {
      "type": "object",
      "properties": {
        "customerId": {
          "type": "string"
        },
        "contactId": {
          "type": "string",
          "x-nullable": true
        },
        "dealId": {
          "type": "string"
        }
      },
      "required": [
        "customerId",
        "contactId",
        "dealId"
      ]
    },
    "PipelineListResponseDto": {
      "type": "object",
      "properties": {
        "pipelines": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "name": {
                "type": "string"
              },
              "sortOrder": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "active": {
                "type": "boolean"
              },
              "isDefault": {
                "type": "boolean"
              },
              "stages": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "pipelineId": {
                      "type": "string"
                    },
                    "name": {
                      "type": "string"
                    },
                    "sortOrder": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991
                    },
                    "probabilityPercent": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991
                    },
                    "staleAfterDays": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991,
                      "x-nullable": true
                    }
                  },
                  "required": [
                    "id",
                    "pipelineId",
                    "name",
                    "sortOrder",
                    "probabilityPercent",
                    "staleAfterDays"
                  ]
                }
              }
            },
            "required": [
              "id",
              "name",
              "sortOrder",
              "active",
              "isDefault",
              "stages"
            ]
          }
        }
      },
      "required": [
        "pipelines"
      ]
    },
    "DealPageResponseDto": {
      "type": "object",
      "properties": {
        "items": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "customerId": {
                "type": "string"
              },
              "contactId": {
                "type": "string",
                "x-nullable": true
              },
              "pipelineId": {
                "type": "string"
              },
              "stageId": {
                "type": "string"
              },
              "title": {
                "type": "string"
              },
              "valueCents": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991,
                "x-nullable": true
              },
              "probabilityPercent": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991,
                "x-nullable": true
              },
              "effectiveProbabilityPercent": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "expectedCloseDate": {
                "type": "string",
                "x-nullable": true
              },
              "ownerMembershipId": {
                "type": "string"
              },
              "ownerName": {
                "type": "string",
                "x-nullable": true
              },
              "customerName": {
                "type": "string",
                "x-nullable": true
              },
              "status": {
                "type": "string",
                "enum": [
                  "open",
                  "won",
                  "lost"
                ]
              },
              "lostReasonId": {
                "type": "string",
                "x-nullable": true
              },
              "lostComment": {
                "type": "string",
                "x-nullable": true
              },
              "wonAt": {
                "type": "string",
                "x-nullable": true
              },
              "lostAt": {
                "type": "string",
                "x-nullable": true
              },
              "sourceLeadId": {
                "type": "string",
                "x-nullable": true
              },
              "projectId": {
                "type": "string",
                "x-nullable": true
              },
              "projectName": {
                "type": "string",
                "x-nullable": true
              },
              "nextActivityAt": {
                "type": "string",
                "x-nullable": true
              },
              "stageEnteredAt": {
                "type": "string"
              },
              "stale": {
                "type": "boolean"
              },
              "tagIds": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "createdAt": {
                "type": "string"
              },
              "updatedAt": {
                "type": "string"
              }
            },
            "required": [
              "id",
              "customerId",
              "contactId",
              "pipelineId",
              "stageId",
              "title",
              "valueCents",
              "probabilityPercent",
              "effectiveProbabilityPercent",
              "expectedCloseDate",
              "ownerMembershipId",
              "ownerName",
              "customerName",
              "status",
              "lostReasonId",
              "lostComment",
              "wonAt",
              "lostAt",
              "sourceLeadId",
              "projectId",
              "projectName",
              "nextActivityAt",
              "stageEnteredAt",
              "stale",
              "tagIds",
              "createdAt",
              "updatedAt"
            ]
          }
        },
        "pageInfo": {
          "type": "object",
          "properties": {
            "nextCursor": {
              "type": "string",
              "x-nullable": true
            },
            "hasMore": {
              "type": "boolean"
            }
          },
          "required": [
            "nextCursor",
            "hasMore"
          ]
        }
      },
      "required": [
        "items",
        "pageInfo"
      ]
    },
    "CreateDealDto": {
      "type": "object",
      "properties": {
        "customerId": {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
        },
        "contactId": {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
        },
        "pipelineId": {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
        },
        "stageId": {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
        },
        "title": {
          "type": "string",
          "minLength": 1,
          "maxLength": 200
        },
        "valueCents": {
          "type": "integer",
          "minimum": 0,
          "maximum": 2000000000
        },
        "probabilityPercent": {
          "type": "integer",
          "minimum": 0,
          "maximum": 100
        },
        "expectedCloseDate": {
          "type": "string",
          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
        },
        "ownerMembershipId": {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
        },
        "tagIds": {
          "maxItems": 50,
          "type": "array",
          "items": {
            "type": "string",
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
          }
        }
      },
      "required": [
        "customerId",
        "title"
      ]
    },
    "DealViewDto": {
      "type": "object",
      "properties": {
        "id": {
          "type": "string"
        },
        "customerId": {
          "type": "string"
        },
        "contactId": {
          "type": "string",
          "x-nullable": true
        },
        "pipelineId": {
          "type": "string"
        },
        "stageId": {
          "type": "string"
        },
        "title": {
          "type": "string"
        },
        "valueCents": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991,
          "x-nullable": true
        },
        "probabilityPercent": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991,
          "x-nullable": true
        },
        "effectiveProbabilityPercent": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991
        },
        "expectedCloseDate": {
          "type": "string",
          "x-nullable": true
        },
        "ownerMembershipId": {
          "type": "string"
        },
        "ownerName": {
          "type": "string",
          "x-nullable": true
        },
        "customerName": {
          "type": "string",
          "x-nullable": true
        },
        "status": {
          "type": "string",
          "enum": [
            "open",
            "won",
            "lost"
          ]
        },
        "lostReasonId": {
          "type": "string",
          "x-nullable": true
        },
        "lostComment": {
          "type": "string",
          "x-nullable": true
        },
        "wonAt": {
          "type": "string",
          "x-nullable": true
        },
        "lostAt": {
          "type": "string",
          "x-nullable": true
        },
        "sourceLeadId": {
          "type": "string",
          "x-nullable": true
        },
        "projectId": {
          "type": "string",
          "x-nullable": true
        },
        "projectName": {
          "type": "string",
          "x-nullable": true
        },
        "nextActivityAt": {
          "type": "string",
          "x-nullable": true
        },
        "stageEnteredAt": {
          "type": "string"
        },
        "stale": {
          "type": "boolean"
        },
        "tagIds": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "createdAt": {
          "type": "string"
        },
        "updatedAt": {
          "type": "string"
        }
      },
      "required": [
        "id",
        "customerId",
        "contactId",
        "pipelineId",
        "stageId",
        "title",
        "valueCents",
        "probabilityPercent",
        "effectiveProbabilityPercent",
        "expectedCloseDate",
        "ownerMembershipId",
        "ownerName",
        "customerName",
        "status",
        "lostReasonId",
        "lostComment",
        "wonAt",
        "lostAt",
        "sourceLeadId",
        "projectId",
        "projectName",
        "nextActivityAt",
        "stageEnteredAt",
        "stale",
        "tagIds",
        "createdAt",
        "updatedAt"
      ]
    },
    "UpdateDealDto": {
      "type": "object",
      "properties": {
        "contactId": {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
          "x-nullable": true
        },
        "title": {
          "type": "string",
          "minLength": 1,
          "maxLength": 200
        },
        "valueCents": {
          "type": "integer",
          "minimum": 0,
          "maximum": 2000000000,
          "x-nullable": true
        },
        "probabilityPercent": {
          "type": "integer",
          "minimum": 0,
          "maximum": 100,
          "x-nullable": true
        },
        "expectedCloseDate": {
          "type": "string",
          "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
          "x-nullable": true
        },
        "ownerMembershipId": {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
        },
        "expectedUpdatedAt": {
          "type": "string"
        }
      }
    },
    "MoveDealStageDto": {
      "type": "object",
      "properties": {
        "stageId": {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
        },
        "beforeDealId": {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
          "x-nullable": true
        },
        "expectedUpdatedAt": {
          "type": "string"
        }
      },
      "required": [
        "stageId"
      ]
    },
    "WinDealDto": {
      "type": "object",
      "properties": {
        "comment": {
          "type": "string",
          "maxLength": 1000
        },
        "linkProjectId": {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
        },
        "expectedUpdatedAt": {
          "type": "string"
        }
      }
    },
    "LoseDealDto": {
      "type": "object",
      "properties": {
        "lostReasonId": {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
        },
        "lostComment": {
          "type": "string",
          "maxLength": 1000
        },
        "expectedUpdatedAt": {
          "type": "string"
        }
      },
      "required": [
        "lostReasonId"
      ]
    },
    "BoardViewDto": {
      "type": "object",
      "properties": {
        "pipeline": {
          "type": "object",
          "properties": {
            "id": {
              "type": "string"
            },
            "name": {
              "type": "string"
            },
            "sortOrder": {
              "type": "integer",
              "minimum": -9007199254740991,
              "maximum": 9007199254740991
            },
            "active": {
              "type": "boolean"
            },
            "isDefault": {
              "type": "boolean"
            },
            "stages": {
              "type": "array",
              "items": {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "string"
                  },
                  "pipelineId": {
                    "type": "string"
                  },
                  "name": {
                    "type": "string"
                  },
                  "sortOrder": {
                    "type": "integer",
                    "minimum": -9007199254740991,
                    "maximum": 9007199254740991
                  },
                  "probabilityPercent": {
                    "type": "integer",
                    "minimum": -9007199254740991,
                    "maximum": 9007199254740991
                  },
                  "staleAfterDays": {
                    "type": "integer",
                    "minimum": -9007199254740991,
                    "maximum": 9007199254740991,
                    "x-nullable": true
                  }
                },
                "required": [
                  "id",
                  "pipelineId",
                  "name",
                  "sortOrder",
                  "probabilityPercent",
                  "staleAfterDays"
                ]
              }
            }
          },
          "required": [
            "id",
            "name",
            "sortOrder",
            "active",
            "isDefault",
            "stages"
          ]
        },
        "columns": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "stage": {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "string"
                  },
                  "pipelineId": {
                    "type": "string"
                  },
                  "name": {
                    "type": "string"
                  },
                  "sortOrder": {
                    "type": "integer",
                    "minimum": -9007199254740991,
                    "maximum": 9007199254740991
                  },
                  "probabilityPercent": {
                    "type": "integer",
                    "minimum": -9007199254740991,
                    "maximum": 9007199254740991
                  },
                  "staleAfterDays": {
                    "type": "integer",
                    "minimum": -9007199254740991,
                    "maximum": 9007199254740991,
                    "x-nullable": true
                  }
                },
                "required": [
                  "id",
                  "pipelineId",
                  "name",
                  "sortOrder",
                  "probabilityPercent",
                  "staleAfterDays"
                ]
              },
              "deals": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "customerId": {
                      "type": "string"
                    },
                    "contactId": {
                      "type": "string",
                      "x-nullable": true
                    },
                    "pipelineId": {
                      "type": "string"
                    },
                    "stageId": {
                      "type": "string"
                    },
                    "title": {
                      "type": "string"
                    },
                    "valueCents": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991,
                      "x-nullable": true
                    },
                    "probabilityPercent": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991,
                      "x-nullable": true
                    },
                    "effectiveProbabilityPercent": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991
                    },
                    "expectedCloseDate": {
                      "type": "string",
                      "x-nullable": true
                    },
                    "ownerMembershipId": {
                      "type": "string"
                    },
                    "ownerName": {
                      "type": "string",
                      "x-nullable": true
                    },
                    "customerName": {
                      "type": "string"
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "open",
                        "won",
                        "lost"
                      ]
                    },
                    "lostReasonId": {
                      "type": "string",
                      "x-nullable": true
                    },
                    "lostComment": {
                      "type": "string",
                      "x-nullable": true
                    },
                    "wonAt": {
                      "type": "string",
                      "x-nullable": true
                    },
                    "lostAt": {
                      "type": "string",
                      "x-nullable": true
                    },
                    "sourceLeadId": {
                      "type": "string",
                      "x-nullable": true
                    },
                    "projectId": {
                      "type": "string",
                      "x-nullable": true
                    },
                    "projectName": {
                      "type": "string",
                      "x-nullable": true
                    },
                    "nextActivityAt": {
                      "type": "string",
                      "x-nullable": true
                    },
                    "stageEnteredAt": {
                      "type": "string"
                    },
                    "stale": {
                      "type": "boolean"
                    },
                    "tagIds": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "createdAt": {
                      "type": "string"
                    },
                    "updatedAt": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "id",
                    "customerId",
                    "contactId",
                    "pipelineId",
                    "stageId",
                    "title",
                    "valueCents",
                    "probabilityPercent",
                    "effectiveProbabilityPercent",
                    "expectedCloseDate",
                    "ownerMembershipId",
                    "ownerName",
                    "customerName",
                    "status",
                    "lostReasonId",
                    "lostComment",
                    "wonAt",
                    "lostAt",
                    "sourceLeadId",
                    "projectId",
                    "projectName",
                    "nextActivityAt",
                    "stageEnteredAt",
                    "stale",
                    "tagIds",
                    "createdAt",
                    "updatedAt"
                  ]
                }
              },
              "dealCount": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "valueCents": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "weightedValueCents": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "staleCount": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              }
            },
            "required": [
              "stage",
              "deals",
              "dealCount",
              "valueCents",
              "weightedValueCents",
              "staleCount"
            ]
          }
        }
      },
      "required": [
        "pipeline",
        "columns"
      ]
    },
    "ActivityPageResponseDto": {
      "type": "object",
      "properties": {
        "items": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "customerId": {
                "type": "string",
                "x-nullable": true
              },
              "customerName": {
                "type": "string",
                "x-nullable": true
              },
              "contactId": {
                "type": "string",
                "x-nullable": true
              },
              "dealId": {
                "type": "string",
                "x-nullable": true
              },
              "leadId": {
                "type": "string",
                "x-nullable": true
              },
              "projectId": {
                "type": "string",
                "x-nullable": true
              },
              "projectName": {
                "type": "string",
                "x-nullable": true
              },
              "type": {
                "type": "string",
                "enum": [
                  "call",
                  "meeting",
                  "email",
                  "note",
                  "task"
                ]
              },
              "subject": {
                "type": "string"
              },
              "body": {
                "type": "string",
                "x-nullable": true
              },
              "dueAt": {
                "type": "string",
                "x-nullable": true
              },
              "doneAt": {
                "type": "string",
                "x-nullable": true
              },
              "ownerMembershipId": {
                "type": "string"
              },
              "createdByMembershipId": {
                "type": "string",
                "x-nullable": true
              },
              "createdAt": {
                "type": "string"
              },
              "updatedAt": {
                "type": "string"
              }
            },
            "required": [
              "id",
              "customerId",
              "customerName",
              "contactId",
              "dealId",
              "leadId",
              "projectId",
              "projectName",
              "type",
              "subject",
              "body",
              "dueAt",
              "doneAt",
              "ownerMembershipId",
              "createdByMembershipId",
              "createdAt",
              "updatedAt"
            ]
          }
        },
        "pageInfo": {
          "type": "object",
          "properties": {
            "nextCursor": {
              "type": "string",
              "x-nullable": true
            },
            "hasMore": {
              "type": "boolean"
            }
          },
          "required": [
            "nextCursor",
            "hasMore"
          ]
        }
      },
      "required": [
        "items",
        "pageInfo"
      ]
    },
    "ActivityAgendaResponseDto": {
      "type": "object",
      "properties": {
        "overdue": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "customerId": {
                "type": "string",
                "x-nullable": true
              },
              "customerName": {
                "type": "string",
                "x-nullable": true
              },
              "contactId": {
                "type": "string",
                "x-nullable": true
              },
              "dealId": {
                "type": "string",
                "x-nullable": true
              },
              "leadId": {
                "type": "string",
                "x-nullable": true
              },
              "projectId": {
                "type": "string",
                "x-nullable": true
              },
              "projectName": {
                "type": "string",
                "x-nullable": true
              },
              "type": {
                "type": "string",
                "enum": [
                  "call",
                  "meeting",
                  "email",
                  "note",
                  "task"
                ]
              },
              "subject": {
                "type": "string"
              },
              "body": {
                "type": "string",
                "x-nullable": true
              },
              "dueAt": {
                "type": "string",
                "x-nullable": true
              },
              "doneAt": {
                "type": "string",
                "x-nullable": true
              },
              "ownerMembershipId": {
                "type": "string"
              },
              "createdByMembershipId": {
                "type": "string",
                "x-nullable": true
              },
              "createdAt": {
                "type": "string"
              },
              "updatedAt": {
                "type": "string"
              }
            },
            "required": [
              "id",
              "customerId",
              "customerName",
              "contactId",
              "dealId",
              "leadId",
              "projectId",
              "projectName",
              "type",
              "subject",
              "body",
              "dueAt",
              "doneAt",
              "ownerMembershipId",
              "createdByMembershipId",
              "createdAt",
              "updatedAt"
            ]
          }
        },
        "today": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "customerId": {
                "type": "string",
                "x-nullable": true
              },
              "customerName": {
                "type": "string",
                "x-nullable": true
              },
              "contactId": {
                "type": "string",
                "x-nullable": true
              },
              "dealId": {
                "type": "string",
                "x-nullable": true
              },
              "leadId": {
                "type": "string",
                "x-nullable": true
              },
              "projectId": {
                "type": "string",
                "x-nullable": true
              },
              "projectName": {
                "type": "string",
                "x-nullable": true
              },
              "type": {
                "type": "string",
                "enum": [
                  "call",
                  "meeting",
                  "email",
                  "note",
                  "task"
                ]
              },
              "subject": {
                "type": "string"
              },
              "body": {
                "type": "string",
                "x-nullable": true
              },
              "dueAt": {
                "type": "string",
                "x-nullable": true
              },
              "doneAt": {
                "type": "string",
                "x-nullable": true
              },
              "ownerMembershipId": {
                "type": "string"
              },
              "createdByMembershipId": {
                "type": "string",
                "x-nullable": true
              },
              "createdAt": {
                "type": "string"
              },
              "updatedAt": {
                "type": "string"
              }
            },
            "required": [
              "id",
              "customerId",
              "customerName",
              "contactId",
              "dealId",
              "leadId",
              "projectId",
              "projectName",
              "type",
              "subject",
              "body",
              "dueAt",
              "doneAt",
              "ownerMembershipId",
              "createdByMembershipId",
              "createdAt",
              "updatedAt"
            ]
          }
        }
      },
      "required": [
        "overdue",
        "today"
      ]
    },
    "CreateActivityDto": {
      "type": "object",
      "properties": {
        "customerId": {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
        },
        "contactId": {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
        },
        "dealId": {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
        },
        "leadId": {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
        },
        "projectId": {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
        },
        "type": {
          "type": "string",
          "enum": [
            "call",
            "meeting",
            "email",
            "note",
            "task"
          ]
        },
        "subject": {
          "type": "string",
          "minLength": 1,
          "maxLength": 200
        },
        "body": {
          "type": "string",
          "maxLength": 8000
        },
        "dueAt": {
          "type": "string",
          "format": "date-time",
          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
        },
        "ownerMembershipId": {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
        }
      },
      "required": [
        "type",
        "subject"
      ]
    },
    "ActivityViewDto": {
      "type": "object",
      "properties": {
        "id": {
          "type": "string"
        },
        "customerId": {
          "type": "string",
          "x-nullable": true
        },
        "customerName": {
          "type": "string",
          "x-nullable": true
        },
        "contactId": {
          "type": "string",
          "x-nullable": true
        },
        "dealId": {
          "type": "string",
          "x-nullable": true
        },
        "leadId": {
          "type": "string",
          "x-nullable": true
        },
        "projectId": {
          "type": "string",
          "x-nullable": true
        },
        "projectName": {
          "type": "string",
          "x-nullable": true
        },
        "type": {
          "type": "string",
          "enum": [
            "call",
            "meeting",
            "email",
            "note",
            "task"
          ]
        },
        "subject": {
          "type": "string"
        },
        "body": {
          "type": "string",
          "x-nullable": true
        },
        "dueAt": {
          "type": "string",
          "x-nullable": true
        },
        "doneAt": {
          "type": "string",
          "x-nullable": true
        },
        "ownerMembershipId": {
          "type": "string"
        },
        "createdByMembershipId": {
          "type": "string",
          "x-nullable": true
        },
        "createdAt": {
          "type": "string"
        },
        "updatedAt": {
          "type": "string"
        }
      },
      "required": [
        "id",
        "customerId",
        "customerName",
        "contactId",
        "dealId",
        "leadId",
        "projectId",
        "projectName",
        "type",
        "subject",
        "body",
        "dueAt",
        "doneAt",
        "ownerMembershipId",
        "createdByMembershipId",
        "createdAt",
        "updatedAt"
      ]
    },
    "ToggleActivityDoneDto": {
      "type": "object",
      "properties": {
        "done": {
          "type": "boolean"
        }
      },
      "required": [
        "done"
      ]
    },
    "ApiKeyListResponseDto": {
      "type": "object",
      "properties": {
        "keys": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "name": {
                "type": "string"
              },
              "kind": {
                "type": "string",
                "enum": [
                  "personal",
                  "service"
                ]
              },
              "ownerMembershipId": {
                "type": "string"
              },
              "ownerName": {
                "type": "string",
                "x-nullable": true
              },
              "ownerActive": {
                "type": "boolean",
                "x-nullable": true
              },
              "description": {
                "type": "string",
                "x-nullable": true
              },
              "tokenPrefix": {
                "type": "string"
              },
              "capabilities": {
                "type": "array",
                "items": {
                  "type": "string",
                  "enum": [
                    "worktime.supervise",
                    "scheduling.plan",
                    "scheduling.admin",
                    "projects.manage",
                    "projects.read",
                    "crm.use",
                    "crm.admin",
                    "hr.manage",
                    "hr.record",
                    "payroll.run",
                    "reports.team",
                    "members.manage",
                    "comms.announce",
                    "integrations.manage",
                    "org.admin"
                  ]
                }
              },
              "readOnly": {
                "type": "boolean"
              },
              "expiresAt": {
                "type": "string",
                "format": "date-time",
                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$",
                "x-nullable": true
              },
              "requests7d": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "errors7d": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "createdAt": {
                "type": "string",
                "format": "date-time",
                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
              },
              "lastUsedAt": {
                "type": "string",
                "format": "date-time",
                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$",
                "x-nullable": true
              },
              "revokedAt": {
                "type": "string",
                "format": "date-time",
                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$",
                "x-nullable": true
              }
            },
            "required": [
              "id",
              "name",
              "kind",
              "ownerMembershipId",
              "ownerName",
              "ownerActive",
              "description",
              "tokenPrefix",
              "capabilities",
              "readOnly",
              "expiresAt",
              "requests7d",
              "errors7d",
              "createdAt",
              "lastUsedAt",
              "revokedAt"
            ]
          }
        }
      },
      "required": [
        "keys"
      ]
    },
    "CreateServiceApiKeyDto": {
      "type": "object",
      "properties": {
        "name": {
          "type": "string",
          "minLength": 1,
          "maxLength": 100
        },
        "description": {
          "type": "string",
          "maxLength": 300
        },
        "ownerMembershipId": {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
        },
        "capabilities": {
          "maxItems": 20,
          "type": "array",
          "items": {
            "type": "string",
            "enum": [
              "worktime.supervise",
              "scheduling.plan",
              "scheduling.admin",
              "projects.manage",
              "projects.read",
              "crm.use",
              "crm.admin",
              "hr.manage",
              "hr.record",
              "payroll.run",
              "reports.team",
              "members.manage",
              "comms.announce",
              "integrations.manage",
              "org.admin"
            ]
          }
        },
        "expiresAt": {
          "type": "string",
          "format": "date-time",
          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$",
          "x-nullable": true
        },
        "readOnly": {
          "type": "boolean"
        }
      },
      "required": [
        "name",
        "ownerMembershipId",
        "capabilities"
      ]
    },
    "CreateApiKeyResponseDto": {
      "type": "object",
      "properties": {
        "id": {
          "type": "string"
        },
        "token": {
          "type": "string"
        }
      },
      "required": [
        "id",
        "token"
      ]
    },
    "ReassignApiKeyDto": {
      "type": "object",
      "properties": {
        "ownerMembershipId": {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
        }
      },
      "required": [
        "ownerMembershipId"
      ]
    },
    "ApiKeyOkResponseDto": {
      "type": "object",
      "properties": {
        "ok": {
          "type": "boolean"
        }
      },
      "required": [
        "ok"
      ]
    },
    "CreateApiKeyDto": {
      "type": "object",
      "properties": {
        "name": {
          "type": "string",
          "minLength": 1,
          "maxLength": 100
        },
        "description": {
          "type": "string",
          "maxLength": 300
        },
        "capabilities": {
          "maxItems": 20,
          "type": "array",
          "items": {
            "type": "string",
            "enum": [
              "worktime.supervise",
              "scheduling.plan",
              "scheduling.admin",
              "projects.manage",
              "projects.read",
              "crm.use",
              "crm.admin",
              "hr.manage",
              "hr.record",
              "payroll.run",
              "reports.team",
              "members.manage",
              "comms.announce",
              "integrations.manage",
              "org.admin"
            ]
          }
        },
        "expiresAt": {
          "type": "string",
          "format": "date-time",
          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$",
          "x-nullable": true
        },
        "readOnly": {
          "type": "boolean"
        }
      },
      "required": [
        "name"
      ]
    },
    "RotateApiKeyResponseDto": {
      "type": "object",
      "properties": {
        "token": {
          "type": "string"
        }
      },
      "required": [
        "token"
      ]
    },
    "AccessContextDto": {
      "type": "object",
      "properties": {
        "tenantId": {
          "type": "string"
        },
        "membershipId": {
          "type": "string"
        },
        "role": {
          "type": "string"
        },
        "capabilities": {
          "type": "array",
          "items": {
            "type": "string",
            "enum": [
              "worktime.supervise",
              "scheduling.plan",
              "scheduling.admin",
              "projects.manage",
              "projects.read",
              "crm.use",
              "crm.admin",
              "hr.manage",
              "hr.record",
              "payroll.run",
              "reports.team",
              "members.manage",
              "comms.announce",
              "integrations.manage",
              "org.admin"
            ]
          }
        },
        "apiKey": {
          "type": "object",
          "properties": {
            "id": {
              "type": "string"
            },
            "kind": {
              "type": "string",
              "enum": [
                "personal",
                "service"
              ]
            },
            "scope": {
              "type": "array",
              "items": {
                "type": "string",
                "enum": [
                  "worktime.supervise",
                  "scheduling.plan",
                  "scheduling.admin",
                  "projects.manage",
                  "projects.read",
                  "crm.use",
                  "crm.admin",
                  "hr.manage",
                  "hr.record",
                  "payroll.run",
                  "reports.team",
                  "members.manage",
                  "comms.announce",
                  "integrations.manage",
                  "org.admin"
                ]
              }
            },
            "readOnly": {
              "type": "boolean"
            },
            "expiresAt": {
              "type": "string",
              "format": "date-time",
              "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$",
              "x-nullable": true
            }
          },
          "required": [
            "id",
            "kind",
            "scope",
            "readOnly",
            "expiresAt"
          ],
          "x-nullable": true
        },
        "oauth": {
          "type": "object",
          "properties": {
            "grantId": {
              "type": "string"
            },
            "clientName": {
              "type": "string"
            },
            "scope": {
              "type": "array",
              "items": {
                "type": "string",
                "enum": [
                  "worktime.supervise",
                  "scheduling.plan",
                  "scheduling.admin",
                  "projects.manage",
                  "projects.read",
                  "crm.use",
                  "crm.admin",
                  "hr.manage",
                  "hr.record",
                  "payroll.run",
                  "reports.team",
                  "members.manage",
                  "comms.announce",
                  "integrations.manage",
                  "org.admin"
                ]
              }
            },
            "resource": {
              "type": "string",
              "x-nullable": true
            }
          },
          "required": [
            "grantId",
            "clientName",
            "scope",
            "resource"
          ],
          "x-nullable": true
        },
        "rateLimits": {
          "type": "object",
          "properties": {
            "perKeyPerMinute": {
              "type": "integer",
              "minimum": -9007199254740991,
              "maximum": 9007199254740991
            },
            "perTenantPerMinute": {
              "type": "integer",
              "minimum": -9007199254740991,
              "maximum": 9007199254740991
            }
          },
          "required": [
            "perKeyPerMinute",
            "perTenantPerMinute"
          ]
        }
      },
      "required": [
        "tenantId",
        "membershipId",
        "role",
        "capabilities",
        "apiKey",
        "oauth",
        "rateLimits"
      ]
    },
    "OAuthGrantListResponseDto": {
      "type": "object",
      "properties": {
        "grants": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "clientName": {
                "type": "string"
              },
              "clientUri": {
                "type": "string",
                "x-nullable": true
              },
              "scopes": {
                "type": "array",
                "items": {
                  "type": "string",
                  "enum": [
                    "worktime.supervise",
                    "scheduling.plan",
                    "scheduling.admin",
                    "projects.manage",
                    "projects.read",
                    "crm.use",
                    "crm.admin",
                    "hr.manage",
                    "hr.record",
                    "payroll.run",
                    "reports.team",
                    "members.manage",
                    "comms.announce",
                    "integrations.manage",
                    "org.admin"
                  ]
                }
              },
              "resource": {
                "type": "string",
                "x-nullable": true
              },
              "memberName": {
                "type": "string",
                "x-nullable": true
              },
              "membershipId": {
                "type": "string"
              },
              "createdAt": {
                "type": "string",
                "format": "date-time",
                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
              },
              "lastUsedAt": {
                "type": "string",
                "format": "date-time",
                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$",
                "x-nullable": true
              }
            },
            "required": [
              "id",
              "clientName",
              "clientUri",
              "scopes",
              "resource",
              "memberName",
              "membershipId",
              "createdAt",
              "lastUsedAt"
            ]
          }
        }
      },
      "required": [
        "grants"
      ]
    },
    "OAuthGrantOkResponseDto": {
      "type": "object",
      "properties": {
        "ok": {
          "type": "boolean"
        }
      },
      "required": [
        "ok"
      ]
    },
    "ShiftPlanResponseDto": {
      "type": "object",
      "properties": {
        "planningUnitId": {
          "type": "string"
        },
        "groupShifts": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "workDate": {
                "type": "string",
                "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
              },
              "membershipId": {
                "type": "string",
                "x-nullable": true
              },
              "planningUnitId": {
                "type": "string",
                "x-nullable": true
              },
              "kind": {
                "type": "string",
                "enum": [
                  "shift",
                  "off"
                ]
              },
              "shiftTypeId": {
                "type": "string",
                "x-nullable": true
              },
              "positionId": {
                "type": "string",
                "x-nullable": true
              },
              "startMinutes": {
                "type": "integer",
                "minimum": 0,
                "maximum": 1440,
                "x-nullable": true
              },
              "endMinutes": {
                "type": "integer",
                "minimum": 1,
                "maximum": 2880,
                "x-nullable": true
              },
              "breakMinutes": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "targetMinutes": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "drivingMinutes": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991,
                "x-nullable": true
              },
              "note": {
                "type": "string",
                "x-nullable": true
              },
              "publishedAt": {
                "type": "string",
                "x-nullable": true
              },
              "updatedAt": {
                "type": "string"
              },
              "segments": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "startMinutes": {
                      "type": "integer",
                      "minimum": 0,
                      "maximum": 1440
                    },
                    "endMinutes": {
                      "type": "integer",
                      "minimum": 1,
                      "maximum": 2880
                    },
                    "breakMinutes": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991
                    },
                    "targetMinutes": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991
                    },
                    "drivingMinutes": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991,
                      "x-nullable": true
                    }
                  },
                  "required": [
                    "startMinutes",
                    "endMinutes",
                    "breakMinutes",
                    "targetMinutes"
                  ]
                }
              }
            },
            "required": [
              "id",
              "workDate",
              "membershipId",
              "planningUnitId",
              "kind",
              "shiftTypeId",
              "positionId",
              "startMinutes",
              "endMinutes",
              "breakMinutes",
              "targetMinutes",
              "note",
              "publishedAt",
              "updatedAt",
              "segments"
            ]
          }
        },
        "members": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "membershipId": {
                "type": "string"
              },
              "displayName": {
                "type": "string"
              },
              "employmentStartDate": {
                "type": "string",
                "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
                "x-nullable": true
              },
              "employmentEndDate": {
                "type": "string",
                "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
                "x-nullable": true
              },
              "shifts": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "workDate": {
                      "type": "string",
                      "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
                    },
                    "membershipId": {
                      "type": "string",
                      "x-nullable": true
                    },
                    "planningUnitId": {
                      "type": "string",
                      "x-nullable": true
                    },
                    "kind": {
                      "type": "string",
                      "enum": [
                        "shift",
                        "off"
                      ]
                    },
                    "shiftTypeId": {
                      "type": "string",
                      "x-nullable": true
                    },
                    "positionId": {
                      "type": "string",
                      "x-nullable": true
                    },
                    "startMinutes": {
                      "type": "integer",
                      "minimum": 0,
                      "maximum": 1440,
                      "x-nullable": true
                    },
                    "endMinutes": {
                      "type": "integer",
                      "minimum": 1,
                      "maximum": 2880,
                      "x-nullable": true
                    },
                    "breakMinutes": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991
                    },
                    "targetMinutes": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991
                    },
                    "drivingMinutes": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991,
                      "x-nullable": true
                    },
                    "note": {
                      "type": "string",
                      "x-nullable": true
                    },
                    "publishedAt": {
                      "type": "string",
                      "x-nullable": true
                    },
                    "updatedAt": {
                      "type": "string"
                    },
                    "segments": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "startMinutes": {
                            "type": "integer",
                            "minimum": 0,
                            "maximum": 1440
                          },
                          "endMinutes": {
                            "type": "integer",
                            "minimum": 1,
                            "maximum": 2880
                          },
                          "breakMinutes": {
                            "type": "integer",
                            "minimum": -9007199254740991,
                            "maximum": 9007199254740991
                          },
                          "targetMinutes": {
                            "type": "integer",
                            "minimum": -9007199254740991,
                            "maximum": 9007199254740991
                          },
                          "drivingMinutes": {
                            "type": "integer",
                            "minimum": -9007199254740991,
                            "maximum": 9007199254740991,
                            "x-nullable": true
                          }
                        },
                        "required": [
                          "startMinutes",
                          "endMinutes",
                          "breakMinutes",
                          "targetMinutes"
                        ]
                      }
                    }
                  },
                  "required": [
                    "id",
                    "workDate",
                    "membershipId",
                    "planningUnitId",
                    "kind",
                    "shiftTypeId",
                    "positionId",
                    "startMinutes",
                    "endMinutes",
                    "breakMinutes",
                    "targetMinutes",
                    "note",
                    "publishedAt",
                    "updatedAt",
                    "segments"
                  ]
                }
              },
              "contextShifts": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "workDate": {
                      "type": "string",
                      "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
                    },
                    "planningUnitId": {
                      "type": "string"
                    },
                    "unitName": {
                      "type": "string"
                    },
                    "startMinutes": {
                      "type": "integer",
                      "minimum": 0,
                      "maximum": 1440
                    },
                    "endMinutes": {
                      "type": "integer",
                      "minimum": 1,
                      "maximum": 2880
                    }
                  },
                  "required": [
                    "workDate",
                    "planningUnitId",
                    "unitName",
                    "startMinutes",
                    "endMinutes"
                  ]
                }
              },
              "contractTargetMinutes": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991,
                "x-nullable": true
              },
              "flexBalanceMinutes": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991,
                "x-nullable": true
              },
              "managerMembershipId": {
                "type": "string",
                "x-nullable": true
              },
              "staffGroupIds": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            },
            "required": [
              "membershipId",
              "displayName",
              "employmentStartDate",
              "employmentEndDate",
              "shifts",
              "contextShifts",
              "contractTargetMinutes",
              "flexBalanceMinutes",
              "managerMembershipId",
              "staffGroupIds"
            ]
          }
        },
        "coverage": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "workDate": {
                "type": "string",
                "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
              },
              "requirementId": {
                "type": "string"
              },
              "startMinutes": {
                "type": "integer",
                "minimum": 0,
                "maximum": 1440
              },
              "endMinutes": {
                "type": "integer",
                "minimum": 1,
                "maximum": 2880
              },
              "requiredCount": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "positionId": {
                "type": "string",
                "x-nullable": true
              },
              "plannedCount": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "shortfall": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "uncoveredPersonMinutes": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "surplusPersonMinutes": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "skillGaps": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "skillIds": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "requiredCount": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991
                    },
                    "plannedCount": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991
                    },
                    "shortfall": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991
                    }
                  },
                  "required": [
                    "skillIds",
                    "requiredCount",
                    "plannedCount",
                    "shortfall"
                  ]
                }
              },
              "skillExpiry": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "skillId": {
                      "type": "string"
                    },
                    "expiredCount": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991
                    },
                    "expiringCount": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991
                    }
                  },
                  "required": [
                    "skillId",
                    "expiredCount",
                    "expiringCount"
                  ]
                }
              },
              "understaffed": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "from": {
                      "type": "integer",
                      "minimum": 0,
                      "maximum": 1440
                    },
                    "to": {
                      "type": "integer",
                      "minimum": 1,
                      "maximum": 2880
                    },
                    "plannedCount": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991
                    }
                  },
                  "required": [
                    "from",
                    "to",
                    "plannedCount"
                  ]
                }
              }
            },
            "required": [
              "workDate",
              "requirementId",
              "startMinutes",
              "endMinutes",
              "requiredCount",
              "positionId",
              "plannedCount",
              "shortfall",
              "uncoveredPersonMinutes",
              "surplusPersonMinutes",
              "skillGaps",
              "skillExpiry",
              "understaffed"
            ]
          }
        },
        "conflicts": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "membershipId": {
                "type": "string"
              },
              "workDate": {
                "type": "string",
                "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
              },
              "type": {
                "type": "string",
                "enum": [
                  "shift-on-absence",
                  "shift-outside-employment"
                ]
              }
            },
            "required": [
              "membershipId",
              "workDate",
              "type"
            ]
          }
        },
        "avoidPairConflicts": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "aMembershipId": {
                "type": "string"
              },
              "bMembershipId": {
                "type": "string"
              },
              "aDisplayName": {
                "type": "string"
              },
              "bDisplayName": {
                "type": "string"
              },
              "workDate": {
                "type": "string",
                "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
              }
            },
            "required": [
              "aMembershipId",
              "bMembershipId",
              "aDisplayName",
              "bDisplayName",
              "workDate"
            ]
          }
        },
        "complianceViolations": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "membershipId": {
                "type": "string"
              },
              "type": {
                "type": "string",
                "enum": [
                  "daily_rest",
                  "weekly_rest",
                  "period_cap",
                  "consecutive_days",
                  "consecutive_nights",
                  "min_shift",
                  "max_shift",
                  "long_shift_count",
                  "forbidden_start",
                  "forbidden_end",
                  "split_gap",
                  "split_span",
                  "split_count",
                  "night_recovery",
                  "weekly_days_off",
                  "weekend_rest",
                  "free_sunday",
                  "consecutive_free_days",
                  "break_required",
                  "rest_debt",
                  "multi_period_cap",
                  "sub_period_cap",
                  "long_window_avg",
                  "v_free_count",
                  "break_placement",
                  "competence_missing",
                  "competence_below_level",
                  "competence_expired",
                  "competence_expiring"
                ]
              },
              "severity": {
                "type": "string",
                "enum": [
                  "hard",
                  "soft"
                ]
              },
              "source": {
                "type": "string",
                "enum": [
                  "law",
                  "tes",
                  "unit"
                ]
              },
              "dates": {
                "type": "array",
                "items": {
                  "type": "string",
                  "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
                }
              },
              "actual": {
                "type": "number"
              },
              "limit": {
                "type": "number"
              }
            },
            "required": [
              "membershipId",
              "type",
              "severity",
              "source",
              "dates",
              "actual",
              "limit"
            ]
          }
        },
        "workdayLengthMinutes": {
          "type": "integer",
          "exclusiveMinimum": true,
          "maximum": 9007199254740991,
          "minimum": 0
        },
        "cancelDeadlineDaysBefore": {
          "type": "integer",
          "minimum": 0,
          "maximum": 9007199254740991,
          "x-nullable": true
        },
        "cancelDeadlineTimeMinutes": {
          "type": "integer",
          "minimum": 0,
          "maximum": 1439,
          "x-nullable": true
        },
        "rotationDeviations": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "membershipId": {
                "type": "string"
              },
              "workDate": {
                "type": "string",
                "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
              },
              "kind": {
                "type": "string",
                "enum": [
                  "type_changed",
                  "times_changed",
                  "expected_work_missing",
                  "expected_off_working"
                ]
              },
              "expectedKind": {
                "type": "string",
                "enum": [
                  "shift",
                  "off"
                ]
              },
              "expectedShiftTypeNameFi": {
                "type": "string",
                "x-nullable": true
              },
              "expectedShiftTypeNameSv": {
                "type": "string",
                "x-nullable": true
              },
              "expectedShiftTypeNameEn": {
                "type": "string",
                "x-nullable": true
              },
              "expectedStartMinutes": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991,
                "x-nullable": true
              },
              "expectedEndMinutes": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991,
                "x-nullable": true
              }
            },
            "required": [
              "membershipId",
              "workDate",
              "kind",
              "expectedKind",
              "expectedShiftTypeNameFi",
              "expectedShiftTypeNameSv",
              "expectedShiftTypeNameEn",
              "expectedStartMinutes",
              "expectedEndMinutes"
            ]
          }
        },
        "holidayDates": {
          "type": "array",
          "items": {
            "type": "string"
          }
        }
      },
      "required": [
        "planningUnitId",
        "groupShifts",
        "members",
        "coverage",
        "conflicts",
        "avoidPairConflicts",
        "complianceViolations",
        "workdayLengthMinutes",
        "cancelDeadlineDaysBefore",
        "cancelDeadlineTimeMinutes",
        "rotationDeviations",
        "holidayDates"
      ]
    },
    "UncoveredShiftListResponseDto": {
      "type": "object",
      "properties": {
        "shifts": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "shiftId": {
                "type": "string"
              },
              "workDate": {
                "type": "string",
                "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
              },
              "membershipId": {
                "type": "string"
              },
              "memberName": {
                "type": "string",
                "x-nullable": true
              },
              "startMinutes": {
                "type": "integer",
                "minimum": 0,
                "maximum": 1440,
                "x-nullable": true
              },
              "endMinutes": {
                "type": "integer",
                "minimum": 1,
                "maximum": 2880,
                "x-nullable": true
              },
              "breakMinutes": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "targetMinutes": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "positionId": {
                "type": "string",
                "x-nullable": true
              },
              "shiftTypeId": {
                "type": "string",
                "x-nullable": true
              },
              "segments": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "startMinutes": {
                      "type": "integer",
                      "minimum": 0,
                      "maximum": 1440
                    },
                    "endMinutes": {
                      "type": "integer",
                      "minimum": 1,
                      "maximum": 2880
                    },
                    "breakMinutes": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991
                    },
                    "targetMinutes": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991
                    },
                    "drivingMinutes": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991,
                      "x-nullable": true
                    }
                  },
                  "required": [
                    "startMinutes",
                    "endMinutes",
                    "breakMinutes",
                    "targetMinutes"
                  ]
                }
              },
              "absenceName": {
                "type": "object",
                "properties": {
                  "nameFi": {
                    "type": "string"
                  },
                  "nameSv": {
                    "type": "string"
                  },
                  "nameEn": {
                    "type": "string"
                  }
                },
                "required": [
                  "nameFi",
                  "nameSv",
                  "nameEn"
                ],
                "x-nullable": true
              },
              "status": {
                "type": "string",
                "enum": [
                  "needs_cover",
                  "released",
                  "filled",
                  "cover_no_longer_needed"
                ]
              },
              "openShiftId": {
                "type": "string",
                "x-nullable": true
              },
              "requiredSkillIds": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "requiredSkills": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "skillId": {
                      "type": "string"
                    },
                    "nameFi": {
                      "type": "string"
                    },
                    "nameSv": {
                      "type": "string"
                    },
                    "nameEn": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "skillId",
                    "nameFi",
                    "nameSv",
                    "nameEn"
                  ]
                }
              }
            },
            "required": [
              "shiftId",
              "workDate",
              "membershipId",
              "memberName",
              "startMinutes",
              "endMinutes",
              "breakMinutes",
              "targetMinutes",
              "positionId",
              "shiftTypeId",
              "segments",
              "absenceName",
              "status",
              "openShiftId",
              "requiredSkillIds",
              "requiredSkills"
            ]
          }
        }
      },
      "required": [
        "shifts"
      ]
    },
    "SchedulingOkResponseDto": {
      "type": "object",
      "properties": {
        "ok": {
          "type": "boolean"
        }
      },
      "required": [
        "ok"
      ]
    },
    "PublishEventPageResponseDto": {
      "type": "object",
      "properties": {
        "items": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "planningUnitId": {
                "type": "string"
              },
              "periodFrom": {
                "type": "string",
                "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
              },
              "periodTo": {
                "type": "string",
                "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
              },
              "publishedAt": {
                "type": "string"
              },
              "publishedBy": {
                "type": "string",
                "x-nullable": true
              },
              "publishedCount": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "recipientCount": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "delivery": {
                "type": "object",
                "properties": {
                  "sent": {
                    "type": "integer",
                    "minimum": -9007199254740991,
                    "maximum": 9007199254740991
                  },
                  "pending": {
                    "type": "integer",
                    "minimum": -9007199254740991,
                    "maximum": 9007199254740991
                  },
                  "failed": {
                    "type": "integer",
                    "minimum": -9007199254740991,
                    "maximum": 9007199254740991
                  },
                  "skipped": {
                    "type": "integer",
                    "minimum": -9007199254740991,
                    "maximum": 9007199254740991
                  }
                },
                "required": [
                  "sent",
                  "pending",
                  "failed",
                  "skipped"
                ]
              }
            },
            "required": [
              "id",
              "planningUnitId",
              "periodFrom",
              "periodTo",
              "publishedAt",
              "publishedBy",
              "publishedCount",
              "recipientCount",
              "delivery"
            ]
          }
        },
        "pageInfo": {
          "type": "object",
          "properties": {
            "nextCursor": {
              "type": "string",
              "x-nullable": true
            },
            "hasMore": {
              "type": "boolean"
            }
          },
          "required": [
            "nextCursor",
            "hasMore"
          ]
        }
      },
      "required": [
        "items",
        "pageInfo"
      ]
    },
    "PlanningUnitListResponseDto": {
      "type": "object",
      "properties": {
        "units": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "name": {
                "type": "string"
              },
              "parentId": {
                "type": "string",
                "x-nullable": true
              },
              "costCenterValueId": {
                "type": "string",
                "x-nullable": true
              },
              "periodWorkWeeks": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991,
                "x-nullable": true
              },
              "periodWorkAnchor": {
                "type": "string",
                "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
                "x-nullable": true
              },
              "crossUnitOptOut": {
                "type": "boolean"
              },
              "active": {
                "type": "boolean"
              },
              "sortOrder": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              }
            },
            "required": [
              "id",
              "name",
              "parentId",
              "costCenterValueId",
              "periodWorkWeeks",
              "periodWorkAnchor",
              "crossUnitOptOut",
              "active",
              "sortOrder"
            ]
          }
        }
      },
      "required": [
        "units"
      ]
    },
    "MyShiftsResponseDto": {
      "type": "object",
      "properties": {
        "shifts": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "workDate": {
                "type": "string",
                "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
              },
              "kind": {
                "type": "string",
                "enum": [
                  "shift",
                  "off"
                ]
              },
              "startMinutes": {
                "type": "integer",
                "minimum": 0,
                "maximum": 1440,
                "x-nullable": true
              },
              "endMinutes": {
                "type": "integer",
                "minimum": 1,
                "maximum": 2880,
                "x-nullable": true
              },
              "breakMinutes": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "targetMinutes": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "segments": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "startMinutes": {
                      "type": "integer",
                      "minimum": 0,
                      "maximum": 1440
                    },
                    "endMinutes": {
                      "type": "integer",
                      "minimum": 1,
                      "maximum": 2880
                    },
                    "breakMinutes": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991
                    },
                    "targetMinutes": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991
                    },
                    "drivingMinutes": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991,
                      "x-nullable": true
                    }
                  },
                  "required": [
                    "startMinutes",
                    "endMinutes",
                    "breakMinutes",
                    "targetMinutes"
                  ]
                }
              },
              "source": {
                "type": "string",
                "enum": [
                  "person-shift",
                  "group-shift"
                ]
              },
              "shiftTypeNameFi": {
                "type": "string",
                "x-nullable": true
              },
              "shiftTypeNameSv": {
                "type": "string",
                "x-nullable": true
              },
              "shiftTypeNameEn": {
                "type": "string",
                "x-nullable": true
              },
              "shortCode": {
                "type": "string",
                "x-nullable": true
              },
              "color": {
                "type": "string",
                "x-nullable": true
              },
              "unitName": {
                "type": "string",
                "x-nullable": true
              },
              "publishedAt": {
                "type": "string",
                "x-nullable": true
              },
              "ackRequired": {
                "type": "boolean"
              },
              "acknowledgedAt": {
                "type": "string",
                "x-nullable": true
              },
              "onApprovedAbsence": {
                "type": "boolean"
              },
              "note": {
                "type": "string",
                "x-nullable": true
              },
              "deviatesFromRotation": {
                "type": "boolean"
              }
            },
            "required": [
              "id",
              "workDate",
              "kind",
              "startMinutes",
              "endMinutes",
              "breakMinutes",
              "targetMinutes",
              "segments",
              "source",
              "shiftTypeNameFi",
              "shiftTypeNameSv",
              "shiftTypeNameEn",
              "shortCode",
              "color",
              "unitName",
              "publishedAt",
              "ackRequired",
              "acknowledgedAt",
              "onApprovedAbsence",
              "note",
              "deviatesFromRotation"
            ]
          }
        },
        "dayNotes": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "date": {
                "type": "string",
                "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
              },
              "title": {
                "type": "string"
              },
              "body": {
                "type": "string"
              },
              "unitName": {
                "type": "string",
                "x-nullable": true
              }
            },
            "required": [
              "id",
              "date",
              "title",
              "body",
              "unitName"
            ]
          }
        },
        "ackRequired": {
          "type": "boolean"
        },
        "autonomousSchedulingEnabled": {
          "type": "boolean"
        },
        "employmentStartDate": {
          "type": "string",
          "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
          "x-nullable": true
        },
        "employmentEndDate": {
          "type": "string",
          "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
          "x-nullable": true
        }
      },
      "required": [
        "shifts",
        "dayNotes",
        "ackRequired",
        "autonomousSchedulingEnabled",
        "employmentStartDate",
        "employmentEndDate"
      ]
    },
    "OpenShiftPageResponseDto": {
      "type": "object",
      "properties": {
        "items": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "planningUnitId": {
                "type": "string"
              },
              "date": {
                "type": "string",
                "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
              },
              "shiftTypeId": {
                "type": "string",
                "x-nullable": true
              },
              "startMinutes": {
                "type": "integer",
                "minimum": 0,
                "maximum": 1440,
                "x-nullable": true
              },
              "endMinutes": {
                "type": "integer",
                "minimum": 1,
                "maximum": 2880,
                "x-nullable": true
              },
              "breakMinutes": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "targetMinutes": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "segments": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "startMinutes": {
                      "type": "integer",
                      "minimum": 0,
                      "maximum": 1440
                    },
                    "endMinutes": {
                      "type": "integer",
                      "minimum": 1,
                      "maximum": 2880
                    },
                    "breakMinutes": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991
                    },
                    "targetMinutes": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991
                    },
                    "drivingMinutes": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991,
                      "x-nullable": true
                    }
                  },
                  "required": [
                    "startMinutes",
                    "endMinutes",
                    "breakMinutes",
                    "targetMinutes"
                  ]
                }
              },
              "requiredSkillIds": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "requiredSkills": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "skillId": {
                      "type": "string"
                    },
                    "nameFi": {
                      "type": "string"
                    },
                    "nameSv": {
                      "type": "string"
                    },
                    "nameEn": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "skillId",
                    "nameFi",
                    "nameSv",
                    "nameEn"
                  ]
                }
              },
              "status": {
                "type": "string",
                "enum": [
                  "open",
                  "claimed",
                  "filled",
                  "cancelled"
                ]
              },
              "reason": {
                "type": "string",
                "x-nullable": true
              },
              "createdAt": {
                "type": "string"
              },
              "expiresAt": {
                "type": "string",
                "x-nullable": true
              },
              "cancelDeadline": {
                "type": "string",
                "x-nullable": true
              },
              "offerStage": {
                "type": "string",
                "enum": [
                  "unit",
                  "cross_unit",
                  "all"
                ]
              },
              "escalateAfterMinutes": {
                "type": "integer",
                "exclusiveMinimum": 0,
                "maximum": 9007199254740991,
                "x-nullable": true
              },
              "claims": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "membershipId": {
                      "type": "string"
                    },
                    "displayName": {
                      "type": "string"
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "pending",
                        "approved",
                        "rejected",
                        "withdrawn"
                      ]
                    },
                    "createdAt": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "membershipId",
                    "displayName",
                    "status",
                    "createdAt"
                  ]
                }
              },
              "myClaimStatus": {
                "type": "string",
                "enum": [
                  "pending",
                  "approved",
                  "rejected",
                  "withdrawn",
                  null
                ],
                "x-nullable": true
              },
              "myClaimReason": {
                "type": "string",
                "x-nullable": true
              },
              "eligible": {
                "type": "boolean"
              },
              "ineligibleReason": {
                "type": "string",
                "enum": [
                  "missing_skill",
                  "not_employed",
                  "already_scheduled",
                  null
                ],
                "x-nullable": true
              },
              "isCrossUnit": {
                "type": "boolean"
              },
              "unitName": {
                "type": "string",
                "x-nullable": true
              }
            },
            "required": [
              "id",
              "planningUnitId",
              "date",
              "shiftTypeId",
              "startMinutes",
              "endMinutes",
              "breakMinutes",
              "targetMinutes",
              "segments",
              "requiredSkillIds",
              "requiredSkills",
              "status",
              "reason",
              "createdAt",
              "expiresAt",
              "cancelDeadline",
              "offerStage",
              "escalateAfterMinutes"
            ]
          }
        },
        "pageInfo": {
          "type": "object",
          "properties": {
            "nextCursor": {
              "type": "string",
              "x-nullable": true
            },
            "hasMore": {
              "type": "boolean"
            }
          },
          "required": [
            "nextCursor",
            "hasMore"
          ]
        }
      },
      "required": [
        "items",
        "pageInfo"
      ]
    },
    "ClaimOpenShiftDto": {
      "type": "object",
      "properties": {
        "message": {
          "type": "string",
          "maxLength": 100000
        }
      }
    },
    "ShiftSwapPageResponseDto": {
      "type": "object",
      "properties": {
        "items": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "requesterMembershipId": {
                "type": "string"
              },
              "requesterDisplayName": {
                "type": "string"
              },
              "requesterDate": {
                "type": "string",
                "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
              },
              "counterpartyMembershipId": {
                "type": "string",
                "x-nullable": true
              },
              "counterpartyDisplayName": {
                "type": "string",
                "x-nullable": true
              },
              "counterpartyDate": {
                "type": "string",
                "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
                "x-nullable": true
              },
              "isGiveAway": {
                "type": "boolean"
              },
              "status": {
                "type": "string",
                "enum": [
                  "proposed",
                  "accepted",
                  "approved",
                  "rejected",
                  "withdrawn",
                  "cancelled"
                ]
              },
              "reason": {
                "type": "string",
                "x-nullable": true
              },
              "createdAt": {
                "type": "string"
              }
            },
            "required": [
              "id",
              "requesterMembershipId",
              "requesterDisplayName",
              "requesterDate",
              "counterpartyMembershipId",
              "counterpartyDisplayName",
              "counterpartyDate",
              "isGiveAway",
              "status",
              "reason",
              "createdAt"
            ]
          }
        },
        "pageInfo": {
          "type": "object",
          "properties": {
            "nextCursor": {
              "type": "string",
              "x-nullable": true
            },
            "hasMore": {
              "type": "boolean"
            }
          },
          "required": [
            "nextCursor",
            "hasMore"
          ]
        }
      },
      "required": [
        "items",
        "pageInfo"
      ]
    },
    "UnitRosterResponseDto": {
      "type": "object",
      "properties": {
        "shifts": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "membershipId": {
                "type": "string"
              },
              "displayName": {
                "type": "string"
              },
              "planningUnitId": {
                "type": "string"
              },
              "planningUnitName": {
                "type": "string"
              },
              "workDate": {
                "type": "string",
                "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
              },
              "startMinutes": {
                "type": "integer",
                "minimum": 0,
                "maximum": 1440,
                "x-nullable": true
              },
              "endMinutes": {
                "type": "integer",
                "minimum": 1,
                "maximum": 2880,
                "x-nullable": true
              },
              "breakMinutes": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "targetMinutes": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "segments": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "startMinutes": {
                      "type": "integer",
                      "minimum": 0,
                      "maximum": 1440
                    },
                    "endMinutes": {
                      "type": "integer",
                      "minimum": 1,
                      "maximum": 2880
                    },
                    "breakMinutes": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991
                    },
                    "targetMinutes": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991
                    },
                    "drivingMinutes": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991,
                      "x-nullable": true
                    }
                  },
                  "required": [
                    "startMinutes",
                    "endMinutes",
                    "breakMinutes",
                    "targetMinutes"
                  ]
                }
              },
              "shiftTypeNameFi": {
                "type": "string",
                "x-nullable": true
              },
              "shiftTypeNameSv": {
                "type": "string",
                "x-nullable": true
              },
              "shiftTypeNameEn": {
                "type": "string",
                "x-nullable": true
              },
              "shortCode": {
                "type": "string",
                "x-nullable": true
              },
              "color": {
                "type": "string",
                "x-nullable": true
              }
            },
            "required": [
              "membershipId",
              "displayName",
              "planningUnitId",
              "planningUnitName",
              "workDate",
              "startMinutes",
              "endMinutes",
              "breakMinutes",
              "targetMinutes",
              "segments",
              "shiftTypeNameFi",
              "shiftTypeNameSv",
              "shiftTypeNameEn",
              "shortCode",
              "color"
            ]
          }
        },
        "units": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "name": {
                "type": "string"
              }
            },
            "required": [
              "id",
              "name"
            ]
          }
        }
      },
      "required": [
        "shifts",
        "units"
      ]
    },
    "ResolveClaimDto": {
      "type": "object",
      "properties": {
        "membershipId": {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
        },
        "reason": {
          "type": "string",
          "minLength": 3,
          "maxLength": 500,
          "x-nullable": true
        }
      },
      "required": [
        "membershipId"
      ]
    },
    "RejectSwapDto": {
      "type": "object",
      "properties": {
        "reason": {
          "type": "string",
          "minLength": 3,
          "maxLength": 500,
          "x-nullable": true
        }
      }
    },
    "DayTypeListResponseDto": {
      "type": "object",
      "properties": {
        "dayTypes": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "code": {
                "type": "string",
                "pattern": "^[a-z][a-z0-9_]{1,49}$"
              },
              "nameFi": {
                "type": "string",
                "minLength": 1,
                "maxLength": 100
              },
              "nameSv": {
                "type": "string",
                "minLength": 1,
                "maxLength": 100
              },
              "nameEn": {
                "type": "string",
                "minLength": 1,
                "maxLength": 100
              },
              "active": {
                "type": "boolean"
              },
              "isSystem": {
                "type": "boolean"
              },
              "locked": {
                "type": "boolean"
              },
              "governedByPolicy": {
                "type": "boolean"
              },
              "sortOrder": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "versions": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "validFrom": {
                      "type": "string",
                      "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
                    },
                    "validTo": {
                      "type": "string",
                      "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
                      "x-nullable": true
                    },
                    "creditsTarget": {
                      "type": "boolean"
                    },
                    "consumesFlex": {
                      "type": "boolean"
                    },
                    "consumesAccountTypeId": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "x-nullable": true
                    },
                    "countsAsWorkTime": {
                      "type": "boolean"
                    },
                    "countsTowardMaxWorkTime": {
                      "type": "boolean"
                    },
                    "exportAsCount": {
                      "type": "boolean"
                    }
                  },
                  "required": [
                    "id",
                    "validFrom",
                    "validTo",
                    "creditsTarget",
                    "consumesFlex",
                    "countsAsWorkTime",
                    "countsTowardMaxWorkTime",
                    "exportAsCount"
                  ]
                }
              }
            },
            "required": [
              "id",
              "code",
              "nameFi",
              "nameSv",
              "nameEn",
              "active",
              "isSystem",
              "locked",
              "governedByPolicy",
              "sortOrder",
              "versions"
            ]
          }
        }
      },
      "required": [
        "dayTypes"
      ]
    },
    "EntryTypeListResponseDto": {
      "type": "object",
      "properties": {
        "entryTypes": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "code": {
                "type": "string",
                "pattern": "^[a-z][a-z0-9_]{1,49}$"
              },
              "nameFi": {
                "type": "string",
                "minLength": 1,
                "maxLength": 100
              },
              "nameSv": {
                "type": "string",
                "minLength": 1,
                "maxLength": 100
              },
              "nameEn": {
                "type": "string",
                "minLength": 1,
                "maxLength": 100
              },
              "active": {
                "type": "boolean"
              },
              "isSystem": {
                "type": "boolean"
              },
              "locked": {
                "type": "boolean"
              },
              "sortOrder": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "versions": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "validFrom": {
                      "type": "string",
                      "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
                    },
                    "validTo": {
                      "type": "string",
                      "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
                      "x-nullable": true
                    },
                    "countsAsWorkTime": {
                      "type": "boolean"
                    },
                    "accruesFlex": {
                      "type": "boolean"
                    },
                    "creditsTarget": {
                      "default": false,
                      "type": "boolean"
                    },
                    "countsTowardMaxWorkTime": {
                      "type": "boolean"
                    },
                    "emergencyWork": {
                      "default": false,
                      "type": "boolean"
                    },
                    "requiresComment": {
                      "default": false,
                      "type": "boolean"
                    },
                    "paid": {
                      "type": "boolean"
                    },
                    "maxDurationMinutes": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991,
                      "x-nullable": true
                    },
                    "perEntryCreditCapMinutes": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991,
                      "default": null,
                      "x-nullable": true
                    },
                    "dailyCreditCapMinutes": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991,
                      "default": null,
                      "x-nullable": true
                    },
                    "creditBeyondTargetCapMinutes": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991,
                      "default": null,
                      "x-nullable": true
                    },
                    "unpaidFirstMinutes": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991,
                      "default": null,
                      "x-nullable": true
                    },
                    "worktimeFractionBp": {
                      "type": "integer",
                      "minimum": 0,
                      "maximum": 10000,
                      "default": null,
                      "x-nullable": true
                    }
                  },
                  "required": [
                    "id",
                    "validFrom",
                    "validTo",
                    "countsAsWorkTime",
                    "accruesFlex",
                    "countsTowardMaxWorkTime",
                    "paid",
                    "maxDurationMinutes"
                  ]
                }
              }
            },
            "required": [
              "id",
              "code",
              "nameFi",
              "nameSv",
              "nameEn",
              "active",
              "isSystem",
              "locked",
              "sortOrder",
              "versions"
            ]
          }
        }
      },
      "required": [
        "entryTypes"
      ]
    },
    "BreakTypeListResponseDto": {
      "type": "object",
      "properties": {
        "breakTypes": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string",
                "format": "uuid",
                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
              },
              "code": {
                "type": "string",
                "minLength": 1,
                "maxLength": 40
              },
              "nameFi": {
                "type": "string",
                "minLength": 1,
                "maxLength": 80
              },
              "nameSv": {
                "type": "string",
                "minLength": 1,
                "maxLength": 80
              },
              "nameEn": {
                "type": "string",
                "minLength": 1,
                "maxLength": 80
              },
              "active": {
                "type": "boolean"
              },
              "isSystem": {
                "type": "boolean"
              },
              "sortOrder": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "versions": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "defaultMinutes": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991,
                      "x-nullable": true
                    },
                    "paidMode": {
                      "type": "string",
                      "enum": [
                        "unpaid",
                        "paid",
                        "paid_up_to"
                      ]
                    },
                    "paidCapMinutes": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991,
                      "x-nullable": true
                    },
                    "overflowTreatment": {
                      "type": "string",
                      "enum": [
                        "unpaid",
                        "paid",
                        "flag"
                      ]
                    },
                    "maxPerDay": {
                      "type": "integer",
                      "minimum": 0,
                      "maximum": 9007199254740991,
                      "x-nullable": true
                    },
                    "maxPaidMinutesPerDay": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991,
                      "x-nullable": true
                    },
                    "satisfiesDailyBreakDuty": {
                      "type": "boolean"
                    },
                    "mustBeContinuous": {
                      "type": "boolean"
                    },
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    },
                    "validFrom": {
                      "type": "string",
                      "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
                    },
                    "validTo": {
                      "type": "string",
                      "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
                      "x-nullable": true
                    }
                  },
                  "required": [
                    "defaultMinutes",
                    "paidMode",
                    "paidCapMinutes",
                    "overflowTreatment",
                    "maxPerDay",
                    "maxPaidMinutesPerDay",
                    "satisfiesDailyBreakDuty",
                    "mustBeContinuous",
                    "id",
                    "validFrom",
                    "validTo"
                  ]
                }
              }
            },
            "required": [
              "id",
              "code",
              "nameFi",
              "nameSv",
              "nameEn",
              "active",
              "isSystem",
              "sortOrder",
              "versions"
            ]
          }
        }
      },
      "required": [
        "breakTypes"
      ]
    },
    "ShiftTypeListResponseDto": {
      "type": "object",
      "properties": {
        "shiftTypes": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "code": {
                "type": "string"
              },
              "nameFi": {
                "type": "string"
              },
              "nameSv": {
                "type": "string"
              },
              "nameEn": {
                "type": "string"
              },
              "shortCode": {
                "type": "string"
              },
              "color": {
                "type": "string"
              },
              "active": {
                "type": "boolean"
              },
              "isSystem": {
                "type": "boolean"
              },
              "sortOrder": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "versions": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "validFrom": {
                      "type": "string",
                      "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
                    },
                    "validTo": {
                      "type": "string",
                      "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
                      "x-nullable": true
                    },
                    "startMinutes": {
                      "type": "integer",
                      "minimum": 0,
                      "maximum": 1440
                    },
                    "endMinutes": {
                      "type": "integer",
                      "minimum": 1,
                      "maximum": 2880
                    },
                    "targetMinutes": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991
                    },
                    "drivingMinutes": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991,
                      "x-nullable": true
                    },
                    "policy": {
                      "type": "object",
                      "properties": {
                        "breakDeductionMode": {
                          "type": "string",
                          "enum": [
                            "none",
                            "minimum",
                            "fixed"
                          ]
                        },
                        "breakThresholdMinutes": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        "breakThresholdBasis": {
                          "type": "string",
                          "enum": [
                            "work",
                            "span"
                          ]
                        },
                        "minBreakMinutes": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        "breakAnchorMinutes": {
                          "type": "integer",
                          "minimum": 0,
                          "maximum": 1440,
                          "x-nullable": true
                        },
                        "paidCoffeeTotalMinutes": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        "paidCoffeeMaxCount": {
                          "type": "integer",
                          "minimum": 0,
                          "maximum": 9007199254740991
                        },
                        "flexWindowStartMinutes": {
                          "type": "integer",
                          "minimum": 0,
                          "maximum": 1440
                        },
                        "flexWindowEndMinutes": {
                          "type": "integer",
                          "minimum": 0,
                          "maximum": 1440
                        },
                        "dayFlexCapMinutes": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        "dayFlexFloorMinutes": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        "dailyRegularBasis": {
                          "type": "string",
                          "enum": [
                            "target",
                            "fixed"
                          ]
                        },
                        "dailyRegularFixedMinutes": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        "dailyOt50Minutes": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991,
                          "x-nullable": true
                        },
                        "flexRoundingMinutes": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        "openPunchAutoClose": {
                          "type": "string",
                          "enum": [
                            "off",
                            "boundary",
                            "planned_end"
                          ]
                        },
                        "punchRoundingMinutes": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        "punchGraceStartMinutes": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        "punchGraceEndMinutes": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        "prepMinMinutes": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        "prepMaxCreditMinutes": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        "wrapMinMinutes": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        "wrapMaxCreditMinutes": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        "prepWrapFixedCreditMinutes": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        "prepWrapCountsTowardWeeklyOt": {
                          "type": "boolean"
                        },
                        "prepWrapDisposition": {
                          "type": "string",
                          "enum": [
                            "flex",
                            "payout",
                            "ignore",
                            "bank"
                          ]
                        },
                        "extendShortBreakToMinutes": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        "shortenLongBreakToMinutes": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        "zeroBreakSuppressesAutoDeduct": {
                          "type": "boolean"
                        },
                        "defaultEntryTypeId": {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                          "x-nullable": true
                        },
                        "deductedBreakTypeId": {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                          "x-nullable": true
                        }
                      }
                    },
                    "segments": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "startMinutes": {
                            "type": "integer",
                            "minimum": 0,
                            "maximum": 1440
                          },
                          "endMinutes": {
                            "type": "integer",
                            "minimum": 1,
                            "maximum": 2880
                          },
                          "breakMinutes": {
                            "type": "integer",
                            "minimum": -9007199254740991,
                            "maximum": 9007199254740991
                          },
                          "targetMinutes": {
                            "type": "integer",
                            "minimum": -9007199254740991,
                            "maximum": 9007199254740991
                          }
                        },
                        "required": [
                          "startMinutes",
                          "endMinutes",
                          "breakMinutes",
                          "targetMinutes"
                        ]
                      }
                    },
                    "clockWindows": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "weekday": {
                            "type": "integer",
                            "minimum": 1,
                            "maximum": 7
                          },
                          "startMinutes": {
                            "type": "integer",
                            "minimum": 0,
                            "maximum": 1440
                          },
                          "endMinutes": {
                            "type": "integer",
                            "minimum": 1,
                            "maximum": 2880
                          },
                          "kind": {
                            "type": "string",
                            "enum": [
                              "allowed",
                              "expected",
                              "ot_upgrade"
                            ]
                          }
                        },
                        "required": [
                          "weekday",
                          "startMinutes",
                          "endMinutes",
                          "kind"
                        ]
                      }
                    }
                  },
                  "required": [
                    "id",
                    "validFrom",
                    "validTo",
                    "startMinutes",
                    "endMinutes",
                    "targetMinutes",
                    "policy",
                    "segments",
                    "clockWindows"
                  ]
                }
              }
            },
            "required": [
              "id",
              "code",
              "nameFi",
              "nameSv",
              "nameEn",
              "shortCode",
              "color",
              "active",
              "isSystem",
              "sortOrder",
              "versions"
            ]
          }
        }
      },
      "required": [
        "shiftTypes"
      ]
    },
    "BalanceTransactionListResponseDto": {
      "type": "object",
      "properties": {
        "items": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "membershipId": {
                "type": "string"
              },
              "accountTypeId": {
                "type": "string"
              },
              "occurredOn": {
                "type": "string",
                "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
              },
              "amountMinutes": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "kind": {
                "type": "string",
                "enum": [
                  "initial",
                  "adjustment",
                  "transfer",
                  "usage",
                  "expiry",
                  "cut"
                ]
              },
              "reason": {
                "type": "string",
                "x-nullable": true
              },
              "sourceWorkDayId": {
                "type": "string",
                "x-nullable": true
              },
              "createdByMembershipId": {
                "type": "string"
              },
              "createdByName": {
                "type": "string",
                "x-nullable": true
              },
              "createdAt": {
                "type": "string"
              }
            },
            "required": [
              "id",
              "membershipId",
              "accountTypeId",
              "occurredOn",
              "amountMinutes",
              "kind",
              "reason",
              "sourceWorkDayId",
              "createdByMembershipId",
              "createdByName",
              "createdAt"
            ]
          }
        },
        "pageInfo": {
          "type": "object",
          "properties": {
            "nextCursor": {
              "type": "string",
              "x-nullable": true
            },
            "hasMore": {
              "type": "boolean"
            }
          },
          "required": [
            "nextCursor",
            "hasMore"
          ]
        }
      },
      "required": [
        "items",
        "pageInfo"
      ]
    },
    "BalanceAccountTypeListResponseDto": {
      "type": "object",
      "properties": {
        "accountTypes": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "kind": {
                "type": "string",
                "enum": [
                  "flex",
                  "overtime_bank",
                  "worktime_bank",
                  "shorter_worktime"
                ]
              },
              "code": {
                "type": "string"
              },
              "nameFi": {
                "type": "string"
              },
              "nameSv": {
                "type": "string"
              },
              "nameEn": {
                "type": "string"
              },
              "accrualSource": {
                "type": "string",
                "enum": [
                  "projection",
                  "ledger"
                ]
              },
              "capMaxMinutes": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991,
                "x-nullable": true
              },
              "capMinMinutes": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991,
                "x-nullable": true
              },
              "yearlyAccrualCapMinutes": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991,
                "x-nullable": true
              },
              "active": {
                "type": "boolean"
              },
              "isSystem": {
                "type": "boolean"
              },
              "locked": {
                "type": "boolean"
              },
              "sortOrder": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "overflowTargetAccountId": {
                "type": "string",
                "x-nullable": true
              },
              "overflowToPay": {
                "type": "boolean"
              }
            },
            "required": [
              "id",
              "kind",
              "code",
              "nameFi",
              "nameSv",
              "nameEn",
              "accrualSource",
              "capMaxMinutes",
              "capMinMinutes",
              "yearlyAccrualCapMinutes",
              "active",
              "isSystem",
              "locked",
              "sortOrder",
              "overflowTargetAccountId",
              "overflowToPay"
            ]
          }
        }
      },
      "required": [
        "accountTypes"
      ]
    },
    "DimensionListResponseDto": {
      "type": "object",
      "properties": {
        "dimensions": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "code": {
                "type": "string"
              },
              "nameFi": {
                "type": "string",
                "minLength": 1,
                "maxLength": 100
              },
              "nameSv": {
                "type": "string",
                "minLength": 1,
                "maxLength": 100
              },
              "nameEn": {
                "type": "string",
                "minLength": 1,
                "maxLength": 100
              },
              "required": {
                "type": "boolean"
              },
              "active": {
                "type": "boolean"
              },
              "locked": {
                "type": "boolean"
              },
              "allowsSplit": {
                "default": false,
                "type": "boolean"
              },
              "askInEntry": {
                "default": true,
                "type": "boolean"
              },
              "sortOrder": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "values": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "parentId": {
                      "type": "string",
                      "x-nullable": true
                    },
                    "code": {
                      "type": "string"
                    },
                    "name": {
                      "type": "string"
                    },
                    "active": {
                      "type": "boolean"
                    },
                    "sortOrder": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991
                    },
                    "path": {
                      "default": [],
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "defaultBillable": {
                      "type": "boolean",
                      "default": null,
                      "x-nullable": true
                    },
                    "customerName": {
                      "type": "string",
                      "default": null,
                      "x-nullable": true
                    }
                  },
                  "required": [
                    "id",
                    "parentId",
                    "code",
                    "name",
                    "active",
                    "sortOrder"
                  ]
                }
              },
              "recentValues": {
                "default": [],
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "parentId": {
                      "type": "string",
                      "x-nullable": true
                    },
                    "code": {
                      "type": "string"
                    },
                    "name": {
                      "type": "string"
                    },
                    "active": {
                      "type": "boolean"
                    },
                    "sortOrder": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991
                    },
                    "path": {
                      "default": [],
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "defaultBillable": {
                      "type": "boolean",
                      "default": null,
                      "x-nullable": true
                    },
                    "customerName": {
                      "type": "string",
                      "default": null,
                      "x-nullable": true
                    }
                  },
                  "required": [
                    "id",
                    "parentId",
                    "code",
                    "name",
                    "active",
                    "sortOrder"
                  ]
                }
              }
            },
            "required": [
              "id",
              "code",
              "nameFi",
              "nameSv",
              "nameEn",
              "required",
              "active",
              "locked",
              "sortOrder",
              "values"
            ]
          }
        }
      },
      "required": [
        "dimensions"
      ]
    },
    "CustomerPageResponseDto": {
      "type": "object",
      "properties": {
        "items": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "code": {
                "type": "string"
              },
              "name": {
                "type": "string"
              },
              "businessId": {
                "type": "string",
                "x-nullable": true
              },
              "einvoiceAddress": {
                "type": "string",
                "x-nullable": true
              },
              "einvoiceOperator": {
                "type": "string",
                "x-nullable": true
              },
              "invoiceReference": {
                "type": "string",
                "x-nullable": true
              },
              "billingRoundingMinutes": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991,
                "x-nullable": true
              },
              "active": {
                "type": "boolean"
              },
              "sortOrder": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "projectCount": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "streetAddress": {
                "type": "string",
                "x-nullable": true
              },
              "postalCode": {
                "type": "string",
                "x-nullable": true
              },
              "city": {
                "type": "string",
                "x-nullable": true
              },
              "country": {
                "type": "string",
                "x-nullable": true
              },
              "website": {
                "type": "string",
                "x-nullable": true
              },
              "industryCode": {
                "type": "string",
                "x-nullable": true
              },
              "notes": {
                "type": "string",
                "x-nullable": true
              },
              "ownerMembershipId": {
                "type": "string",
                "x-nullable": true
              },
              "defaultContactId": {
                "type": "string",
                "x-nullable": true
              },
              "vatId": {
                "type": "string",
                "x-nullable": true
              },
              "vatTreatment": {
                "type": "string",
                "enum": [
                  "standard",
                  "reverse_charge_construction",
                  "tax_exempt"
                ]
              },
              "invoiceEmail": {
                "type": "string",
                "x-nullable": true
              },
              "invoiceLanguage": {
                "type": "string",
                "enum": [
                  "fi",
                  "sv",
                  "en",
                  null
                ],
                "x-nullable": true
              },
              "deliveryMethod": {
                "type": "string",
                "enum": [
                  "einvoice",
                  "email",
                  "manual",
                  null
                ],
                "x-nullable": true
              },
              "defaultPaymentTermDays": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991,
                "x-nullable": true
              },
              "buyerReferenceDefault": {
                "type": "string",
                "x-nullable": true
              },
              "invoicingNotes": {
                "type": "string",
                "x-nullable": true
              },
              "fixedReferenceNumber": {
                "type": "string",
                "x-nullable": true
              },
              "paymentTermId": {
                "type": "string",
                "x-nullable": true
              },
              "paymentTermName": {
                "type": "string",
                "x-nullable": true
              },
              "openDealCount": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "openPipelineValueCents": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "lastActivityAt": {
                "type": "string",
                "x-nullable": true
              },
              "tags": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "name": {
                      "type": "string"
                    },
                    "color": {
                      "type": "string",
                      "x-nullable": true
                    }
                  },
                  "required": [
                    "id",
                    "name",
                    "color"
                  ]
                }
              },
              "updatedAt": {
                "type": "string"
              }
            },
            "required": [
              "id",
              "code",
              "name",
              "businessId",
              "einvoiceAddress",
              "einvoiceOperator",
              "invoiceReference",
              "billingRoundingMinutes",
              "active",
              "sortOrder",
              "projectCount",
              "streetAddress",
              "postalCode",
              "city",
              "country",
              "website",
              "industryCode",
              "notes",
              "ownerMembershipId",
              "defaultContactId",
              "vatId",
              "vatTreatment",
              "invoiceEmail",
              "invoiceLanguage",
              "deliveryMethod",
              "defaultPaymentTermDays",
              "buyerReferenceDefault",
              "invoicingNotes",
              "openDealCount",
              "openPipelineValueCents",
              "lastActivityAt",
              "tags",
              "updatedAt"
            ]
          }
        },
        "pageInfo": {
          "type": "object",
          "properties": {
            "nextCursor": {
              "type": "string",
              "x-nullable": true
            },
            "hasMore": {
              "type": "boolean"
            }
          },
          "required": [
            "nextCursor",
            "hasMore"
          ]
        }
      },
      "required": [
        "items",
        "pageInfo"
      ]
    },
    "CustomerGetResponseDto": {
      "type": "object",
      "properties": {
        "customer": {
          "type": "object",
          "properties": {
            "id": {
              "type": "string"
            },
            "code": {
              "type": "string"
            },
            "name": {
              "type": "string"
            },
            "businessId": {
              "type": "string",
              "x-nullable": true
            },
            "einvoiceAddress": {
              "type": "string",
              "x-nullable": true
            },
            "einvoiceOperator": {
              "type": "string",
              "x-nullable": true
            },
            "invoiceReference": {
              "type": "string",
              "x-nullable": true
            },
            "billingRoundingMinutes": {
              "type": "integer",
              "minimum": -9007199254740991,
              "maximum": 9007199254740991,
              "x-nullable": true
            },
            "active": {
              "type": "boolean"
            },
            "sortOrder": {
              "type": "integer",
              "minimum": -9007199254740991,
              "maximum": 9007199254740991
            },
            "projectCount": {
              "type": "integer",
              "minimum": -9007199254740991,
              "maximum": 9007199254740991
            },
            "streetAddress": {
              "type": "string",
              "x-nullable": true
            },
            "postalCode": {
              "type": "string",
              "x-nullable": true
            },
            "city": {
              "type": "string",
              "x-nullable": true
            },
            "country": {
              "type": "string",
              "x-nullable": true
            },
            "website": {
              "type": "string",
              "x-nullable": true
            },
            "industryCode": {
              "type": "string",
              "x-nullable": true
            },
            "notes": {
              "type": "string",
              "x-nullable": true
            },
            "ownerMembershipId": {
              "type": "string",
              "x-nullable": true
            },
            "defaultContactId": {
              "type": "string",
              "x-nullable": true
            },
            "vatId": {
              "type": "string",
              "x-nullable": true
            },
            "vatTreatment": {
              "type": "string",
              "enum": [
                "standard",
                "reverse_charge_construction",
                "tax_exempt"
              ]
            },
            "invoiceEmail": {
              "type": "string",
              "x-nullable": true
            },
            "invoiceLanguage": {
              "type": "string",
              "enum": [
                "fi",
                "sv",
                "en",
                null
              ],
              "x-nullable": true
            },
            "deliveryMethod": {
              "type": "string",
              "enum": [
                "einvoice",
                "email",
                "manual",
                null
              ],
              "x-nullable": true
            },
            "defaultPaymentTermDays": {
              "type": "integer",
              "minimum": -9007199254740991,
              "maximum": 9007199254740991,
              "x-nullable": true
            },
            "buyerReferenceDefault": {
              "type": "string",
              "x-nullable": true
            },
            "invoicingNotes": {
              "type": "string",
              "x-nullable": true
            },
            "fixedReferenceNumber": {
              "type": "string",
              "x-nullable": true
            },
            "paymentTermId": {
              "type": "string",
              "x-nullable": true
            },
            "paymentTermName": {
              "type": "string",
              "x-nullable": true
            },
            "openDealCount": {
              "type": "integer",
              "minimum": -9007199254740991,
              "maximum": 9007199254740991
            },
            "openPipelineValueCents": {
              "type": "integer",
              "minimum": -9007199254740991,
              "maximum": 9007199254740991
            },
            "lastActivityAt": {
              "type": "string",
              "x-nullable": true
            },
            "tags": {
              "type": "array",
              "items": {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "string"
                  },
                  "name": {
                    "type": "string"
                  },
                  "color": {
                    "type": "string",
                    "x-nullable": true
                  }
                },
                "required": [
                  "id",
                  "name",
                  "color"
                ]
              }
            },
            "updatedAt": {
              "type": "string"
            }
          },
          "required": [
            "id",
            "code",
            "name",
            "businessId",
            "einvoiceAddress",
            "einvoiceOperator",
            "invoiceReference",
            "billingRoundingMinutes",
            "active",
            "sortOrder",
            "projectCount",
            "streetAddress",
            "postalCode",
            "city",
            "country",
            "website",
            "industryCode",
            "notes",
            "ownerMembershipId",
            "defaultContactId",
            "vatId",
            "vatTreatment",
            "invoiceEmail",
            "invoiceLanguage",
            "deliveryMethod",
            "defaultPaymentTermDays",
            "buyerReferenceDefault",
            "invoicingNotes",
            "openDealCount",
            "openPipelineValueCents",
            "lastActivityAt",
            "tags",
            "updatedAt"
          ]
        }
      },
      "required": [
        "customer"
      ]
    },
    "CreateCustomerDto": {
      "type": "object",
      "properties": {
        "code": {
          "type": "string",
          "pattern": "^[a-z0-9][a-z0-9_-]{0,49}$"
        },
        "name": {
          "type": "string",
          "minLength": 1,
          "maxLength": 200
        },
        "businessId": {
          "type": "string",
          "maxLength": 20
        },
        "einvoiceAddress": {
          "type": "string",
          "maxLength": 50
        },
        "einvoiceOperator": {
          "type": "string",
          "maxLength": 50
        },
        "invoiceReference": {
          "type": "string",
          "maxLength": 50
        },
        "billingRoundingMinutes": {
          "type": "integer",
          "minimum": 1,
          "maximum": 480
        },
        "sortOrder": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991
        },
        "streetAddress": {
          "type": "string",
          "maxLength": 200
        },
        "postalCode": {
          "type": "string",
          "maxLength": 20
        },
        "city": {
          "type": "string",
          "maxLength": 100
        },
        "country": {
          "type": "string",
          "maxLength": 2
        },
        "website": {
          "type": "string",
          "maxLength": 200
        },
        "industryCode": {
          "type": "string",
          "maxLength": 20
        },
        "notes": {
          "type": "string",
          "maxLength": 8000
        },
        "ownerMembershipId": {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
        },
        "defaultContactId": {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
        },
        "vatId": {
          "type": "string",
          "maxLength": 20
        },
        "vatTreatment": {
          "type": "string",
          "enum": [
            "standard",
            "reverse_charge_construction",
            "tax_exempt"
          ]
        },
        "invoiceEmail": {
          "type": "string",
          "maxLength": 320,
          "format": "email",
          "pattern": "^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"
        },
        "invoiceLanguage": {
          "type": "string",
          "enum": [
            "fi",
            "sv",
            "en"
          ]
        },
        "deliveryMethod": {
          "type": "string",
          "enum": [
            "einvoice",
            "email",
            "manual"
          ]
        },
        "defaultPaymentTermDays": {
          "type": "integer",
          "minimum": 1,
          "maximum": 90
        },
        "buyerReferenceDefault": {
          "type": "string",
          "maxLength": 70
        },
        "invoicingNotes": {
          "type": "string",
          "maxLength": 2000
        },
        "fixedReferenceNumber": {
          "type": "string",
          "pattern": "^\\d{4,20}$"
        },
        "paymentTermId": {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
        }
      },
      "required": [
        "code",
        "name"
      ]
    },
    "CustomerIdResponseDto": {
      "type": "object",
      "properties": {
        "id": {
          "type": "string"
        }
      },
      "required": [
        "id"
      ]
    },
    "UpdateCustomerDto": {
      "type": "object",
      "properties": {
        "name": {
          "type": "string",
          "minLength": 1,
          "maxLength": 200
        },
        "businessId": {
          "type": "string",
          "maxLength": 20,
          "x-nullable": true
        },
        "einvoiceAddress": {
          "type": "string",
          "maxLength": 50,
          "x-nullable": true
        },
        "einvoiceOperator": {
          "type": "string",
          "maxLength": 50,
          "x-nullable": true
        },
        "invoiceReference": {
          "type": "string",
          "maxLength": 50,
          "x-nullable": true
        },
        "billingRoundingMinutes": {
          "type": "integer",
          "minimum": 1,
          "maximum": 480,
          "x-nullable": true
        },
        "active": {
          "type": "boolean"
        },
        "sortOrder": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991
        },
        "streetAddress": {
          "type": "string",
          "maxLength": 200,
          "x-nullable": true
        },
        "postalCode": {
          "type": "string",
          "maxLength": 20,
          "x-nullable": true
        },
        "city": {
          "type": "string",
          "maxLength": 100,
          "x-nullable": true
        },
        "country": {
          "type": "string",
          "maxLength": 2,
          "x-nullable": true
        },
        "website": {
          "type": "string",
          "maxLength": 200,
          "x-nullable": true
        },
        "industryCode": {
          "type": "string",
          "maxLength": 20,
          "x-nullable": true
        },
        "notes": {
          "type": "string",
          "maxLength": 8000,
          "x-nullable": true
        },
        "ownerMembershipId": {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
          "x-nullable": true
        },
        "defaultContactId": {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
          "x-nullable": true
        },
        "vatId": {
          "type": "string",
          "maxLength": 20,
          "x-nullable": true
        },
        "vatTreatment": {
          "type": "string",
          "enum": [
            "standard",
            "reverse_charge_construction",
            "tax_exempt"
          ]
        },
        "invoiceEmail": {
          "type": "string",
          "maxLength": 320,
          "format": "email",
          "pattern": "^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$",
          "x-nullable": true
        },
        "invoiceLanguage": {
          "type": "string",
          "enum": [
            "fi",
            "sv",
            "en",
            null
          ],
          "x-nullable": true
        },
        "deliveryMethod": {
          "type": "string",
          "enum": [
            "einvoice",
            "email",
            "manual",
            null
          ],
          "x-nullable": true
        },
        "defaultPaymentTermDays": {
          "type": "integer",
          "minimum": 1,
          "maximum": 90,
          "x-nullable": true
        },
        "buyerReferenceDefault": {
          "type": "string",
          "maxLength": 70,
          "x-nullable": true
        },
        "invoicingNotes": {
          "type": "string",
          "maxLength": 2000,
          "x-nullable": true
        },
        "fixedReferenceNumber": {
          "type": "string",
          "pattern": "^\\d{4,20}$",
          "x-nullable": true
        },
        "paymentTermId": {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
          "x-nullable": true
        },
        "expectedUpdatedAt": {
          "type": "string"
        }
      }
    },
    "CustomerOkResponseDto": {
      "type": "object",
      "properties": {
        "ok": {
          "type": "boolean"
        }
      },
      "required": [
        "ok"
      ]
    },
    "EmploymentResponseDto": {
      "type": "object",
      "properties": {
        "employment": {
          "type": "object",
          "properties": {
            "jobTitle": {
              "type": "string",
              "x-nullable": true
            },
            "employmentType": {
              "type": "string",
              "enum": [
                "permanent",
                "fixed_term"
              ]
            },
            "fixedTermGrounds": {
              "type": "string",
              "x-nullable": true
            },
            "fixedTermEndDate": {
              "type": "string",
              "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
              "x-nullable": true
            },
            "probationEndDate": {
              "type": "string",
              "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
              "x-nullable": true
            },
            "payType": {
              "type": "string",
              "enum": [
                "monthly",
                "hourly"
              ]
            },
            "contractWeeklyMinutes": {
              "type": "integer",
              "minimum": 0,
              "maximum": 9007199254740991,
              "x-nullable": true
            },
            "contractMinWeeklyMinutes": {
              "type": "integer",
              "minimum": 0,
              "maximum": 9007199254740991,
              "x-nullable": true
            },
            "placeOfWork": {
              "type": "string",
              "x-nullable": true
            },
            "placeOfWorkKind": {
              "type": "string",
              "enum": [
                "fixed",
                "varying",
                "remote",
                "no_fixed"
              ]
            },
            "employerId": {
              "type": "string",
              "x-nullable": true
            },
            "employerName": {
              "type": "string",
              "x-nullable": true
            },
            "payGroup": {
              "type": "string",
              "x-nullable": true
            },
            "payrollNumber": {
              "type": "string",
              "x-nullable": true
            },
            "pensionProvider": {
              "type": "string",
              "x-nullable": true
            },
            "accidentInsurer": {
              "type": "string",
              "x-nullable": true
            },
            "leaveAccrualRule": {
              "type": "string",
              "enum": [
                "14-day",
                "35-hour",
                null
              ],
              "x-nullable": true
            },
            "terminationReason": {
              "type": "string",
              "x-nullable": true
            },
            "terminationNoticeDate": {
              "type": "string",
              "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
              "x-nullable": true
            },
            "fixedTermRenewalCount": {
              "type": "integer",
              "minimum": 0,
              "maximum": 9007199254740991
            }
          },
          "required": [
            "jobTitle",
            "employmentType",
            "fixedTermGrounds",
            "fixedTermEndDate",
            "probationEndDate",
            "payType",
            "contractWeeklyMinutes",
            "contractMinWeeklyMinutes",
            "placeOfWork",
            "placeOfWorkKind",
            "employerId",
            "employerName",
            "payGroup",
            "payrollNumber",
            "pensionProvider",
            "accidentInsurer",
            "leaveAccrualRule",
            "terminationReason",
            "terminationNoticeDate",
            "fixedTermRenewalCount"
          ]
        }
      },
      "required": [
        "employment"
      ]
    },
    "UpdateEmploymentDto": {
      "type": "object",
      "properties": {
        "jobTitle": {
          "type": "string",
          "maxLength": 120,
          "x-nullable": true
        },
        "employmentType": {
          "type": "string",
          "enum": [
            "permanent",
            "fixed_term"
          ]
        },
        "fixedTermGrounds": {
          "type": "string",
          "maxLength": 500,
          "x-nullable": true
        },
        "fixedTermEndDate": {
          "type": "string",
          "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
          "x-nullable": true
        },
        "probationEndDate": {
          "type": "string",
          "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
          "x-nullable": true
        },
        "payType": {
          "type": "string",
          "enum": [
            "monthly",
            "hourly"
          ]
        },
        "payrollNumber": {
          "type": "string",
          "maxLength": 40,
          "x-nullable": true
        },
        "pensionProvider": {
          "type": "string",
          "maxLength": 120,
          "x-nullable": true
        },
        "accidentInsurer": {
          "type": "string",
          "maxLength": 120,
          "x-nullable": true
        },
        "leaveAccrualRule": {
          "type": "string",
          "enum": [
            "14-day",
            "35-hour",
            null
          ],
          "x-nullable": true
        },
        "employerId": {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
          "x-nullable": true
        }
      },
      "required": [
        "employmentType",
        "payType"
      ]
    },
    "EmploymentOkResponseDto": {
      "type": "object",
      "properties": {
        "ok": {
          "type": "boolean"
        }
      },
      "required": [
        "ok"
      ]
    },
    "PayrollIdentityViewDto": {
      "type": "object",
      "properties": {
        "membershipId": {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
        },
        "displayName": {
          "type": "string"
        },
        "payrollNumber": {
          "type": "string",
          "x-nullable": true
        }
      },
      "required": [
        "membershipId",
        "displayName",
        "payrollNumber"
      ]
    },
    "UpdatePayrollIdentityDto": {
      "type": "object",
      "properties": {
        "payrollNumber": {
          "type": "string",
          "maxLength": 40,
          "x-nullable": true
        }
      },
      "required": [
        "payrollNumber"
      ]
    },
    "TerminationResponseDto": {
      "type": "object",
      "properties": {
        "termination": {
          "type": "object",
          "properties": {
            "active": {
              "type": "boolean"
            },
            "endDate": {
              "type": "string",
              "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
              "x-nullable": true
            },
            "reasonCode": {
              "type": "string",
              "enum": [
                "resignation",
                "termination_person",
                "termination_finance",
                "fixed_term_end",
                "probation_cancellation",
                "rescission",
                "retirement",
                "mutual_agreement",
                "other",
                null
              ],
              "x-nullable": true
            },
            "noticeDate": {
              "type": "string",
              "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
              "x-nullable": true
            },
            "note": {
              "type": "string",
              "x-nullable": true
            },
            "offboardingRunId": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
              "x-nullable": true
            },
            "noticeDefaults": {
              "type": "object",
              "properties": {
                "serviceDays": {
                  "type": "integer",
                  "minimum": 0,
                  "maximum": 9007199254740991
                },
                "employer": {
                  "type": "object",
                  "properties": {
                    "unit": {
                      "type": "string",
                      "enum": [
                        "days",
                        "months"
                      ]
                    },
                    "value": {
                      "type": "integer",
                      "exclusiveMinimum": true,
                      "maximum": 9007199254740991,
                      "minimum": 0
                    }
                  },
                  "required": [
                    "unit",
                    "value"
                  ]
                },
                "employee": {
                  "type": "object",
                  "properties": {
                    "unit": {
                      "type": "string",
                      "enum": [
                        "days",
                        "months"
                      ]
                    },
                    "value": {
                      "type": "integer",
                      "exclusiveMinimum": true,
                      "maximum": 9007199254740991,
                      "minimum": 0
                    }
                  },
                  "required": [
                    "unit",
                    "value"
                  ]
                },
                "earliestEndDateEmployer": {
                  "type": "string",
                  "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
                },
                "earliestEndDateEmployee": {
                  "type": "string",
                  "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
                }
              },
              "required": [
                "serviceDays",
                "employer",
                "employee",
                "earliestEndDateEmployer",
                "earliestEndDateEmployee"
              ],
              "x-nullable": true
            }
          },
          "required": [
            "active",
            "endDate",
            "reasonCode",
            "noticeDate",
            "note",
            "offboardingRunId",
            "noticeDefaults"
          ]
        }
      },
      "required": [
        "termination"
      ]
    },
    "TerminateEmploymentDto": {
      "type": "object",
      "properties": {
        "endDate": {
          "type": "string",
          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
        },
        "reasonCode": {
          "type": "string",
          "enum": [
            "resignation",
            "termination_person",
            "termination_finance",
            "fixed_term_end",
            "probation_cancellation",
            "rescission",
            "retirement",
            "mutual_agreement",
            "other"
          ]
        },
        "noticeDate": {
          "type": "string",
          "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
          "x-nullable": true
        },
        "note": {
          "type": "string",
          "maxLength": 2000,
          "x-nullable": true
        },
        "startOffboarding": {
          "type": "boolean"
        },
        "offboardingTemplateId": {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
          "x-nullable": true
        }
      },
      "required": [
        "endDate",
        "reasonCode",
        "startOffboarding"
      ]
    },
    "AbsencePolicyListResponseDto": {
      "type": "object",
      "properties": {
        "policies": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "code": {
                "type": "string"
              },
              "nameFi": {
                "type": "string"
              },
              "nameSv": {
                "type": "string"
              },
              "nameEn": {
                "type": "string"
              },
              "dayTypeId": {
                "type": "string"
              },
              "dayTypeCode": {
                "type": "string"
              },
              "partialEntryTypeId": {
                "type": "string",
                "x-nullable": true
              },
              "workflowMode": {
                "type": "string",
                "enum": [
                  "request",
                  "notification",
                  "employer_assignment"
                ]
              },
              "sensitivity": {
                "type": "string",
                "enum": [
                  "normal",
                  "restricted",
                  "health"
                ]
              },
              "availabilityEffect": {
                "type": "string",
                "enum": [
                  "unavailable",
                  "none"
                ]
              },
              "consumesLeaveLedgerKind": {
                "type": "string",
                "enum": [
                  "annual_leave",
                  "additional_leave",
                  "free_time",
                  "saved_leave",
                  "bonus_leave",
                  null
                ],
                "x-nullable": true
              },
              "consumesAccount": {
                "type": "object",
                "properties": {
                  "accountTypeId": {
                    "type": "string"
                  },
                  "kind": {
                    "type": "string",
                    "enum": [
                      "flex",
                      "overtime_bank",
                      "worktime_bank",
                      "shorter_worktime"
                    ]
                  },
                  "code": {
                    "type": "string"
                  },
                  "nameFi": {
                    "type": "string"
                  },
                  "nameSv": {
                    "type": "string"
                  },
                  "nameEn": {
                    "type": "string"
                  }
                },
                "required": [
                  "accountTypeId",
                  "kind",
                  "code",
                  "nameFi",
                  "nameSv",
                  "nameEn"
                ],
                "default": null,
                "x-nullable": true
              },
              "requiresApproval": {
                "type": "boolean"
              },
              "certificateAfterDays": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991,
                "default": null,
                "x-nullable": true
              },
              "active": {
                "type": "boolean"
              },
              "sortOrder": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              }
            },
            "required": [
              "id",
              "code",
              "nameFi",
              "nameSv",
              "nameEn",
              "dayTypeId",
              "dayTypeCode",
              "partialEntryTypeId",
              "workflowMode",
              "sensitivity",
              "availabilityEffect",
              "consumesLeaveLedgerKind",
              "requiresApproval",
              "active",
              "sortOrder"
            ]
          }
        },
        "approver": {
          "type": "object",
          "properties": {
            "name": {
              "type": "string"
            }
          },
          "required": [
            "name"
          ],
          "x-nullable": true
        }
      },
      "required": [
        "policies"
      ]
    },
    "AbsencePeriodListResponseDto": {
      "type": "object",
      "properties": {
        "periods": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "membershipId": {
                "type": "string"
              },
              "memberName": {
                "type": "string",
                "x-nullable": true
              },
              "policyId": {
                "type": "string"
              },
              "policyCode": {
                "type": "string"
              },
              "policyNameFi": {
                "type": "string"
              },
              "policyNameSv": {
                "type": "string"
              },
              "policyNameEn": {
                "type": "string"
              },
              "sensitivity": {
                "type": "string",
                "enum": [
                  "normal",
                  "restricted",
                  "health"
                ]
              },
              "status": {
                "type": "string",
                "enum": [
                  "draft",
                  "submitted",
                  "approved",
                  "rejected",
                  "cancelled",
                  "withdrawn"
                ]
              },
              "origin": {
                "type": "string",
                "enum": [
                  "employee",
                  "planner"
                ]
              },
              "workflowMode": {
                "type": "string",
                "enum": [
                  "request",
                  "notification",
                  "employer_assignment"
                ]
              },
              "startDate": {
                "type": "string",
                "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
              },
              "endDate": {
                "type": "string",
                "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
              },
              "startHalfDay": {
                "type": "boolean"
              },
              "endHalfDay": {
                "type": "boolean"
              },
              "consumesQuarterDays": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "consumesMinutes": {
                "default": 0,
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "certificateRequired": {
                "default": false,
                "type": "boolean"
              },
              "certificateStatus": {
                "type": "string",
                "enum": [
                  "missing",
                  "provided",
                  "waived",
                  null
                ],
                "default": null,
                "x-nullable": true
              },
              "reason": {
                "type": "string",
                "x-nullable": true
              },
              "decidedByMembershipId": {
                "type": "string",
                "x-nullable": true
              },
              "decidedByName": {
                "type": "string",
                "x-nullable": true
              },
              "decidedAt": {
                "type": "string",
                "x-nullable": true
              },
              "decisionReason": {
                "type": "string",
                "x-nullable": true
              },
              "createdAt": {
                "type": "string"
              },
              "updatedAt": {
                "type": "string"
              },
              "viewerPermissions": {
                "type": "array",
                "items": {
                  "type": "string",
                  "enum": [
                    "viewCapacity",
                    "viewAbsenceDetail",
                    "requestForSelf",
                    "decideLeave",
                    "administerEntitlement"
                  ]
                }
              }
            },
            "required": [
              "id",
              "membershipId",
              "memberName",
              "policyId",
              "policyCode",
              "policyNameFi",
              "policyNameSv",
              "policyNameEn",
              "sensitivity",
              "status",
              "origin",
              "workflowMode",
              "startDate",
              "endDate",
              "startHalfDay",
              "endHalfDay",
              "consumesQuarterDays",
              "reason",
              "decidedByMembershipId",
              "decidedByName",
              "decidedAt",
              "decisionReason",
              "createdAt",
              "updatedAt",
              "viewerPermissions"
            ]
          }
        }
      },
      "required": [
        "periods"
      ]
    },
    "PreviewAbsencePeriodDto": {
      "type": "object",
      "properties": {
        "policyId": {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
        },
        "startDate": {
          "type": "string",
          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
        },
        "endDate": {
          "type": "string",
          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
        },
        "startHalfDay": {
          "type": "boolean"
        },
        "endHalfDay": {
          "type": "boolean"
        },
        "reason": {
          "type": "string",
          "maxLength": 1000
        },
        "excludePeriodId": {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
        }
      },
      "required": [
        "policyId",
        "startDate",
        "endDate"
      ]
    },
    "AbsencePeriodPreviewDto": {
      "type": "object",
      "properties": {
        "days": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "workDate": {
                "type": "string",
                "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
              },
              "available": {
                "type": "boolean"
              },
              "workRecordForm": {
                "type": "string",
                "enum": [
                  "none",
                  "day_type",
                  "entry_type"
                ]
              },
              "expectedTargetMinutes": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "expectedSource": {
                "type": "string",
                "x-nullable": true
              },
              "consumesEntitlement": {
                "type": "boolean"
              },
              "consumesQuarterDays": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "consumesAccountMinutes": {
                "default": 0,
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "exclusionReason": {
                "type": "string",
                "enum": [
                  "consumes",
                  "sunday",
                  "rest-day",
                  "exception-day",
                  "public-holiday",
                  "eve",
                  "easter-saturday",
                  "not-leave-policy",
                  "not-workday"
                ]
              },
              "sickWaitingDay": {
                "default": false,
                "type": "boolean"
              },
              "sickPayInfo": {
                "type": "object",
                "properties": {
                  "paid": {
                    "type": "boolean"
                  },
                  "percent": {
                    "type": "number"
                  },
                  "paidDayIndex": {
                    "type": "integer",
                    "minimum": -9007199254740991,
                    "maximum": 9007199254740991,
                    "x-nullable": true
                  }
                },
                "required": [
                  "paid",
                  "percent",
                  "paidDayIndex"
                ],
                "default": null,
                "x-nullable": true
              }
            },
            "required": [
              "workDate",
              "available",
              "workRecordForm",
              "expectedTargetMinutes",
              "expectedSource",
              "consumesEntitlement",
              "consumesQuarterDays",
              "exclusionReason"
            ]
          }
        },
        "consumesQuarterDays": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991
        },
        "consumesDays": {
          "type": "number"
        },
        "consumesAccountMinutes": {
          "default": 0,
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991
        },
        "bankBalanceSource": {
          "type": "object",
          "properties": {
            "account": {
              "type": "object",
              "properties": {
                "accountTypeId": {
                  "type": "string"
                },
                "kind": {
                  "type": "string",
                  "enum": [
                    "flex",
                    "overtime_bank",
                    "worktime_bank",
                    "shorter_worktime"
                  ]
                },
                "code": {
                  "type": "string"
                },
                "nameFi": {
                  "type": "string"
                },
                "nameSv": {
                  "type": "string"
                },
                "nameEn": {
                  "type": "string"
                }
              },
              "required": [
                "accountTypeId",
                "kind",
                "code",
                "nameFi",
                "nameSv",
                "nameEn"
              ]
            },
            "settledMinutes": {
              "type": "integer",
              "minimum": -9007199254740991,
              "maximum": 9007199254740991
            },
            "plannedDrawMinutes": {
              "type": "integer",
              "minimum": -9007199254740991,
              "maximum": 9007199254740991
            },
            "floorMinutes": {
              "type": "integer",
              "minimum": -9007199254740991,
              "maximum": 9007199254740991
            },
            "availableMinutes": {
              "type": "integer",
              "minimum": -9007199254740991,
              "maximum": 9007199254740991
            },
            "allowAdvance": {
              "type": "boolean"
            }
          },
          "required": [
            "account",
            "settledMinutes",
            "plannedDrawMinutes",
            "floorMinutes",
            "availableMinutes",
            "allowAdvance"
          ],
          "default": null,
          "x-nullable": true
        },
        "blockingErrors": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "warnings": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "conflicts": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "workDate": {
                "type": "string",
                "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
              },
              "type": {
                "type": "string",
                "enum": [
                  "existing-draft",
                  "confirmed-day",
                  "exported-day",
                  "published-shift",
                  "overlapping-period",
                  "outside-employment"
                ]
              }
            },
            "required": [
              "workDate",
              "type"
            ]
          }
        },
        "recordedDayBlocks": {
          "default": [],
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "workDate": {
                "type": "string",
                "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
              },
              "status": {
                "type": "string",
                "enum": [
                  "confirmed",
                  "approved"
                ]
              },
              "canReopen": {
                "type": "boolean"
              },
              "reopenBlockedReason": {
                "type": "string",
                "enum": [
                  "requires_supervisor",
                  "period_locked",
                  "day_invoiced",
                  null
                ],
                "default": null,
                "x-nullable": true
              }
            },
            "required": [
              "workDate",
              "status",
              "canReopen"
            ]
          }
        }
      },
      "required": [
        "days",
        "consumesQuarterDays",
        "consumesDays",
        "blockingErrors",
        "warnings",
        "conflicts"
      ]
    },
    "CreateAbsencePeriodDto": {
      "type": "object",
      "properties": {
        "policyId": {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
        },
        "startDate": {
          "type": "string",
          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
        },
        "endDate": {
          "type": "string",
          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
        },
        "startHalfDay": {
          "type": "boolean"
        },
        "endHalfDay": {
          "type": "boolean"
        },
        "reason": {
          "type": "string",
          "maxLength": 1000
        }
      },
      "required": [
        "policyId",
        "startDate",
        "endDate"
      ]
    },
    "AbsencePeriodDetailDto": {
      "type": "object",
      "properties": {
        "id": {
          "type": "string"
        },
        "membershipId": {
          "type": "string"
        },
        "memberName": {
          "type": "string",
          "x-nullable": true
        },
        "policyId": {
          "type": "string"
        },
        "policyCode": {
          "type": "string"
        },
        "policyNameFi": {
          "type": "string"
        },
        "policyNameSv": {
          "type": "string"
        },
        "policyNameEn": {
          "type": "string"
        },
        "sensitivity": {
          "type": "string",
          "enum": [
            "normal",
            "restricted",
            "health"
          ]
        },
        "status": {
          "type": "string",
          "enum": [
            "draft",
            "submitted",
            "approved",
            "rejected",
            "cancelled",
            "withdrawn"
          ]
        },
        "origin": {
          "type": "string",
          "enum": [
            "employee",
            "planner"
          ]
        },
        "workflowMode": {
          "type": "string",
          "enum": [
            "request",
            "notification",
            "employer_assignment"
          ]
        },
        "startDate": {
          "type": "string",
          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
        },
        "endDate": {
          "type": "string",
          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
        },
        "startHalfDay": {
          "type": "boolean"
        },
        "endHalfDay": {
          "type": "boolean"
        },
        "consumesQuarterDays": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991
        },
        "consumesMinutes": {
          "default": 0,
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991
        },
        "certificateRequired": {
          "default": false,
          "type": "boolean"
        },
        "certificateStatus": {
          "type": "string",
          "enum": [
            "missing",
            "provided",
            "waived",
            null
          ],
          "default": null,
          "x-nullable": true
        },
        "reason": {
          "type": "string",
          "x-nullable": true
        },
        "decidedByMembershipId": {
          "type": "string",
          "x-nullable": true
        },
        "decidedByName": {
          "type": "string",
          "x-nullable": true
        },
        "decidedAt": {
          "type": "string",
          "x-nullable": true
        },
        "decisionReason": {
          "type": "string",
          "x-nullable": true
        },
        "createdAt": {
          "type": "string"
        },
        "updatedAt": {
          "type": "string"
        },
        "viewerPermissions": {
          "type": "array",
          "items": {
            "type": "string",
            "enum": [
              "viewCapacity",
              "viewAbsenceDetail",
              "requestForSelf",
              "decideLeave",
              "administerEntitlement"
            ]
          }
        },
        "days": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "workDate": {
                "type": "string",
                "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
              },
              "available": {
                "type": "boolean"
              },
              "workRecordForm": {
                "type": "string",
                "enum": [
                  "none",
                  "day_type",
                  "entry_type"
                ]
              },
              "expectedTargetMinutes": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "expectedSource": {
                "type": "string",
                "x-nullable": true
              },
              "consumesEntitlement": {
                "type": "boolean"
              },
              "consumesQuarterDays": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "consumesAccountMinutes": {
                "default": 0,
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "exclusionReason": {
                "type": "string",
                "enum": [
                  "consumes",
                  "sunday",
                  "rest-day",
                  "exception-day",
                  "public-holiday",
                  "eve",
                  "easter-saturday",
                  "not-leave-policy",
                  "not-workday"
                ]
              },
              "sickWaitingDay": {
                "default": false,
                "type": "boolean"
              },
              "sickPayInfo": {
                "type": "object",
                "properties": {
                  "paid": {
                    "type": "boolean"
                  },
                  "percent": {
                    "type": "number"
                  },
                  "paidDayIndex": {
                    "type": "integer",
                    "minimum": -9007199254740991,
                    "maximum": 9007199254740991,
                    "x-nullable": true
                  }
                },
                "required": [
                  "paid",
                  "percent",
                  "paidDayIndex"
                ],
                "default": null,
                "x-nullable": true
              }
            },
            "required": [
              "workDate",
              "available",
              "workRecordForm",
              "expectedTargetMinutes",
              "expectedSource",
              "consumesEntitlement",
              "consumesQuarterDays",
              "exclusionReason"
            ]
          }
        },
        "events": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "type": {
                "type": "string",
                "enum": [
                  "submit",
                  "approve",
                  "reject",
                  "withdraw",
                  "cancel",
                  "postpone",
                  "modify",
                  "restore",
                  "certificate_provided",
                  "certificate_waived",
                  "certificate_reset"
                ]
              },
              "actorMembershipId": {
                "type": "string"
              },
              "actorName": {
                "type": "string"
              },
              "occurredAt": {
                "type": "string"
              },
              "reason": {
                "type": "string",
                "x-nullable": true
              }
            },
            "required": [
              "id",
              "type",
              "actorMembershipId",
              "actorName",
              "occurredAt",
              "reason"
            ]
          }
        },
        "comments": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "authorMembershipId": {
                "type": "string"
              },
              "authorName": {
                "type": "string"
              },
              "body": {
                "type": "string"
              },
              "createdAt": {
                "type": "string"
              }
            },
            "required": [
              "id",
              "authorMembershipId",
              "authorName",
              "body",
              "createdAt"
            ]
          }
        },
        "conflicts": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "workDate": {
                "type": "string",
                "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
              },
              "type": {
                "type": "string",
                "enum": [
                  "existing-draft",
                  "confirmed-day",
                  "exported-day",
                  "published-shift",
                  "overlapping-period",
                  "outside-employment"
                ]
              }
            },
            "required": [
              "workDate",
              "type"
            ]
          }
        },
        "planningUnitId": {
          "type": "string",
          "x-nullable": true
        },
        "consumesLeaveLedgerKind": {
          "type": "string",
          "enum": [
            "annual_leave",
            "additional_leave",
            "free_time",
            "saved_leave",
            "bonus_leave",
            null
          ],
          "x-nullable": true
        }
      },
      "required": [
        "id",
        "membershipId",
        "memberName",
        "policyId",
        "policyCode",
        "policyNameFi",
        "policyNameSv",
        "policyNameEn",
        "sensitivity",
        "status",
        "origin",
        "workflowMode",
        "startDate",
        "endDate",
        "startHalfDay",
        "endHalfDay",
        "consumesQuarterDays",
        "reason",
        "decidedByMembershipId",
        "decidedByName",
        "decidedAt",
        "decisionReason",
        "createdAt",
        "updatedAt",
        "viewerPermissions",
        "days",
        "events",
        "comments",
        "conflicts",
        "planningUnitId",
        "consumesLeaveLedgerKind"
      ]
    },
    "SubmitAbsencePeriodDto": {
      "type": "object",
      "properties": {
        "reopenRecordedDays": {
          "type": "boolean"
        }
      },
      "default": {}
    },
    "ApproveAbsencePeriodDto": {
      "type": "object",
      "properties": {
        "reason": {
          "type": "string",
          "maxLength": 500
        },
        "expectedUpdatedAt": {
          "type": "string"
        },
        "reopenRecordedDays": {
          "type": "boolean"
        }
      }
    },
    "TeamAbsenceResponseDto": {
      "type": "object",
      "properties": {
        "items": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "membershipId": {
                "type": "string"
              },
              "displayName": {
                "type": "string"
              },
              "periods": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "startDate": {
                      "type": "string",
                      "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
                    },
                    "endDate": {
                      "type": "string",
                      "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "draft",
                        "submitted",
                        "approved",
                        "rejected",
                        "cancelled",
                        "withdrawn"
                      ]
                    },
                    "updatedAt": {
                      "type": "string"
                    },
                    "workflowMode": {
                      "type": "string",
                      "enum": [
                        "request",
                        "notification",
                        "employer_assignment"
                      ]
                    },
                    "detail": {
                      "type": "object",
                      "properties": {
                        "policyCode": {
                          "type": "string"
                        },
                        "policyNameFi": {
                          "type": "string"
                        },
                        "policyNameSv": {
                          "type": "string"
                        },
                        "policyNameEn": {
                          "type": "string"
                        },
                        "consumesQuarterDays": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        "consumesLeaveLedgerKind": {
                          "type": "string",
                          "enum": [
                            "annual_leave",
                            "additional_leave",
                            "free_time",
                            "saved_leave",
                            "bonus_leave",
                            null
                          ],
                          "x-nullable": true
                        }
                      },
                      "required": [
                        "policyCode",
                        "policyNameFi",
                        "policyNameSv",
                        "policyNameEn",
                        "consumesQuarterDays",
                        "consumesLeaveLedgerKind"
                      ],
                      "x-nullable": true
                    }
                  },
                  "required": [
                    "id",
                    "startDate",
                    "endDate",
                    "status",
                    "updatedAt",
                    "workflowMode",
                    "detail"
                  ]
                }
              }
            },
            "required": [
              "membershipId",
              "displayName",
              "periods"
            ]
          }
        },
        "pageInfo": {
          "type": "object",
          "properties": {
            "nextCursor": {
              "type": "string",
              "x-nullable": true
            },
            "hasMore": {
              "type": "boolean"
            }
          },
          "required": [
            "nextCursor",
            "hasMore"
          ]
        },
        "blackouts": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "kind": {
                "type": "string",
                "enum": [
                  "blackout",
                  "wish_window"
                ]
              },
              "nameFi": {
                "type": "string"
              },
              "nameSv": {
                "type": "string"
              },
              "nameEn": {
                "type": "string"
              },
              "startDate": {
                "type": "string",
                "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
              },
              "endDate": {
                "type": "string",
                "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
              },
              "planningUnitId": {
                "type": "string",
                "x-nullable": true
              }
            },
            "required": [
              "id",
              "kind",
              "nameFi",
              "nameSv",
              "nameEn",
              "startDate",
              "endDate",
              "planningUnitId"
            ]
          }
        }
      },
      "required": [
        "items",
        "pageInfo",
        "blackouts"
      ]
    },
    "RejectAbsencePeriodDto": {
      "type": "object",
      "properties": {
        "reason": {
          "type": "string",
          "minLength": 3,
          "maxLength": 500
        },
        "expectedUpdatedAt": {
          "type": "string"
        }
      },
      "required": [
        "reason"
      ]
    },
    "PlanAbsencePeriodDto": {
      "type": "object",
      "properties": {
        "policyId": {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
        },
        "startDate": {
          "type": "string",
          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
        },
        "endDate": {
          "type": "string",
          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
        },
        "startHalfDay": {
          "type": "boolean"
        },
        "endHalfDay": {
          "type": "boolean"
        },
        "reason": {
          "type": "string",
          "maxLength": 1000
        },
        "membershipId": {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
        },
        "excludePeriodId": {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
        },
        "reopenRecordedDays": {
          "type": "boolean"
        }
      },
      "required": [
        "policyId",
        "startDate",
        "endDate",
        "membershipId"
      ]
    },
    "LeaveBalanceResponseDto": {
      "type": "object",
      "properties": {
        "membershipId": {
          "type": "string"
        },
        "asOf": {
          "type": "string",
          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
        },
        "creditYearEnd": {
          "type": "string",
          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
        },
        "balances": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "ledgerKind": {
                "type": "string",
                "enum": [
                  "annual_leave",
                  "additional_leave",
                  "free_time",
                  "saved_leave",
                  "bonus_leave"
                ]
              },
              "quarterDays": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "days": {
                "type": "number"
              },
              "recordedQuarterDays": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "recordedDays": {
                "type": "number"
              },
              "projectedQuarterDays": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "projectedDays": {
                "type": "number"
              }
            },
            "required": [
              "ledgerKind",
              "quarterDays",
              "days",
              "recordedQuarterDays",
              "recordedDays",
              "projectedQuarterDays",
              "projectedDays"
            ]
          }
        },
        "saveableQuarterDays": {
          "default": 0,
          "type": "integer",
          "minimum": 0,
          "maximum": 9007199254740991
        },
        "saveableDays": {
          "default": 0,
          "type": "number",
          "minimum": 0
        }
      },
      "required": [
        "membershipId",
        "asOf",
        "creditYearEnd",
        "balances"
      ]
    },
    "LeaveSaveProposalOkResponseDto": {
      "type": "object",
      "properties": {
        "ok": {
          "type": "boolean"
        }
      },
      "required": [
        "ok"
      ]
    },
    "ApproveLeaveSaveProposalDto": {
      "type": "object",
      "properties": {
        "expectedUpdatedAt": {
          "type": "string"
        }
      }
    },
    "DeclineLeaveSaveProposalDto": {
      "type": "object",
      "properties": {
        "reason": {
          "type": "string",
          "minLength": 3,
          "maxLength": 500
        },
        "expectedUpdatedAt": {
          "type": "string"
        }
      },
      "required": [
        "reason"
      ]
    },
    "MembershipListResponseDto": {
      "type": "object",
      "properties": {
        "items": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "displayName": {
                "type": "string"
              },
              "email": {
                "type": "string"
              },
              "role": {
                "type": "string",
                "enum": [
                  "employee",
                  "manager",
                  "admin",
                  "payroll",
                  "hr"
                ]
              },
              "managerMembershipId": {
                "type": "string",
                "x-nullable": true
              },
              "worktimeModelId": {
                "type": "string",
                "x-nullable": true
              },
              "planningUnitId": {
                "type": "string",
                "x-nullable": true
              },
              "canPlanAllUnits": {
                "type": "boolean"
              },
              "active": {
                "type": "boolean"
              },
              "employmentStartDate": {
                "type": "string",
                "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
                "x-nullable": true
              },
              "employmentEndDate": {
                "type": "string",
                "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
                "x-nullable": true
              },
              "personalFlexMinMinutes": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991,
                "x-nullable": true
              },
              "personalFlexMaxMinutes": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991,
                "x-nullable": true
              },
              "employer": {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "string"
                  },
                  "name": {
                    "type": "string"
                  }
                },
                "required": [
                  "id",
                  "name"
                ],
                "x-nullable": true
              },
              "invitationStatus": {
                "type": "string",
                "enum": [
                  "pending",
                  "accepted",
                  "expired",
                  null
                ],
                "x-nullable": true
              },
              "jobTitle": {
                "type": "string",
                "x-nullable": true
              },
              "fixedTermEndDate": {
                "type": "string",
                "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
                "x-nullable": true
              },
              "attention": {
                "type": "array",
                "items": {
                  "type": "string",
                  "enum": [
                    "statement_due",
                    "statement_update_due",
                    "probation_review",
                    "fixed_term_ending",
                    "qualification_expiring",
                    "qualification_expired"
                  ]
                },
                "x-nullable": true
              },
              "updatedAt": {
                "type": "string"
              }
            },
            "required": [
              "id",
              "displayName",
              "email",
              "role",
              "managerMembershipId",
              "worktimeModelId",
              "planningUnitId",
              "canPlanAllUnits",
              "active",
              "employmentStartDate",
              "employmentEndDate",
              "personalFlexMinMinutes",
              "personalFlexMaxMinutes",
              "employer",
              "invitationStatus",
              "jobTitle",
              "fixedTermEndDate",
              "attention",
              "updatedAt"
            ]
          }
        },
        "pageInfo": {
          "type": "object",
          "properties": {
            "nextCursor": {
              "type": "string",
              "x-nullable": true
            },
            "hasMore": {
              "type": "boolean"
            }
          },
          "required": [
            "nextCursor",
            "hasMore"
          ]
        }
      },
      "required": [
        "items",
        "pageInfo"
      ]
    },
    "MembershipDetailResponseDto": {
      "type": "object",
      "properties": {
        "id": {
          "type": "string"
        },
        "displayName": {
          "type": "string"
        },
        "email": {
          "type": "string"
        },
        "role": {
          "type": "string",
          "enum": [
            "employee",
            "manager",
            "admin",
            "payroll",
            "hr"
          ]
        },
        "managerMembershipId": {
          "type": "string",
          "x-nullable": true
        },
        "worktimeModelId": {
          "type": "string",
          "x-nullable": true
        },
        "planningUnitId": {
          "type": "string",
          "x-nullable": true
        },
        "canPlanAllUnits": {
          "type": "boolean"
        },
        "active": {
          "type": "boolean"
        },
        "employmentStartDate": {
          "type": "string",
          "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
          "x-nullable": true
        },
        "employmentEndDate": {
          "type": "string",
          "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
          "x-nullable": true
        },
        "personalFlexMinMinutes": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991,
          "x-nullable": true
        },
        "personalFlexMaxMinutes": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991,
          "x-nullable": true
        },
        "employer": {
          "type": "object",
          "properties": {
            "id": {
              "type": "string"
            },
            "name": {
              "type": "string"
            }
          },
          "required": [
            "id",
            "name"
          ],
          "x-nullable": true
        },
        "invitationStatus": {
          "type": "string",
          "enum": [
            "pending",
            "accepted",
            "expired",
            null
          ],
          "x-nullable": true
        },
        "jobTitle": {
          "type": "string",
          "x-nullable": true
        },
        "fixedTermEndDate": {
          "type": "string",
          "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
          "x-nullable": true
        },
        "attention": {
          "type": "array",
          "items": {
            "type": "string",
            "enum": [
              "statement_due",
              "statement_update_due",
              "probation_review",
              "fixed_term_ending",
              "qualification_expiring",
              "qualification_expired"
            ]
          },
          "x-nullable": true
        },
        "updatedAt": {
          "type": "string"
        },
        "managerName": {
          "type": "string",
          "x-nullable": true
        },
        "units": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "planningUnitId": {
                "type": "string"
              },
              "name": {
                "type": "string"
              },
              "isPrimary": {
                "type": "boolean"
              },
              "validFrom": {
                "type": "string"
              }
            },
            "required": [
              "planningUnitId",
              "name",
              "isPrimary",
              "validFrom"
            ]
          }
        },
        "leaveGroupId": {
          "type": "string",
          "x-nullable": true
        },
        "preferredLanguage": {
          "type": "string",
          "enum": [
            "fi",
            "sv",
            "en",
            null
          ],
          "x-nullable": true
        },
        "isMinor": {
          "type": "boolean"
        },
        "hrScopeUnitIds": {
          "type": "array",
          "items": {
            "type": "string",
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
          }
        },
        "hrRecorder": {
          "type": "boolean"
        },
        "crmSeat": {
          "type": "boolean"
        }
      },
      "required": [
        "id",
        "displayName",
        "email",
        "role",
        "managerMembershipId",
        "worktimeModelId",
        "planningUnitId",
        "canPlanAllUnits",
        "active",
        "employmentStartDate",
        "employmentEndDate",
        "personalFlexMinMinutes",
        "personalFlexMaxMinutes",
        "employer",
        "invitationStatus",
        "jobTitle",
        "fixedTermEndDate",
        "attention",
        "updatedAt",
        "managerName",
        "units",
        "leaveGroupId",
        "preferredLanguage",
        "isMinor",
        "hrScopeUnitIds",
        "hrRecorder",
        "crmSeat"
      ]
    },
    "CreateMembershipDto": {
      "type": "object",
      "properties": {
        "email": {
          "type": "string",
          "format": "email",
          "pattern": "^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"
        },
        "displayName": {
          "type": "string",
          "minLength": 1,
          "maxLength": 200
        },
        "role": {
          "type": "string",
          "enum": [
            "employee",
            "manager",
            "admin",
            "payroll",
            "hr"
          ]
        },
        "phone": {
          "type": "string",
          "maxLength": 40
        },
        "managerMembershipId": {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
          "x-nullable": true
        },
        "worktimeModelId": {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
          "x-nullable": true
        },
        "leaveGroupId": {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
          "x-nullable": true
        },
        "initialPassword": {
          "type": "string",
          "minLength": 10,
          "maxLength": 200
        },
        "locale": {
          "type": "string",
          "enum": [
            "fi",
            "sv",
            "en"
          ]
        },
        "moduleAccess": {
          "type": "array",
          "items": {
            "type": "string",
            "enum": [
              "shift_planning",
              "travel_expense",
              "hr",
              "project_management",
              "crm"
            ]
          }
        }
      },
      "required": [
        "displayName",
        "role"
      ]
    },
    "CreateMembershipResponseDto": {
      "type": "object",
      "properties": {
        "id": {
          "type": "string"
        },
        "invitation": {
          "type": "object",
          "properties": {
            "inviteUrl": {
              "type": "string"
            },
            "emailed": {
              "type": "boolean"
            },
            "expiresAt": {
              "type": "string"
            }
          },
          "required": [
            "inviteUrl",
            "emailed",
            "expiresAt"
          ],
          "x-nullable": true
        },
        "moduleGrants": {
          "type": "object",
          "properties": {
            "granted": {
              "type": "array",
              "items": {
                "type": "string",
                "enum": [
                  "shift_planning",
                  "travel_expense",
                  "hr",
                  "project_management",
                  "crm"
                ]
              }
            },
            "seatLimited": {
              "type": "array",
              "items": {
                "type": "string",
                "enum": [
                  "shift_planning",
                  "travel_expense",
                  "hr",
                  "project_management",
                  "crm"
                ]
              }
            }
          },
          "required": [
            "granted",
            "seatLimited"
          ]
        }
      },
      "required": [
        "id",
        "invitation",
        "moduleGrants"
      ]
    },
    "BulkCreateMembershipsDto": {
      "type": "object",
      "properties": {
        "rows": {
          "minItems": 1,
          "maxItems": 500,
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "email": {
                "type": "string",
                "format": "email",
                "pattern": "^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"
              },
              "displayName": {
                "type": "string",
                "minLength": 1,
                "maxLength": 200
              },
              "role": {
                "type": "string",
                "enum": [
                  "employee",
                  "manager",
                  "admin",
                  "payroll",
                  "hr"
                ]
              },
              "phone": {
                "type": "string",
                "maxLength": 40
              },
              "managerMembershipId": {
                "type": "string",
                "format": "uuid",
                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                "x-nullable": true
              },
              "managerEmail": {
                "type": "string",
                "format": "email",
                "pattern": "^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"
              },
              "worktimeModelId": {
                "type": "string",
                "format": "uuid",
                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                "x-nullable": true
              },
              "unitName": {
                "type": "string",
                "maxLength": 200
              },
              "worktimeModelName": {
                "type": "string",
                "maxLength": 200
              },
              "employerCode": {
                "type": "string",
                "maxLength": 40
              },
              "employmentStartDate": {
                "type": "string",
                "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
              },
              "employmentEndDate": {
                "type": "string",
                "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
              },
              "employmentType": {
                "type": "string",
                "enum": [
                  "permanent",
                  "fixed_term"
                ]
              },
              "jobTitle": {
                "type": "string",
                "maxLength": 120
              },
              "locale": {
                "type": "string",
                "enum": [
                  "fi",
                  "sv",
                  "en"
                ]
              }
            },
            "required": [
              "displayName",
              "role"
            ]
          }
        },
        "locale": {
          "type": "string",
          "enum": [
            "fi",
            "sv",
            "en"
          ]
        },
        "initialPassword": {
          "type": "string",
          "minLength": 10,
          "maxLength": 200
        },
        "moduleAccess": {
          "type": "array",
          "items": {
            "type": "string",
            "enum": [
              "shift_planning",
              "travel_expense",
              "hr",
              "project_management",
              "crm"
            ]
          }
        }
      },
      "required": [
        "rows"
      ]
    },
    "BulkCreateMembershipsResponseDto": {
      "type": "object",
      "properties": {
        "results": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "email": {
                "type": "string"
              },
              "displayName": {
                "type": "string"
              },
              "status": {
                "type": "string",
                "enum": [
                  "invited",
                  "created",
                  "skipped",
                  "error"
                ]
              },
              "membershipId": {
                "type": "string",
                "x-nullable": true
              },
              "code": {
                "type": "string",
                "x-nullable": true
              },
              "grantedModules": {
                "type": "array",
                "items": {
                  "type": "string",
                  "enum": [
                    "shift_planning",
                    "travel_expense",
                    "hr",
                    "project_management",
                    "crm"
                  ]
                }
              },
              "seatLimitedModules": {
                "type": "array",
                "items": {
                  "type": "string",
                  "enum": [
                    "shift_planning",
                    "travel_expense",
                    "hr",
                    "project_management",
                    "crm"
                  ]
                }
              }
            },
            "required": [
              "email",
              "displayName",
              "status",
              "membershipId",
              "code",
              "grantedModules",
              "seatLimitedModules"
            ]
          }
        }
      },
      "required": [
        "results"
      ]
    },
    "InviteMemberDto": {
      "type": "object",
      "properties": {
        "locale": {
          "type": "string",
          "enum": [
            "fi",
            "sv",
            "en"
          ]
        }
      }
    },
    "MembershipInviteResultDto": {
      "type": "object",
      "properties": {
        "inviteUrl": {
          "type": "string"
        },
        "emailed": {
          "type": "boolean"
        },
        "expiresAt": {
          "type": "string"
        }
      },
      "required": [
        "inviteUrl",
        "emailed",
        "expiresAt"
      ]
    },
    "UpdateMembershipDto": {
      "type": "object",
      "properties": {
        "role": {
          "type": "string",
          "enum": [
            "employee",
            "manager",
            "admin",
            "payroll",
            "hr"
          ]
        },
        "managerMembershipId": {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
          "x-nullable": true
        },
        "worktimeModelId": {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
          "x-nullable": true
        },
        "planningUnitId": {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
          "x-nullable": true
        },
        "leaveGroupId": {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
          "x-nullable": true
        },
        "canPlanAllUnits": {
          "type": "boolean"
        },
        "hrScopeUnitIds": {
          "type": "array",
          "items": {
            "type": "string",
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
          }
        },
        "hrRecorder": {
          "type": "boolean"
        },
        "crmSeat": {
          "type": "boolean"
        },
        "employmentStartDate": {
          "type": "string",
          "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
          "x-nullable": true
        },
        "employmentEndDate": {
          "type": "string",
          "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
          "x-nullable": true
        },
        "personalFlexMinMinutes": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991,
          "x-nullable": true
        },
        "personalFlexMaxMinutes": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991,
          "x-nullable": true
        }
      }
    },
    "MembershipOkResponseDto": {
      "type": "object",
      "properties": {
        "ok": {
          "type": "boolean"
        }
      },
      "required": [
        "ok"
      ]
    },
    "AddMembershipUnitDto": {
      "type": "object",
      "properties": {
        "planningUnitId": {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
        }
      },
      "required": [
        "planningUnitId"
      ]
    },
    "DeactivateMembershipResponseDto": {
      "type": "object",
      "properties": {
        "ok": {
          "type": "boolean"
        },
        "orphanedServiceKeys": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "name": {
                "type": "string"
              }
            },
            "required": [
              "id",
              "name"
            ]
          }
        }
      },
      "required": [
        "ok",
        "orphanedServiceKeys"
      ]
    },
    "TrainingRequestOkResponseDto": {
      "type": "object",
      "properties": {
        "ok": {
          "type": "boolean"
        }
      },
      "required": [
        "ok"
      ]
    },
    "ApproveTrainingRequestDto": {
      "type": "object",
      "properties": {
        "expectedUpdatedAt": {
          "type": "string"
        }
      }
    },
    "DeclineTrainingRequestDto": {
      "type": "object",
      "properties": {
        "reason": {
          "type": "string",
          "minLength": 1,
          "maxLength": 2000
        },
        "expectedUpdatedAt": {
          "type": "string"
        }
      },
      "required": [
        "reason"
      ]
    },
    "ProjectPortfolioAttentionResponseDto": {
      "type": "object",
      "properties": {
        "projectCount": {
          "type": "integer",
          "minimum": 0,
          "maximum": 9007199254740991
        },
        "attentionProjectCount": {
          "type": "integer",
          "minimum": 0,
          "maximum": 9007199254740991
        },
        "overBudgetCount": {
          "type": "integer",
          "minimum": 0,
          "maximum": 9007199254740991
        },
        "atRiskCount": {
          "type": "integer",
          "minimum": 0,
          "maximum": 9007199254740991
        },
        "overdueTaskCount": {
          "type": "integer",
          "minimum": 0,
          "maximum": 9007199254740991
        },
        "readyToBillCents": {
          "type": "integer",
          "minimum": 0,
          "maximum": 9007199254740991
        },
        "overdueInvoiceCount": {
          "type": "integer",
          "minimum": 0,
          "maximum": 9007199254740991
        },
        "overdueInvoiceCents": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991
        }
      },
      "required": [
        "projectCount",
        "attentionProjectCount",
        "overBudgetCount",
        "atRiskCount",
        "overdueTaskCount"
      ]
    },
    "ProjectRosterResponseDto": {
      "type": "object",
      "properties": {
        "items": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "projectId": {
                "type": "string"
              },
              "code": {
                "type": "string"
              },
              "name": {
                "type": "string"
              },
              "customerId": {
                "type": "string",
                "x-nullable": true
              },
              "customerName": {
                "type": "string",
                "x-nullable": true
              },
              "ownerMembershipId": {
                "type": "string",
                "x-nullable": true
              },
              "ownerName": {
                "type": "string",
                "x-nullable": true
              },
              "status": {
                "type": "string",
                "enum": [
                  "draft",
                  "active",
                  "on_hold",
                  "closed"
                ]
              },
              "billingModel": {
                "type": "string",
                "enum": [
                  "time_materials",
                  "fixed_price",
                  "non_billable",
                  "retainer"
                ]
              },
              "startDate": {
                "type": "string",
                "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
                "x-nullable": true
              },
              "endDate": {
                "type": "string",
                "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
                "x-nullable": true
              },
              "health": {
                "type": "string",
                "enum": [
                  "on_track",
                  "at_risk",
                  "over_budget",
                  "no_data"
                ]
              },
              "minutes": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "billableMinutes": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "lifetimeMinutes": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "revenueBasis": {
                "type": "string",
                "enum": [
                  "worked",
                  "invoiced"
                ]
              },
              "revenueCents": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991,
                "x-nullable": true
              },
              "contractValueCents": {
                "type": "integer",
                "minimum": 0,
                "maximum": 9007199254740991,
                "x-nullable": true
              },
              "approvedChangeOrderCents": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "invoicedLifetimeCents": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991,
                "x-nullable": true
              },
              "costCents": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991,
                "x-nullable": true
              },
              "marginCents": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991,
                "x-nullable": true
              },
              "marginPct": {
                "type": "number",
                "x-nullable": true
              },
              "expenseCostCents": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991,
                "x-nullable": true
              },
              "expenseRevenueCents": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "purchaseCostCents": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991,
                "x-nullable": true
              },
              "purchaseRevenueCents": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "unpricedBillableMinutes": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "uncostedMinutes": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991,
                "x-nullable": true
              },
              "budgetMinutes": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991,
                "x-nullable": true
              },
              "budgetAmountCents": {
                "type": "integer",
                "minimum": 0,
                "maximum": 9007199254740991,
                "x-nullable": true
              },
              "budgetMinutesUsedPct": {
                "type": "number",
                "x-nullable": true
              },
              "budgetAmountUsedPct": {
                "type": "number",
                "x-nullable": true
              },
              "openTaskCount": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "overdueTaskCount": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "healthReasons": {
                "type": "array",
                "items": {
                  "type": "string",
                  "enum": [
                    "over_budget",
                    "past_end",
                    "near_budget",
                    "thin_margin",
                    "losing",
                    "tasks_overdue"
                  ]
                }
              },
              "statusUpdate": {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "string"
                  },
                  "rag": {
                    "type": "string",
                    "enum": [
                      "on_track",
                      "at_risk",
                      "off_track"
                    ]
                  },
                  "note": {
                    "type": "string"
                  },
                  "authorName": {
                    "type": "string",
                    "x-nullable": true
                  },
                  "createdAt": {
                    "type": "string",
                    "format": "date-time",
                    "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
                  }
                },
                "required": [
                  "id",
                  "rag",
                  "note",
                  "authorName",
                  "createdAt"
                ],
                "x-nullable": true
              },
              "situation": {
                "type": "string",
                "enum": [
                  "on_track",
                  "at_risk",
                  "off_track",
                  "none"
                ]
              },
              "situationSource": {
                "type": "string",
                "enum": [
                  "update",
                  "computed"
                ]
              },
              "unbilledCents": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991,
                "x-nullable": true
              }
            },
            "required": [
              "projectId",
              "code",
              "name",
              "customerId",
              "customerName",
              "ownerMembershipId",
              "ownerName",
              "status",
              "billingModel",
              "startDate",
              "endDate",
              "health",
              "minutes",
              "billableMinutes",
              "lifetimeMinutes",
              "revenueBasis",
              "revenueCents",
              "contractValueCents",
              "approvedChangeOrderCents",
              "invoicedLifetimeCents",
              "costCents",
              "marginCents",
              "marginPct",
              "expenseCostCents",
              "expenseRevenueCents",
              "purchaseCostCents",
              "purchaseRevenueCents",
              "unpricedBillableMinutes",
              "uncostedMinutes",
              "budgetMinutes",
              "budgetAmountCents",
              "budgetMinutesUsedPct",
              "budgetAmountUsedPct",
              "openTaskCount",
              "overdueTaskCount",
              "healthReasons",
              "statusUpdate",
              "situation",
              "situationSource",
              "unbilledCents"
            ]
          }
        },
        "pageInfo": {
          "type": "object",
          "properties": {
            "nextCursor": {
              "type": "string",
              "x-nullable": true
            },
            "hasMore": {
              "type": "boolean"
            }
          },
          "required": [
            "nextCursor",
            "hasMore"
          ]
        },
        "includesCost": {
          "type": "boolean"
        },
        "kpis": {
          "type": "object",
          "properties": {
            "projectCount": {
              "type": "integer",
              "minimum": 0,
              "maximum": 9007199254740991
            },
            "totalMinutes": {
              "type": "integer",
              "minimum": -9007199254740991,
              "maximum": 9007199254740991
            },
            "totalRevenueCents": {
              "type": "integer",
              "minimum": -9007199254740991,
              "maximum": 9007199254740991
            },
            "avgMarginPct": {
              "type": "number",
              "x-nullable": true
            },
            "overBudgetCount": {
              "type": "integer",
              "minimum": 0,
              "maximum": 9007199254740991
            },
            "unbilledProjectCount": {
              "type": "integer",
              "minimum": 0,
              "maximum": 9007199254740991,
              "x-nullable": true
            }
          },
          "required": [
            "projectCount",
            "totalMinutes",
            "totalRevenueCents",
            "avgMarginPct",
            "overBudgetCount",
            "unbilledProjectCount"
          ]
        }
      },
      "required": [
        "items",
        "pageInfo",
        "includesCost",
        "kpis"
      ]
    },
    "ProjectOverviewResponseDto": {
      "type": "object",
      "properties": {
        "attention": {
          "type": "object",
          "properties": {
            "items": {
              "type": "array",
              "items": {
                "type": "object",
                "properties": {
                  "kind": {
                    "type": "string",
                    "enum": [
                      "overdue",
                      "blocked",
                      "waiting"
                    ]
                  },
                  "taskId": {
                    "type": "string",
                    "x-nullable": true
                  },
                  "title": {
                    "type": "string"
                  },
                  "taskKey": {
                    "type": "string",
                    "x-nullable": true
                  }
                },
                "required": [
                  "kind",
                  "taskId",
                  "title",
                  "taskKey"
                ]
              }
            },
            "more": {
              "type": "integer",
              "minimum": 0,
              "maximum": 9007199254740991
            }
          },
          "required": [
            "items",
            "more"
          ]
        },
        "milestones": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "name": {
                "type": "string"
              },
              "date": {
                "type": "string",
                "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
              },
              "taskCount": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "past": {
                "type": "boolean"
              }
            },
            "required": [
              "id",
              "name",
              "date",
              "taskCount",
              "past"
            ]
          }
        },
        "completion": {
          "type": "object",
          "properties": {
            "done": {
              "type": "integer",
              "minimum": -9007199254740991,
              "maximum": 9007199254740991
            },
            "countable": {
              "type": "integer",
              "minimum": -9007199254740991,
              "maximum": 9007199254740991
            },
            "pct": {
              "type": "integer",
              "minimum": -9007199254740991,
              "maximum": 9007199254740991
            },
            "earnedPct": {
              "type": "integer",
              "minimum": -9007199254740991,
              "maximum": 9007199254740991,
              "x-nullable": true
            },
            "spiAvailable": {
              "type": "boolean"
            }
          },
          "required": [
            "done",
            "countable",
            "pct",
            "earnedPct",
            "spiAvailable"
          ]
        },
        "budget": {
          "type": "object",
          "properties": {
            "budgetMinutes": {
              "type": "integer",
              "minimum": -9007199254740991,
              "maximum": 9007199254740991,
              "x-nullable": true
            },
            "lifetimeMinutes": {
              "type": "integer",
              "minimum": -9007199254740991,
              "maximum": 9007199254740991
            },
            "budgetMinutesUsedPct": {
              "type": "number",
              "x-nullable": true
            },
            "budgetAmountCents": {
              "type": "integer",
              "minimum": 0,
              "maximum": 9007199254740991,
              "x-nullable": true
            },
            "budgetAmountUsedPct": {
              "type": "number",
              "x-nullable": true
            },
            "forecast": {
              "type": "object",
              "properties": {
                "eacMinutes": {
                  "type": "integer",
                  "minimum": -9007199254740991,
                  "maximum": 9007199254740991
                },
                "eacBudgetMinutesPct": {
                  "type": "number",
                  "x-nullable": true
                },
                "overBudgetMinutes": {
                  "type": "boolean"
                }
              },
              "required": [
                "eacMinutes",
                "eacBudgetMinutesPct",
                "overBudgetMinutes"
              ],
              "x-nullable": true
            }
          },
          "required": [
            "budgetMinutes",
            "lifetimeMinutes",
            "budgetMinutesUsedPct",
            "budgetAmountCents",
            "budgetAmountUsedPct",
            "forecast"
          ]
        },
        "margin": {
          "type": "object",
          "properties": {
            "marginCents": {
              "type": "integer",
              "minimum": -9007199254740991,
              "maximum": 9007199254740991,
              "x-nullable": true
            },
            "marginPct": {
              "type": "number",
              "x-nullable": true
            },
            "tesDeltaCents": {
              "type": "integer",
              "minimum": -9007199254740991,
              "maximum": 9007199254740991,
              "x-nullable": true
            }
          },
          "required": [
            "marginCents",
            "marginPct",
            "tesDeltaCents"
          ],
          "x-nullable": true
        },
        "unbilled": {
          "type": "object",
          "properties": {
            "taskCount": {
              "type": "integer",
              "minimum": -9007199254740991,
              "maximum": 9007199254740991
            },
            "lineCount": {
              "type": "integer",
              "minimum": -9007199254740991,
              "maximum": 9007199254740991
            },
            "totalCents": {
              "type": "integer",
              "minimum": -9007199254740991,
              "maximum": 9007199254740991
            },
            "unpricedLineCount": {
              "type": "integer",
              "minimum": -9007199254740991,
              "maximum": 9007199254740991
            }
          },
          "required": [
            "taskCount",
            "lineCount",
            "totalCents",
            "unpricedLineCount"
          ],
          "x-nullable": true
        },
        "team": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "memberName": {
                "type": "string"
              },
              "plannedMinutesPerWeek": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991,
                "x-nullable": true
              }
            },
            "required": [
              "id",
              "memberName",
              "plannedMinutesPerWeek"
            ]
          }
        },
        "recentActivity": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "workDate": {
                "type": "string",
                "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
              },
              "memberName": {
                "type": "string"
              },
              "valueName": {
                "type": "string"
              },
              "minutes": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "entryCount": {
                "type": "integer",
                "exclusiveMinimum": true,
                "maximum": 9007199254740991,
                "minimum": 0
              }
            },
            "required": [
              "workDate",
              "memberName",
              "valueName",
              "minutes",
              "entryCount"
            ]
          }
        },
        "feed": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "at": {
                "type": "string",
                "format": "date-time",
                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
              },
              "kind": {
                "type": "string",
                "enum": [
                  "task_activity",
                  "status_update",
                  "baseline_set",
                  "approval_response",
                  "purchase_added"
                ]
              },
              "actorName": {
                "type": "string",
                "x-nullable": true
              },
              "taskId": {
                "type": "string",
                "x-nullable": true
              },
              "taskKey": {
                "type": "string",
                "x-nullable": true
              },
              "taskTitle": {
                "type": "string",
                "x-nullable": true
              },
              "activityType": {
                "type": "string",
                "x-nullable": true
              },
              "statusFrom": {
                "type": "string",
                "x-nullable": true
              },
              "statusTo": {
                "type": "string",
                "x-nullable": true
              },
              "rag": {
                "type": "string",
                "enum": [
                  "on_track",
                  "at_risk",
                  "off_track",
                  null
                ],
                "x-nullable": true
              },
              "note": {
                "type": "string",
                "x-nullable": true
              },
              "decision": {
                "type": "string",
                "enum": [
                  "approved",
                  "changes_requested",
                  null
                ],
                "x-nullable": true
              },
              "subjectTitle": {
                "type": "string",
                "x-nullable": true
              },
              "description": {
                "type": "string",
                "x-nullable": true
              }
            },
            "required": [
              "at",
              "kind",
              "actorName",
              "taskId",
              "taskKey",
              "taskTitle",
              "activityType",
              "statusFrom",
              "statusTo",
              "rag",
              "note",
              "decision",
              "subjectTitle",
              "description"
            ]
          }
        },
        "sourceQuote": {
          "type": "object",
          "properties": {
            "id": {
              "type": "string"
            },
            "displayKey": {
              "type": "string"
            },
            "title": {
              "type": "string"
            },
            "totalNetCents": {
              "type": "integer",
              "minimum": -9007199254740991,
              "maximum": 9007199254740991
            }
          },
          "required": [
            "id",
            "displayKey",
            "title",
            "totalNetCents"
          ],
          "x-nullable": true
        },
        "statusUpdate": {
          "type": "object",
          "properties": {
            "id": {
              "type": "string"
            },
            "rag": {
              "type": "string",
              "enum": [
                "on_track",
                "at_risk",
                "off_track"
              ]
            },
            "note": {
              "type": "string"
            },
            "authorName": {
              "type": "string",
              "x-nullable": true
            },
            "createdAt": {
              "type": "string",
              "format": "date-time",
              "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
            }
          },
          "required": [
            "id",
            "rag",
            "note",
            "authorName",
            "createdAt"
          ],
          "x-nullable": true
        }
      },
      "required": [
        "attention",
        "milestones",
        "completion",
        "budget",
        "margin",
        "unbilled",
        "team",
        "recentActivity",
        "feed",
        "sourceQuote",
        "statusUpdate"
      ]
    },
    "TaskBoardResponseDto": {
      "type": "object",
      "properties": {
        "source": {
          "type": "string",
          "enum": [
            "project",
            "tenant_default"
          ]
        },
        "statuses": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "projectId": {
                "type": "string",
                "x-nullable": true
              },
              "name": {
                "type": "string"
              },
              "color": {
                "type": "string",
                "x-nullable": true
              },
              "category": {
                "type": "string",
                "enum": [
                  "todo",
                  "in_progress",
                  "done",
                  "cancelled"
                ]
              },
              "sortOrder": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "wipLimit": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991,
                "x-nullable": true
              },
              "taskCount": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              }
            },
            "required": [
              "id",
              "projectId",
              "name",
              "color",
              "category",
              "sortOrder",
              "wipLimit",
              "taskCount"
            ]
          }
        },
        "columns": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "statusId": {
                "type": "string"
              },
              "tasks": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "projectId": {
                      "type": "string"
                    },
                    "number": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991
                    },
                    "phaseId": {
                      "type": "string",
                      "x-nullable": true
                    },
                    "phaseName": {
                      "type": "string",
                      "x-nullable": true
                    },
                    "phaseSortOrder": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991,
                      "x-nullable": true
                    },
                    "dimensionValueId": {
                      "type": "string",
                      "x-nullable": true
                    },
                    "title": {
                      "type": "string"
                    },
                    "description": {
                      "type": "string",
                      "x-nullable": true
                    },
                    "statusId": {
                      "type": "string"
                    },
                    "statusCategory": {
                      "type": "string",
                      "enum": [
                        "todo",
                        "in_progress",
                        "done",
                        "cancelled"
                      ]
                    },
                    "assigneeMembershipId": {
                      "type": "string",
                      "x-nullable": true
                    },
                    "assigneeName": {
                      "type": "string",
                      "x-nullable": true
                    },
                    "priority": {
                      "type": "string",
                      "enum": [
                        "low",
                        "normal",
                        "high",
                        "urgent"
                      ]
                    },
                    "startDate": {
                      "type": "string",
                      "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
                      "x-nullable": true
                    },
                    "dueDate": {
                      "type": "string",
                      "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
                      "x-nullable": true
                    },
                    "estimateMinutes": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991,
                      "x-nullable": true
                    },
                    "progressPct": {
                      "type": "integer",
                      "minimum": 0,
                      "maximum": 100,
                      "x-nullable": true
                    },
                    "sortKey": {
                      "type": "string"
                    },
                    "milestoneId": {
                      "type": "string",
                      "x-nullable": true
                    },
                    "tags": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "name": {
                            "type": "string"
                          },
                          "color": {
                            "type": "string",
                            "x-nullable": true
                          }
                        },
                        "required": [
                          "id",
                          "name",
                          "color"
                        ]
                      }
                    },
                    "recurrenceId": {
                      "type": "string",
                      "x-nullable": true
                    },
                    "fieldValues": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "fieldId": {
                            "type": "string"
                          },
                          "value": {}
                        },
                        "required": [
                          "fieldId",
                          "value"
                        ]
                      }
                    },
                    "archivedAt": {
                      "type": "string",
                      "x-nullable": true
                    },
                    "checklistDoneCount": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991
                    },
                    "checklistTotalCount": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991
                    },
                    "commentCount": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991
                    },
                    "actualMinutes": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991,
                      "x-nullable": true
                    },
                    "updatedAt": {
                      "type": "string"
                    },
                    "createdAt": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "id",
                    "projectId",
                    "number",
                    "phaseId",
                    "phaseName",
                    "phaseSortOrder",
                    "dimensionValueId",
                    "title",
                    "statusId",
                    "statusCategory",
                    "assigneeMembershipId",
                    "assigneeName",
                    "priority",
                    "startDate",
                    "dueDate",
                    "estimateMinutes",
                    "progressPct",
                    "sortKey",
                    "milestoneId",
                    "tags",
                    "recurrenceId",
                    "fieldValues",
                    "archivedAt",
                    "checklistDoneCount",
                    "checklistTotalCount",
                    "commentCount",
                    "actualMinutes",
                    "updatedAt",
                    "createdAt"
                  ]
                }
              },
              "totalCount": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "hasMore": {
                "type": "boolean"
              }
            },
            "required": [
              "statusId",
              "tasks",
              "totalCount",
              "hasMore"
            ]
          }
        },
        "dependencies": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "predecessorTaskId": {
                "type": "string"
              },
              "successorTaskId": {
                "type": "string"
              },
              "lagDays": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              }
            },
            "required": [
              "predecessorTaskId",
              "successorTaskId",
              "lagDays"
            ]
          }
        },
        "milestones": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "projectId": {
                "type": "string"
              },
              "name": {
                "type": "string"
              },
              "date": {
                "type": "string",
                "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
              },
              "taskCount": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "openTaskCount": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "overdueTaskCount": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              }
            },
            "required": [
              "id",
              "projectId",
              "name",
              "date",
              "taskCount",
              "openTaskCount",
              "overdueTaskCount"
            ]
          }
        },
        "fields": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "name": {
                "type": "string"
              },
              "type": {
                "type": "string",
                "enum": [
                  "text",
                  "number",
                  "date",
                  "select",
                  "multi_select",
                  "checkbox",
                  "url"
                ]
              },
              "options": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 100
                    },
                    "label": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 60
                    },
                    "color": {
                      "type": "string",
                      "pattern": "^#[0-9a-fA-F]{6}$",
                      "x-nullable": true
                    }
                  },
                  "required": [
                    "id",
                    "label"
                  ]
                }
              },
              "showOnCard": {
                "type": "boolean"
              },
              "sortOrder": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "archived": {
                "type": "boolean"
              }
            },
            "required": [
              "id",
              "name",
              "type",
              "options",
              "showOnCard",
              "sortOrder",
              "archived"
            ]
          }
        },
        "taskTimeTracking": {
          "type": "string",
          "enum": [
            "off",
            "optional",
            "required"
          ]
        },
        "criticalPath": {
          "type": "object",
          "properties": {
            "taskIds": {
              "type": "array",
              "items": {
                "type": "string"
              }
            },
            "totalDays": {
              "type": "integer",
              "minimum": -9007199254740991,
              "maximum": 9007199254740991
            }
          },
          "required": [
            "taskIds",
            "totalDays"
          ]
        }
      },
      "required": [
        "source",
        "statuses",
        "columns",
        "dependencies",
        "milestones",
        "fields",
        "taskTimeTracking",
        "criticalPath"
      ]
    },
    "TaskPageResponseDto": {
      "type": "object",
      "properties": {
        "items": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "projectId": {
                "type": "string"
              },
              "number": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "phaseId": {
                "type": "string",
                "x-nullable": true
              },
              "phaseName": {
                "type": "string",
                "x-nullable": true
              },
              "phaseSortOrder": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991,
                "x-nullable": true
              },
              "dimensionValueId": {
                "type": "string",
                "x-nullable": true
              },
              "title": {
                "type": "string"
              },
              "description": {
                "type": "string",
                "x-nullable": true
              },
              "statusId": {
                "type": "string"
              },
              "statusCategory": {
                "type": "string",
                "enum": [
                  "todo",
                  "in_progress",
                  "done",
                  "cancelled"
                ]
              },
              "assigneeMembershipId": {
                "type": "string",
                "x-nullable": true
              },
              "assigneeName": {
                "type": "string",
                "x-nullable": true
              },
              "priority": {
                "type": "string",
                "enum": [
                  "low",
                  "normal",
                  "high",
                  "urgent"
                ]
              },
              "startDate": {
                "type": "string",
                "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
                "x-nullable": true
              },
              "dueDate": {
                "type": "string",
                "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
                "x-nullable": true
              },
              "estimateMinutes": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991,
                "x-nullable": true
              },
              "progressPct": {
                "type": "integer",
                "minimum": 0,
                "maximum": 100,
                "x-nullable": true
              },
              "sortKey": {
                "type": "string"
              },
              "milestoneId": {
                "type": "string",
                "x-nullable": true
              },
              "tags": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "name": {
                      "type": "string"
                    },
                    "color": {
                      "type": "string",
                      "x-nullable": true
                    }
                  },
                  "required": [
                    "id",
                    "name",
                    "color"
                  ]
                }
              },
              "recurrenceId": {
                "type": "string",
                "x-nullable": true
              },
              "fieldValues": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "fieldId": {
                      "type": "string"
                    },
                    "value": {}
                  },
                  "required": [
                    "fieldId",
                    "value"
                  ]
                }
              },
              "archivedAt": {
                "type": "string",
                "x-nullable": true
              },
              "checklistDoneCount": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "checklistTotalCount": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "commentCount": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "actualMinutes": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991,
                "x-nullable": true
              },
              "updatedAt": {
                "type": "string"
              },
              "createdAt": {
                "type": "string"
              }
            },
            "required": [
              "id",
              "projectId",
              "number",
              "phaseId",
              "phaseName",
              "phaseSortOrder",
              "dimensionValueId",
              "title",
              "statusId",
              "statusCategory",
              "assigneeMembershipId",
              "assigneeName",
              "priority",
              "startDate",
              "dueDate",
              "estimateMinutes",
              "progressPct",
              "sortKey",
              "milestoneId",
              "tags",
              "recurrenceId",
              "fieldValues",
              "archivedAt",
              "checklistDoneCount",
              "checklistTotalCount",
              "commentCount",
              "actualMinutes",
              "updatedAt",
              "createdAt"
            ]
          }
        },
        "pageInfo": {
          "type": "object",
          "properties": {
            "nextCursor": {
              "type": "string",
              "x-nullable": true
            },
            "hasMore": {
              "type": "boolean"
            }
          },
          "required": [
            "nextCursor",
            "hasMore"
          ]
        }
      },
      "required": [
        "items",
        "pageInfo"
      ]
    },
    "TaskOkResponseDto": {
      "type": "object",
      "properties": {
        "ok": {
          "type": "boolean"
        }
      },
      "required": [
        "ok"
      ]
    },
    "CreateTaskDto": {
      "type": "object",
      "properties": {
        "title": {
          "type": "string",
          "minLength": 1,
          "maxLength": 200
        },
        "description": {
          "type": "string",
          "maxLength": 8000,
          "x-nullable": true
        },
        "templateId": {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
        },
        "statusId": {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
        },
        "phaseId": {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
          "x-nullable": true
        },
        "assigneeMembershipId": {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
          "x-nullable": true
        },
        "priority": {
          "default": "normal",
          "type": "string",
          "enum": [
            "low",
            "normal",
            "high",
            "urgent"
          ]
        },
        "startDate": {
          "type": "string",
          "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
          "x-nullable": true
        },
        "dueDate": {
          "type": "string",
          "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
          "x-nullable": true
        },
        "estimateMinutes": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991,
          "x-nullable": true
        },
        "milestoneId": {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
          "x-nullable": true
        },
        "tagIds": {
          "maxItems": 20,
          "type": "array",
          "items": {
            "type": "string",
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
          }
        },
        "trackTime": {
          "type": "boolean"
        },
        "fixedPriceCents": {
          "type": "integer",
          "minimum": 0,
          "maximum": 9007199254740991,
          "x-nullable": true
        }
      },
      "required": [
        "title"
      ]
    },
    "TaskViewDto": {
      "type": "object",
      "properties": {
        "id": {
          "type": "string"
        },
        "projectId": {
          "type": "string"
        },
        "number": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991
        },
        "phaseId": {
          "type": "string",
          "x-nullable": true
        },
        "phaseName": {
          "type": "string",
          "x-nullable": true
        },
        "phaseSortOrder": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991,
          "x-nullable": true
        },
        "dimensionValueId": {
          "type": "string",
          "x-nullable": true
        },
        "title": {
          "type": "string"
        },
        "description": {
          "type": "string",
          "x-nullable": true
        },
        "statusId": {
          "type": "string"
        },
        "statusCategory": {
          "type": "string",
          "enum": [
            "todo",
            "in_progress",
            "done",
            "cancelled"
          ]
        },
        "assigneeMembershipId": {
          "type": "string",
          "x-nullable": true
        },
        "assigneeName": {
          "type": "string",
          "x-nullable": true
        },
        "priority": {
          "type": "string",
          "enum": [
            "low",
            "normal",
            "high",
            "urgent"
          ]
        },
        "startDate": {
          "type": "string",
          "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
          "x-nullable": true
        },
        "dueDate": {
          "type": "string",
          "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
          "x-nullable": true
        },
        "estimateMinutes": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991,
          "x-nullable": true
        },
        "progressPct": {
          "type": "integer",
          "minimum": 0,
          "maximum": 100,
          "x-nullable": true
        },
        "sortKey": {
          "type": "string"
        },
        "milestoneId": {
          "type": "string",
          "x-nullable": true
        },
        "tags": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "name": {
                "type": "string"
              },
              "color": {
                "type": "string",
                "x-nullable": true
              }
            },
            "required": [
              "id",
              "name",
              "color"
            ]
          }
        },
        "recurrenceId": {
          "type": "string",
          "x-nullable": true
        },
        "fieldValues": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "fieldId": {
                "type": "string"
              },
              "value": {}
            },
            "required": [
              "fieldId",
              "value"
            ]
          }
        },
        "archivedAt": {
          "type": "string",
          "x-nullable": true
        },
        "checklistDoneCount": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991
        },
        "checklistTotalCount": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991
        },
        "commentCount": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991
        },
        "actualMinutes": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991,
          "x-nullable": true
        },
        "updatedAt": {
          "type": "string"
        },
        "createdAt": {
          "type": "string"
        }
      },
      "required": [
        "id",
        "projectId",
        "number",
        "phaseId",
        "phaseName",
        "phaseSortOrder",
        "dimensionValueId",
        "title",
        "statusId",
        "statusCategory",
        "assigneeMembershipId",
        "assigneeName",
        "priority",
        "startDate",
        "dueDate",
        "estimateMinutes",
        "progressPct",
        "sortKey",
        "milestoneId",
        "tags",
        "recurrenceId",
        "fieldValues",
        "archivedAt",
        "checklistDoneCount",
        "checklistTotalCount",
        "commentCount",
        "actualMinutes",
        "updatedAt",
        "createdAt"
      ]
    },
    "TaskStatusListResponseDto": {
      "type": "object",
      "properties": {
        "source": {
          "type": "string",
          "enum": [
            "project",
            "tenant_default"
          ]
        },
        "statuses": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "projectId": {
                "type": "string",
                "x-nullable": true
              },
              "name": {
                "type": "string"
              },
              "color": {
                "type": "string",
                "x-nullable": true
              },
              "category": {
                "type": "string",
                "enum": [
                  "todo",
                  "in_progress",
                  "done",
                  "cancelled"
                ]
              },
              "sortOrder": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "wipLimit": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991,
                "x-nullable": true
              },
              "taskCount": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              }
            },
            "required": [
              "id",
              "projectId",
              "name",
              "color",
              "category",
              "sortOrder",
              "wipLimit",
              "taskCount"
            ]
          }
        }
      },
      "required": [
        "source",
        "statuses"
      ]
    },
    "TaskDetailResponseDto": {
      "type": "object",
      "properties": {
        "id": {
          "type": "string"
        },
        "projectId": {
          "type": "string"
        },
        "number": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991
        },
        "phaseId": {
          "type": "string",
          "x-nullable": true
        },
        "phaseName": {
          "type": "string",
          "x-nullable": true
        },
        "phaseSortOrder": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991,
          "x-nullable": true
        },
        "dimensionValueId": {
          "type": "string",
          "x-nullable": true
        },
        "title": {
          "type": "string"
        },
        "description": {
          "type": "string",
          "x-nullable": true
        },
        "statusId": {
          "type": "string"
        },
        "statusCategory": {
          "type": "string",
          "enum": [
            "todo",
            "in_progress",
            "done",
            "cancelled"
          ]
        },
        "assigneeMembershipId": {
          "type": "string",
          "x-nullable": true
        },
        "assigneeName": {
          "type": "string",
          "x-nullable": true
        },
        "priority": {
          "type": "string",
          "enum": [
            "low",
            "normal",
            "high",
            "urgent"
          ]
        },
        "startDate": {
          "type": "string",
          "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
          "x-nullable": true
        },
        "dueDate": {
          "type": "string",
          "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
          "x-nullable": true
        },
        "estimateMinutes": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991,
          "x-nullable": true
        },
        "progressPct": {
          "type": "integer",
          "minimum": 0,
          "maximum": 100,
          "x-nullable": true
        },
        "sortKey": {
          "type": "string"
        },
        "milestoneId": {
          "type": "string",
          "x-nullable": true
        },
        "tags": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "name": {
                "type": "string"
              },
              "color": {
                "type": "string",
                "x-nullable": true
              }
            },
            "required": [
              "id",
              "name",
              "color"
            ]
          }
        },
        "recurrenceId": {
          "type": "string",
          "x-nullable": true
        },
        "fieldValues": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "fieldId": {
                "type": "string"
              },
              "value": {}
            },
            "required": [
              "fieldId",
              "value"
            ]
          }
        },
        "archivedAt": {
          "type": "string",
          "x-nullable": true
        },
        "checklistDoneCount": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991
        },
        "checklistTotalCount": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991
        },
        "commentCount": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991
        },
        "actualMinutes": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991,
          "x-nullable": true
        },
        "updatedAt": {
          "type": "string"
        },
        "createdAt": {
          "type": "string"
        },
        "projectName": {
          "type": "string"
        },
        "projectCode": {
          "type": "string"
        },
        "checklist": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "title": {
                "type": "string"
              },
              "done": {
                "type": "boolean"
              },
              "sortOrder": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "assigneeMembershipId": {
                "type": "string",
                "x-nullable": true
              },
              "assigneeName": {
                "type": "string",
                "x-nullable": true
              },
              "dueDate": {
                "type": "string",
                "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
                "x-nullable": true
              }
            },
            "required": [
              "id",
              "title",
              "done",
              "sortOrder",
              "assigneeMembershipId",
              "assigneeName",
              "dueDate"
            ]
          }
        },
        "predecessors": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "title": {
                "type": "string"
              },
              "statusCategory": {
                "type": "string",
                "enum": [
                  "todo",
                  "in_progress",
                  "done",
                  "cancelled"
                ]
              },
              "dueDate": {
                "type": "string",
                "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
                "x-nullable": true
              },
              "taskKey": {
                "type": "string"
              },
              "projectId": {
                "type": "string"
              },
              "external": {
                "type": "boolean"
              },
              "lagDays": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              }
            },
            "required": [
              "id",
              "title",
              "statusCategory",
              "dueDate",
              "taskKey",
              "projectId",
              "external",
              "lagDays"
            ]
          }
        },
        "successors": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "title": {
                "type": "string"
              },
              "statusCategory": {
                "type": "string",
                "enum": [
                  "todo",
                  "in_progress",
                  "done",
                  "cancelled"
                ]
              },
              "dueDate": {
                "type": "string",
                "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
                "x-nullable": true
              },
              "taskKey": {
                "type": "string"
              },
              "projectId": {
                "type": "string"
              },
              "external": {
                "type": "boolean"
              },
              "lagDays": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              }
            },
            "required": [
              "id",
              "title",
              "statusCategory",
              "dueDate",
              "taskKey",
              "projectId",
              "external",
              "lagDays"
            ]
          }
        },
        "recurrence": {
          "type": "object",
          "properties": {
            "id": {
              "type": "string"
            },
            "freq": {
              "type": "string",
              "enum": [
                "daily",
                "weekly",
                "monthly"
              ]
            },
            "interval": {
              "type": "integer",
              "minimum": -9007199254740991,
              "maximum": 9007199254740991
            },
            "byWeekday": {
              "type": "integer",
              "minimum": -9007199254740991,
              "maximum": 9007199254740991,
              "x-nullable": true
            },
            "byMonthDay": {
              "type": "integer",
              "minimum": -9007199254740991,
              "maximum": 9007199254740991,
              "x-nullable": true
            },
            "mode": {
              "type": "string",
              "enum": [
                "schedule",
                "on_complete"
              ]
            },
            "active": {
              "type": "boolean"
            }
          },
          "required": [
            "id",
            "freq",
            "interval",
            "byWeekday",
            "byMonthDay",
            "mode",
            "active"
          ],
          "x-nullable": true
        },
        "fields": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "name": {
                "type": "string"
              },
              "type": {
                "type": "string",
                "enum": [
                  "text",
                  "number",
                  "date",
                  "select",
                  "multi_select",
                  "checkbox",
                  "url"
                ]
              },
              "options": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 100
                    },
                    "label": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 60
                    },
                    "color": {
                      "type": "string",
                      "pattern": "^#[0-9a-fA-F]{6}$",
                      "x-nullable": true
                    }
                  },
                  "required": [
                    "id",
                    "label"
                  ]
                }
              },
              "showOnCard": {
                "type": "boolean"
              },
              "sortOrder": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "archived": {
                "type": "boolean"
              }
            },
            "required": [
              "id",
              "name",
              "type",
              "options",
              "showOnCard",
              "sortOrder",
              "archived"
            ]
          }
        },
        "watching": {
          "type": "boolean"
        },
        "watchers": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "membershipId": {
                "type": "string"
              },
              "name": {
                "type": "string",
                "x-nullable": true
              }
            },
            "required": [
              "membershipId",
              "name"
            ]
          }
        },
        "taskTimeTracking": {
          "type": "string",
          "enum": [
            "off",
            "optional",
            "required"
          ]
        },
        "permissions": {
          "type": "object",
          "properties": {
            "canEditPlan": {
              "type": "boolean"
            },
            "canMove": {
              "type": "boolean"
            },
            "canComment": {
              "type": "boolean"
            },
            "canEditChecklist": {
              "type": "boolean"
            },
            "canDelete": {
              "type": "boolean"
            }
          },
          "required": [
            "canEditPlan",
            "canMove",
            "canComment",
            "canEditChecklist",
            "canDelete"
          ]
        }
      },
      "required": [
        "id",
        "projectId",
        "number",
        "phaseId",
        "phaseName",
        "phaseSortOrder",
        "dimensionValueId",
        "title",
        "description",
        "statusId",
        "statusCategory",
        "assigneeMembershipId",
        "assigneeName",
        "priority",
        "startDate",
        "dueDate",
        "estimateMinutes",
        "progressPct",
        "sortKey",
        "milestoneId",
        "tags",
        "recurrenceId",
        "fieldValues",
        "archivedAt",
        "checklistDoneCount",
        "checklistTotalCount",
        "commentCount",
        "actualMinutes",
        "updatedAt",
        "createdAt",
        "projectName",
        "projectCode",
        "checklist",
        "predecessors",
        "successors",
        "recurrence",
        "fields",
        "watching",
        "watchers",
        "taskTimeTracking",
        "permissions"
      ]
    },
    "MeTasksResponseDto": {
      "type": "object",
      "properties": {
        "tasks": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "projectId": {
                "type": "string"
              },
              "projectName": {
                "type": "string"
              },
              "projectCode": {
                "type": "string"
              },
              "number": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "phaseName": {
                "type": "string",
                "x-nullable": true
              },
              "title": {
                "type": "string"
              },
              "tags": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "name": {
                      "type": "string"
                    },
                    "color": {
                      "type": "string",
                      "x-nullable": true
                    }
                  },
                  "required": [
                    "id",
                    "name",
                    "color"
                  ]
                }
              },
              "description": {
                "type": "string",
                "x-nullable": true
              },
              "statusId": {
                "type": "string"
              },
              "statusName": {
                "type": "string"
              },
              "statusCategory": {
                "type": "string",
                "enum": [
                  "todo",
                  "in_progress",
                  "done",
                  "cancelled"
                ]
              },
              "priority": {
                "type": "string",
                "enum": [
                  "low",
                  "normal",
                  "high",
                  "urgent"
                ]
              },
              "startDate": {
                "type": "string",
                "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
                "x-nullable": true
              },
              "dueDate": {
                "type": "string",
                "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
                "x-nullable": true
              },
              "checklistDoneCount": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "checklistTotalCount": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "commentCount": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "relation": {
                "type": "string",
                "enum": [
                  "assignee",
                  "commenter",
                  "watcher",
                  "project_member"
                ]
              },
              "estimateMinutes": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991,
                "x-nullable": true
              },
              "myMinutes": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "blockedBy": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "taskId": {
                      "type": "string"
                    },
                    "taskKey": {
                      "type": "string"
                    },
                    "title": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "taskId",
                    "taskKey",
                    "title"
                  ]
                }
              },
              "blocksCount": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "dimensionValueId": {
                "type": "string",
                "x-nullable": true
              },
              "taskTimeTracking": {
                "type": "string",
                "enum": [
                  "off",
                  "optional",
                  "required"
                ]
              },
              "updatedAt": {
                "type": "string"
              }
            },
            "required": [
              "id",
              "projectId",
              "projectName",
              "projectCode",
              "number",
              "phaseName",
              "title",
              "tags",
              "description",
              "statusId",
              "statusName",
              "statusCategory",
              "priority",
              "startDate",
              "dueDate",
              "checklistDoneCount",
              "checklistTotalCount",
              "commentCount",
              "relation",
              "estimateMinutes",
              "myMinutes",
              "blockedBy",
              "blocksCount",
              "dimensionValueId",
              "taskTimeTracking",
              "updatedAt"
            ]
          }
        },
        "boards": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "projectId": {
                "type": "string"
              },
              "statuses": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "name": {
                      "type": "string"
                    },
                    "category": {
                      "type": "string",
                      "enum": [
                        "todo",
                        "in_progress",
                        "done",
                        "cancelled"
                      ]
                    },
                    "sortOrder": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991
                    }
                  },
                  "required": [
                    "id",
                    "name",
                    "category",
                    "sortOrder"
                  ]
                }
              }
            },
            "required": [
              "projectId",
              "statuses"
            ]
          }
        },
        "checklistItems": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "taskId": {
                "type": "string"
              },
              "title": {
                "type": "string"
              },
              "done": {
                "type": "boolean"
              },
              "dueDate": {
                "type": "string",
                "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
                "x-nullable": true
              },
              "taskTitle": {
                "type": "string"
              },
              "taskNumber": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "projectId": {
                "type": "string"
              },
              "projectCode": {
                "type": "string"
              },
              "projectName": {
                "type": "string"
              }
            },
            "required": [
              "id",
              "taskId",
              "title",
              "done",
              "dueDate",
              "taskTitle",
              "taskNumber",
              "projectId",
              "projectCode",
              "projectName"
            ]
          }
        },
        "waiting": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "notificationId": {
                "type": "string"
              },
              "type": {
                "type": "string",
                "enum": [
                  "task_mentioned",
                  "task_commented"
                ]
              },
              "taskId": {
                "type": "string"
              },
              "taskKey": {
                "type": "string",
                "x-nullable": true
              },
              "taskTitle": {
                "type": "string",
                "x-nullable": true
              },
              "actorName": {
                "type": "string",
                "x-nullable": true
              },
              "preview": {
                "type": "string",
                "x-nullable": true
              },
              "createdAt": {
                "type": "string"
              }
            },
            "required": [
              "notificationId",
              "type",
              "taskId",
              "taskKey",
              "taskTitle",
              "actorName",
              "preview",
              "createdAt"
            ]
          }
        },
        "myWeekMinutes": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991
        }
      },
      "required": [
        "tasks",
        "boards",
        "checklistItems",
        "waiting",
        "myWeekMinutes"
      ]
    },
    "MeTaskStatusChangeDto": {
      "type": "object",
      "properties": {
        "statusId": {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
        },
        "expectedUpdatedAt": {
          "type": "string"
        }
      },
      "required": [
        "statusId"
      ]
    },
    "BillingIdResponseDto": {
      "type": "object",
      "properties": {
        "id": {
          "type": "string"
        }
      },
      "required": [
        "id"
      ]
    },
    "BillingCandidatesResponseDto": {
      "type": "object",
      "properties": {
        "periodStart": {
          "type": "string",
          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
        },
        "periodEnd": {
          "type": "string",
          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
        },
        "granularity": {
          "type": "string",
          "enum": [
            "project",
            "phase",
            "task",
            "person",
            "day"
          ]
        },
        "invoiceCount": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991
        },
        "netCents": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991
        },
        "vatCents": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991
        },
        "grossCents": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991
        },
        "unpricedMinutes": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991
        },
        "invoices": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "customerId": {
                "type": "string"
              },
              "customerCode": {
                "type": "string"
              },
              "customerName": {
                "type": "string"
              },
              "reference": {
                "type": "string"
              },
              "netCents": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "vatCents": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "grossCents": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "lines": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "lineKey": {
                      "type": "string"
                    },
                    "source": {
                      "type": "string",
                      "enum": [
                        "work",
                        "expense",
                        "trip",
                        "purchase",
                        "manual",
                        "contract",
                        "change_order"
                      ]
                    },
                    "bucketKey": {
                      "type": "string"
                    },
                    "productCode": {
                      "type": "string",
                      "x-nullable": true
                    },
                    "description": {
                      "type": "string"
                    },
                    "quantity": {
                      "type": "number"
                    },
                    "unit": {
                      "type": "string",
                      "enum": [
                        "hour",
                        "piece",
                        "day",
                        "km",
                        "fixed"
                      ]
                    },
                    "unitPriceCents": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991
                    },
                    "amountCents": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991
                    },
                    "vatRate": {
                      "type": "number"
                    },
                    "vatCode": {
                      "type": "string",
                      "x-nullable": true
                    },
                    "vatCents": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991
                    },
                    "costCenter": {
                      "type": "string"
                    },
                    "project": {
                      "type": "string"
                    },
                    "projectId": {
                      "type": "string",
                      "x-nullable": true
                    },
                    "projectPhase": {
                      "type": "string"
                    },
                    "unpriced": {
                      "type": "boolean"
                    },
                    "workedMinutes": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991,
                      "default": null,
                      "x-nullable": true
                    },
                    "billingBaseMinutes": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991,
                      "default": null,
                      "x-nullable": true
                    },
                    "roundedMinutes": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991,
                      "default": null,
                      "x-nullable": true
                    }
                  },
                  "required": [
                    "lineKey",
                    "source",
                    "bucketKey",
                    "productCode",
                    "description",
                    "quantity",
                    "unit",
                    "unitPriceCents",
                    "amountCents",
                    "vatRate",
                    "vatCode",
                    "vatCents",
                    "costCenter",
                    "project",
                    "projectId",
                    "projectPhase",
                    "unpriced"
                  ]
                }
              }
            },
            "required": [
              "customerId",
              "customerCode",
              "customerName",
              "reference",
              "netCents",
              "vatCents",
              "grossCents",
              "lines"
            ]
          }
        },
        "warnings": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "code": {
                "type": "string"
              },
              "detail": {
                "type": "string",
                "x-nullable": true
              }
            },
            "required": [
              "code",
              "detail"
            ]
          }
        },
        "candidateHash": {
          "type": "string"
        }
      },
      "required": [
        "periodStart",
        "periodEnd",
        "granularity",
        "invoiceCount",
        "netCents",
        "vatCents",
        "grossCents",
        "unpricedMinutes",
        "invoices",
        "warnings",
        "candidateHash"
      ]
    },
    "BillingBatchListResponseDto": {
      "type": "object",
      "properties": {
        "items": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "kind": {
                "type": "string",
                "enum": [
                  "invoice",
                  "write_off",
                  "invoice_document"
                ]
              },
              "writeOffReason": {
                "type": "string",
                "x-nullable": true
              },
              "periodFrom": {
                "type": "string",
                "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
              },
              "periodTo": {
                "type": "string",
                "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
              },
              "targetId": {
                "type": "string",
                "x-nullable": true
              },
              "adapterKey": {
                "type": "string"
              },
              "status": {
                "type": "string",
                "enum": [
                  "draft",
                  "exported",
                  "canceled",
                  "document"
                ]
              },
              "customerCount": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "lineCount": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "netCents": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "vatCents": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "grossCents": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "createdAt": {
                "type": "string"
              },
              "canceledAt": {
                "type": "string",
                "x-nullable": true
              },
              "cancelReason": {
                "type": "string",
                "x-nullable": true
              }
            },
            "required": [
              "id",
              "kind",
              "writeOffReason",
              "periodFrom",
              "periodTo",
              "targetId",
              "adapterKey",
              "status",
              "customerCount",
              "lineCount",
              "netCents",
              "vatCents",
              "grossCents",
              "createdAt",
              "canceledAt",
              "cancelReason"
            ]
          }
        },
        "pageInfo": {
          "type": "object",
          "properties": {
            "nextCursor": {
              "type": "string",
              "x-nullable": true
            },
            "hasMore": {
              "type": "boolean"
            }
          },
          "required": [
            "nextCursor",
            "hasMore"
          ]
        }
      },
      "required": [
        "items",
        "pageInfo"
      ]
    },
    "CreateBillingBatchDto": {
      "type": "object",
      "properties": {
        "from": {
          "type": "string",
          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
        },
        "to": {
          "type": "string",
          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
        },
        "targetId": {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
        },
        "kind": {
          "type": "string",
          "enum": [
            "invoice",
            "write_off",
            "invoice_document"
          ]
        },
        "writeOffReason": {
          "type": "string",
          "minLength": 1,
          "maxLength": 500
        },
        "granularity": {
          "type": "string",
          "enum": [
            "project",
            "phase",
            "task",
            "person",
            "day"
          ]
        },
        "exclude": {
          "maxItems": 2000,
          "type": "array",
          "items": {
            "type": "string",
            "minLength": 1,
            "maxLength": 500
          }
        },
        "adjustments": {
          "maxItems": 500,
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "lineKey": {
                "type": "string",
                "minLength": 1,
                "maxLength": 500
              },
              "billedMinutes": {
                "type": "integer",
                "minimum": 0,
                "maximum": 600000
              },
              "reason": {
                "type": "string",
                "minLength": 1,
                "maxLength": 500
              }
            },
            "required": [
              "lineKey",
              "billedMinutes",
              "reason"
            ]
          }
        },
        "candidateHash": {
          "type": "string",
          "maxLength": 128
        },
        "manualLines": {
          "maxItems": 500,
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "customerId": {
                "type": "string",
                "format": "uuid",
                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
              },
              "productCode": {
                "type": "string",
                "maxLength": 64,
                "default": null,
                "x-nullable": true
              },
              "description": {
                "type": "string",
                "minLength": 1,
                "maxLength": 200
              },
              "quantity": {
                "default": 1,
                "type": "number",
                "exclusiveMinimum": true,
                "minimum": 0
              },
              "unit": {
                "default": "fixed",
                "type": "string",
                "enum": [
                  "hour",
                  "piece",
                  "day",
                  "km",
                  "fixed"
                ]
              },
              "unitPriceCents": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "vatRate": {
                "default": 0,
                "type": "number",
                "minimum": 0,
                "maximum": 100
              },
              "vatCode": {
                "type": "string",
                "maxLength": 32,
                "default": null,
                "x-nullable": true
              },
              "costCenter": {
                "default": "",
                "type": "string",
                "maxLength": 64
              },
              "project": {
                "default": "",
                "type": "string",
                "maxLength": 120
              }
            },
            "required": [
              "customerId",
              "description",
              "unitPriceCents"
            ]
          }
        }
      },
      "required": [
        "from",
        "to",
        "targetId"
      ]
    },
    "BillingDeliveryListResponseDto": {
      "type": "object",
      "properties": {
        "deliveries": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "batchId": {
                "type": "string"
              },
              "status": {
                "type": "string",
                "enum": [
                  "pending",
                  "delivering",
                  "delivered",
                  "failed"
                ]
              },
              "attempts": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "errorCode": {
                "type": "string",
                "x-nullable": true
              },
              "createdAt": {
                "type": "string"
              },
              "updatedAt": {
                "type": "string"
              }
            },
            "required": [
              "id",
              "batchId",
              "status",
              "attempts",
              "errorCode",
              "createdAt",
              "updatedAt"
            ]
          }
        }
      },
      "required": [
        "deliveries"
      ]
    },
    "InvoicePageResponseDto": {
      "type": "object",
      "properties": {
        "items": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "documentType": {
                "type": "string",
                "enum": [
                  "invoice",
                  "credit_note",
                  "reminder",
                  "advance"
                ]
              },
              "status": {
                "type": "string",
                "enum": [
                  "draft",
                  "issued"
                ]
              },
              "lane": {
                "type": "string",
                "enum": [
                  "draft",
                  "approved",
                  "issued",
                  "sent",
                  "overdue",
                  "paid",
                  "credited"
                ]
              },
              "reviewStatus": {
                "type": "string",
                "enum": [
                  "none",
                  "requested",
                  "approved"
                ]
              },
              "invoiceNumber": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991,
                "x-nullable": true
              },
              "invoiceNumberText": {
                "type": "string",
                "x-nullable": true
              },
              "customerId": {
                "type": "string"
              },
              "customerName": {
                "type": "string"
              },
              "invoiceDate": {
                "type": "string",
                "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
                "x-nullable": true
              },
              "dueDate": {
                "type": "string",
                "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
                "x-nullable": true
              },
              "periodFrom": {
                "type": "string",
                "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
                "x-nullable": true
              },
              "periodTo": {
                "type": "string",
                "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
                "x-nullable": true
              },
              "language": {
                "type": "string",
                "enum": [
                  "fi",
                  "sv",
                  "en"
                ]
              },
              "netTotalCents": {
                "type": "integer",
                "minimum": -2147483647,
                "maximum": 2147483647
              },
              "vatTotalCents": {
                "type": "integer",
                "minimum": -2147483647,
                "maximum": 2147483647
              },
              "grossTotalCents": {
                "type": "integer",
                "minimum": -2147483647,
                "maximum": 2147483647
              },
              "openCents": {
                "type": "integer",
                "minimum": -2147483647,
                "maximum": 2147483647
              },
              "overdueDays": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991,
                "x-nullable": true
              },
              "dispatchStatus": {
                "type": "string",
                "enum": [
                  "queued",
                  "sending",
                  "sent",
                  "delivered",
                  "failed",
                  null
                ],
                "x-nullable": true
              },
              "dispatchChannel": {
                "type": "string",
                "enum": [
                  "einvoice",
                  "email",
                  "manual",
                  "print",
                  null
                ],
                "x-nullable": true
              },
              "sentAt": {
                "type": "string",
                "x-nullable": true
              },
              "creditedByInvoiceId": {
                "type": "string",
                "x-nullable": true
              },
              "lineCount": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "createdAt": {
                "type": "string"
              },
              "updatedAt": {
                "type": "string"
              }
            },
            "required": [
              "id",
              "documentType",
              "status",
              "lane",
              "reviewStatus",
              "invoiceNumber",
              "invoiceNumberText",
              "customerId",
              "customerName",
              "invoiceDate",
              "dueDate",
              "periodFrom",
              "periodTo",
              "language",
              "netTotalCents",
              "vatTotalCents",
              "grossTotalCents",
              "openCents",
              "overdueDays",
              "dispatchStatus",
              "dispatchChannel",
              "sentAt",
              "creditedByInvoiceId",
              "lineCount",
              "createdAt",
              "updatedAt"
            ]
          }
        },
        "pageInfo": {
          "type": "object",
          "properties": {
            "nextCursor": {
              "type": "string",
              "x-nullable": true
            },
            "hasMore": {
              "type": "boolean"
            }
          },
          "required": [
            "nextCursor",
            "hasMore"
          ]
        }
      },
      "required": [
        "items",
        "pageInfo"
      ]
    },
    "InvoicingSummaryResponseDto": {
      "type": "object",
      "properties": {
        "asOf": {
          "type": "string",
          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
        },
        "invoicedThisMonthCents": {
          "type": "integer",
          "minimum": -2147483647,
          "maximum": 2147483647
        },
        "openArCents": {
          "type": "integer",
          "minimum": -2147483647,
          "maximum": 2147483647
        },
        "overdueCents": {
          "type": "integer",
          "minimum": -2147483647,
          "maximum": 2147483647
        },
        "overdueInvoiceCount": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991
        },
        "billableNowCents": {
          "type": "integer",
          "minimum": -2147483647,
          "maximum": 2147483647
        },
        "wipCents": {
          "type": "integer",
          "minimum": -2147483647,
          "maximum": 2147483647
        },
        "draftCount": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991
        },
        "draftValueCents": {
          "type": "integer",
          "minimum": -2147483647,
          "maximum": 2147483647
        }
      },
      "required": [
        "asOf",
        "invoicedThisMonthCents",
        "openArCents",
        "overdueCents",
        "overdueInvoiceCount",
        "billableNowCents",
        "wipCents",
        "draftCount",
        "draftValueCents"
      ]
    },
    "CreateInvoiceDraftsDto": {
      "type": "object",
      "properties": {
        "periodFrom": {
          "type": "string",
          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
        },
        "periodTo": {
          "type": "string",
          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
        },
        "customerIds": {
          "maxItems": 200,
          "type": "array",
          "items": {
            "type": "string",
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
          }
        },
        "projectIds": {
          "maxItems": 200,
          "type": "array",
          "items": {
            "type": "string",
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
          }
        },
        "grouping": {
          "type": "string",
          "enum": [
            "combine",
            "separate"
          ]
        },
        "granularity": {
          "type": "string",
          "enum": [
            "project",
            "phase",
            "task",
            "person",
            "day"
          ]
        },
        "profileId": {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
        },
        "invoiceDate": {
          "type": "string",
          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
        }
      },
      "required": [
        "periodFrom",
        "periodTo"
      ],
      "additionalProperties": false
    },
    "CreateInvoiceDraftsResponseDto": {
      "type": "object",
      "properties": {
        "drafts": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "invoiceId": {
                "type": "string"
              },
              "customerId": {
                "type": "string"
              },
              "customerName": {
                "type": "string"
              },
              "projectId": {
                "type": "string",
                "x-nullable": true
              },
              "lineCount": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "netTotalCents": {
                "type": "integer",
                "minimum": -2147483647,
                "maximum": 2147483647
              },
              "vatTotalCents": {
                "type": "integer",
                "minimum": -2147483647,
                "maximum": 2147483647
              },
              "grossTotalCents": {
                "type": "integer",
                "minimum": -2147483647,
                "maximum": 2147483647
              }
            },
            "required": [
              "invoiceId",
              "customerId",
              "customerName",
              "projectId",
              "lineCount",
              "netTotalCents",
              "vatTotalCents",
              "grossTotalCents"
            ]
          }
        },
        "skipped": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "customerId": {
                "type": "string"
              },
              "code": {
                "type": "string"
              }
            },
            "required": [
              "customerId",
              "code"
            ]
          }
        }
      },
      "required": [
        "drafts",
        "skipped"
      ]
    },
    "InvoiceViewDto": {
      "type": "object",
      "properties": {
        "id": {
          "type": "string"
        },
        "batchId": {
          "type": "string"
        },
        "documentType": {
          "type": "string",
          "enum": [
            "invoice",
            "credit_note",
            "reminder",
            "advance"
          ]
        },
        "status": {
          "type": "string",
          "enum": [
            "draft",
            "issued"
          ]
        },
        "lane": {
          "type": "string",
          "enum": [
            "draft",
            "approved",
            "issued",
            "sent",
            "overdue",
            "paid",
            "credited"
          ]
        },
        "reviewStatus": {
          "type": "string",
          "enum": [
            "none",
            "requested",
            "approved"
          ]
        },
        "customerId": {
          "type": "string"
        },
        "customerName": {
          "type": "string"
        },
        "customerCode": {
          "type": "string"
        },
        "contactId": {
          "type": "string",
          "x-nullable": true
        },
        "contactName": {
          "type": "string",
          "x-nullable": true
        },
        "contactEmail": {
          "type": "string",
          "x-nullable": true
        },
        "profileId": {
          "type": "string"
        },
        "originalInvoiceId": {
          "type": "string",
          "x-nullable": true
        },
        "originalInvoiceNumberText": {
          "type": "string",
          "x-nullable": true
        },
        "invoiceNumber": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991,
          "x-nullable": true
        },
        "invoiceNumberText": {
          "type": "string",
          "x-nullable": true
        },
        "invoiceDate": {
          "type": "string",
          "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
          "x-nullable": true
        },
        "dueDate": {
          "type": "string",
          "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
          "x-nullable": true
        },
        "periodFrom": {
          "type": "string",
          "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
          "x-nullable": true
        },
        "periodTo": {
          "type": "string",
          "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
          "x-nullable": true
        },
        "language": {
          "type": "string",
          "enum": [
            "fi",
            "sv",
            "en"
          ]
        },
        "currency": {
          "type": "string",
          "enum": [
            "EUR"
          ]
        },
        "vatTreatment": {
          "type": "string",
          "enum": [
            "standard",
            "reverse_charge_construction",
            "tax_exempt"
          ]
        },
        "paymentTermDays": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991
        },
        "penaltyInterestPercent": {
          "type": "number"
        },
        "referenceNumber": {
          "type": "string",
          "x-nullable": true
        },
        "referenceType": {
          "type": "string",
          "enum": [
            "domestic",
            "rf"
          ]
        },
        "virtualBarcode": {
          "type": "string",
          "x-nullable": true
        },
        "buyerReference": {
          "type": "string",
          "x-nullable": true
        },
        "orderNumber": {
          "type": "string",
          "x-nullable": true
        },
        "contractNumber": {
          "type": "string",
          "x-nullable": true
        },
        "ourReference": {
          "type": "string",
          "x-nullable": true
        },
        "noteBeforeLines": {
          "type": "string",
          "x-nullable": true
        },
        "noteAfterLines": {
          "type": "string",
          "x-nullable": true
        },
        "sellerSnapshot": {
          "type": "object",
          "properties": {
            "legalName": {
              "type": "string"
            },
            "businessId": {
              "type": "string"
            },
            "vatId": {
              "type": "string",
              "x-nullable": true
            },
            "streetAddress": {
              "type": "string"
            },
            "postalCode": {
              "type": "string"
            },
            "city": {
              "type": "string"
            },
            "country": {
              "type": "string"
            },
            "email": {
              "type": "string",
              "x-nullable": true
            },
            "phone": {
              "type": "string",
              "x-nullable": true
            },
            "iban": {
              "type": "string"
            },
            "bic": {
              "type": "string",
              "x-nullable": true
            }
          },
          "required": [
            "legalName",
            "businessId",
            "vatId",
            "streetAddress",
            "postalCode",
            "city",
            "country",
            "email",
            "phone",
            "iban",
            "bic"
          ],
          "x-nullable": true
        },
        "customerSnapshot": {
          "type": "object",
          "properties": {
            "name": {
              "type": "string"
            },
            "businessId": {
              "type": "string",
              "x-nullable": true
            },
            "vatId": {
              "type": "string",
              "x-nullable": true
            },
            "streetAddress": {
              "type": "string",
              "x-nullable": true
            },
            "postalCode": {
              "type": "string",
              "x-nullable": true
            },
            "city": {
              "type": "string",
              "x-nullable": true
            },
            "country": {
              "type": "string",
              "x-nullable": true
            },
            "invoiceEmail": {
              "type": "string",
              "x-nullable": true
            },
            "einvoiceAddress": {
              "type": "string",
              "x-nullable": true
            },
            "einvoiceOperator": {
              "type": "string",
              "x-nullable": true
            }
          },
          "required": [
            "name",
            "businessId",
            "vatId",
            "streetAddress",
            "postalCode",
            "city",
            "country",
            "invoiceEmail",
            "einvoiceAddress",
            "einvoiceOperator"
          ],
          "x-nullable": true
        },
        "netTotalCents": {
          "type": "integer",
          "minimum": -2147483647,
          "maximum": 2147483647
        },
        "vatTotalCents": {
          "type": "integer",
          "minimum": -2147483647,
          "maximum": 2147483647
        },
        "grossTotalCents": {
          "type": "integer",
          "minimum": -2147483647,
          "maximum": 2147483647
        },
        "vatGroups": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "vatRate": {
                "type": "number"
              },
              "netCents": {
                "type": "integer",
                "minimum": -2147483647,
                "maximum": 2147483647
              },
              "vatCents": {
                "type": "integer",
                "minimum": -2147483647,
                "maximum": 2147483647
              }
            },
            "required": [
              "vatRate",
              "netCents",
              "vatCents"
            ]
          }
        },
        "openCents": {
          "type": "integer",
          "minimum": -2147483647,
          "maximum": 2147483647
        },
        "paidCents": {
          "type": "integer",
          "minimum": -2147483647,
          "maximum": 2147483647
        },
        "creditAppliedCents": {
          "type": "integer",
          "minimum": -2147483647,
          "maximum": 2147483647
        },
        "overdueDays": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991,
          "x-nullable": true
        },
        "issuedAt": {
          "type": "string",
          "x-nullable": true
        },
        "issuedByName": {
          "type": "string",
          "x-nullable": true
        },
        "sentAt": {
          "type": "string",
          "x-nullable": true
        },
        "creditedByInvoiceId": {
          "type": "string",
          "x-nullable": true
        },
        "creditedByInvoiceNumberText": {
          "type": "string",
          "x-nullable": true
        },
        "recurringScheduleId": {
          "type": "string",
          "x-nullable": true
        },
        "paymentTermId": {
          "type": "string",
          "x-nullable": true
        },
        "termNetDays": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991,
          "x-nullable": true
        },
        "termDiscountDays": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991,
          "x-nullable": true
        },
        "termDiscountPercent": {
          "type": "number",
          "x-nullable": true
        },
        "cashDiscountCents": {
          "type": "integer",
          "minimum": -2147483647,
          "maximum": 2147483647
        },
        "advanceAppliedCents": {
          "type": "integer",
          "minimum": -2147483647,
          "maximum": 2147483647
        },
        "customerAdvanceBalanceCents": {
          "type": "integer",
          "minimum": -2147483647,
          "maximum": 2147483647
        },
        "preDueRemindedAt": {
          "type": "string",
          "x-nullable": true
        },
        "shareUrl": {
          "type": "string",
          "x-nullable": true
        },
        "effectiveDispatchRoute": {
          "type": "object",
          "properties": {
            "channel": {
              "type": "string",
              "enum": [
                "einvoice",
                "email",
                "manual",
                "print"
              ]
            },
            "recipient": {
              "type": "string",
              "x-nullable": true
            }
          },
          "required": [
            "channel",
            "recipient"
          ]
        },
        "lines": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "sortOrder": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "groupKey": {
                "type": "string",
                "x-nullable": true
              },
              "groupTitle": {
                "type": "string",
                "x-nullable": true
              },
              "source": {
                "type": "string",
                "enum": [
                  "work",
                  "expense",
                  "trip",
                  "purchase",
                  "contract",
                  "change_order",
                  "manual",
                  "discount",
                  "advance"
                ]
              },
              "bucketKey": {
                "type": "string",
                "x-nullable": true
              },
              "description": {
                "type": "string"
              },
              "quantity": {
                "type": "number"
              },
              "unit": {
                "type": "string",
                "enum": [
                  "hour",
                  "piece",
                  "day",
                  "km",
                  "fixed"
                ]
              },
              "unitPriceCents": {
                "type": "integer",
                "minimum": -2147483647,
                "maximum": 2147483647
              },
              "discountPercent": {
                "type": "number",
                "x-nullable": true
              },
              "vatRate": {
                "type": "number"
              },
              "netAmountCents": {
                "type": "integer",
                "minimum": -2147483647,
                "maximum": 2147483647
              },
              "vatAmountCents": {
                "type": "integer",
                "minimum": -2147483647,
                "maximum": 2147483647
              },
              "disposition": {
                "type": "string",
                "enum": [
                  "bill",
                  "later",
                  "write_off"
                ]
              },
              "writeOffReason": {
                "type": "string",
                "x-nullable": true
              },
              "lineKey": {
                "type": "string",
                "x-nullable": true
              },
              "minutes": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991,
                "x-nullable": true
              },
              "workedMinutes": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991,
                "x-nullable": true
              },
              "billingBaseMinutes": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991,
                "x-nullable": true
              },
              "roundedMinutes": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991,
                "x-nullable": true
              },
              "projectId": {
                "type": "string",
                "x-nullable": true
              },
              "projectName": {
                "type": "string",
                "x-nullable": true
              },
              "taskId": {
                "type": "string",
                "x-nullable": true
              },
              "installmentId": {
                "type": "string",
                "x-nullable": true
              },
              "changeOrderId": {
                "type": "string",
                "x-nullable": true
              },
              "orderReference": {
                "type": "string",
                "x-nullable": true
              },
              "updatedAt": {
                "type": "string"
              }
            },
            "required": [
              "id",
              "sortOrder",
              "groupKey",
              "groupTitle",
              "source",
              "bucketKey",
              "description",
              "quantity",
              "unit",
              "unitPriceCents",
              "discountPercent",
              "vatRate",
              "netAmountCents",
              "vatAmountCents",
              "disposition",
              "writeOffReason",
              "lineKey",
              "minutes",
              "workedMinutes",
              "billingBaseMinutes",
              "roundedMinutes",
              "projectId",
              "projectName",
              "taskId",
              "installmentId",
              "changeOrderId",
              "updatedAt"
            ]
          }
        },
        "preflight": {
          "type": "object",
          "properties": {
            "canIssue": {
              "type": "boolean"
            },
            "blockers": {
              "type": "array",
              "items": {
                "type": "object",
                "properties": {
                  "code": {
                    "type": "string"
                  },
                  "detail": {
                    "type": "string",
                    "x-nullable": true
                  }
                },
                "required": [
                  "code",
                  "detail"
                ]
              }
            },
            "warnings": {
              "type": "array",
              "items": {
                "type": "object",
                "properties": {
                  "code": {
                    "type": "string"
                  },
                  "detail": {
                    "type": "string",
                    "x-nullable": true
                  }
                },
                "required": [
                  "code",
                  "detail"
                ]
              }
            }
          },
          "required": [
            "canIssue",
            "blockers",
            "warnings"
          ]
        },
        "dispatches": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "invoiceId": {
                "type": "string"
              },
              "channel": {
                "type": "string",
                "enum": [
                  "einvoice",
                  "email",
                  "manual",
                  "print"
                ]
              },
              "status": {
                "type": "string",
                "enum": [
                  "queued",
                  "sending",
                  "sent",
                  "delivered",
                  "failed"
                ]
              },
              "recipient": {
                "type": "string"
              },
              "operatorMessageId": {
                "type": "string",
                "x-nullable": true
              },
              "errorCode": {
                "type": "string",
                "x-nullable": true
              },
              "testMode": {
                "type": "boolean"
              },
              "attemptNumber": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "artifactAttachmentId": {
                "type": "string",
                "x-nullable": true
              },
              "sentAt": {
                "type": "string",
                "x-nullable": true
              },
              "deliveredAt": {
                "type": "string",
                "x-nullable": true
              },
              "createdAt": {
                "type": "string"
              },
              "updatedAt": {
                "type": "string"
              }
            },
            "required": [
              "id",
              "invoiceId",
              "channel",
              "status",
              "recipient",
              "operatorMessageId",
              "errorCode",
              "testMode",
              "attemptNumber",
              "artifactAttachmentId",
              "sentAt",
              "deliveredAt",
              "createdAt",
              "updatedAt"
            ]
          }
        },
        "settlements": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "kind": {
                "type": "string",
                "enum": [
                  "payment",
                  "credit",
                  "cash_discount"
                ]
              },
              "sourceId": {
                "type": "string"
              },
              "date": {
                "type": "string",
                "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
              },
              "amountCents": {
                "type": "integer",
                "minimum": -2147483647,
                "maximum": 2147483647
              },
              "reference": {
                "type": "string",
                "x-nullable": true
              },
              "payerName": {
                "type": "string",
                "x-nullable": true
              },
              "source": {
                "type": "string",
                "enum": [
                  "manual",
                  "netvisor",
                  "camt054",
                  null
                ],
                "x-nullable": true
              },
              "createdAt": {
                "type": "string"
              }
            },
            "required": [
              "id",
              "kind",
              "sourceId",
              "date",
              "amountCents",
              "reference",
              "payerName",
              "source",
              "createdAt"
            ]
          }
        },
        "events": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "type": {
                "type": "string"
              },
              "actorName": {
                "type": "string",
                "x-nullable": true
              },
              "detail": {
                "type": "string",
                "x-nullable": true
              },
              "createdAt": {
                "type": "string"
              }
            },
            "required": [
              "id",
              "type",
              "actorName",
              "detail",
              "createdAt"
            ]
          }
        },
        "createdAt": {
          "type": "string"
        },
        "updatedAt": {
          "type": "string"
        }
      },
      "required": [
        "id",
        "batchId",
        "documentType",
        "status",
        "lane",
        "reviewStatus",
        "customerId",
        "customerName",
        "customerCode",
        "contactId",
        "contactName",
        "contactEmail",
        "profileId",
        "originalInvoiceId",
        "originalInvoiceNumberText",
        "invoiceNumber",
        "invoiceNumberText",
        "invoiceDate",
        "dueDate",
        "periodFrom",
        "periodTo",
        "language",
        "currency",
        "vatTreatment",
        "paymentTermDays",
        "penaltyInterestPercent",
        "referenceNumber",
        "referenceType",
        "virtualBarcode",
        "buyerReference",
        "orderNumber",
        "contractNumber",
        "ourReference",
        "noteBeforeLines",
        "noteAfterLines",
        "sellerSnapshot",
        "customerSnapshot",
        "netTotalCents",
        "vatTotalCents",
        "grossTotalCents",
        "vatGroups",
        "openCents",
        "paidCents",
        "creditAppliedCents",
        "overdueDays",
        "issuedAt",
        "issuedByName",
        "sentAt",
        "creditedByInvoiceId",
        "creditedByInvoiceNumberText",
        "recurringScheduleId",
        "lines",
        "preflight",
        "dispatches",
        "settlements",
        "events",
        "createdAt",
        "updatedAt"
      ]
    },
    "UpdateInvoiceDraftDto": {
      "type": "object",
      "properties": {
        "customerId": {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
        },
        "contactId": {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
          "x-nullable": true
        },
        "profileId": {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
        },
        "language": {
          "type": "string",
          "enum": [
            "fi",
            "sv",
            "en"
          ]
        },
        "invoiceDate": {
          "type": "string",
          "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
          "x-nullable": true
        },
        "dueDate": {
          "type": "string",
          "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
          "x-nullable": true
        },
        "periodFrom": {
          "type": "string",
          "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
          "x-nullable": true
        },
        "periodTo": {
          "type": "string",
          "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
          "x-nullable": true
        },
        "paymentTermDays": {
          "type": "integer",
          "minimum": 1,
          "maximum": 90
        },
        "paymentTermId": {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
          "x-nullable": true
        },
        "penaltyInterestPercent": {
          "type": "number",
          "minimum": 0,
          "maximum": 30,
          "multipleOf": 0.1
        },
        "vatTreatment": {
          "type": "string",
          "enum": [
            "standard",
            "reverse_charge_construction",
            "tax_exempt"
          ]
        },
        "referenceType": {
          "type": "string",
          "enum": [
            "domestic",
            "rf"
          ]
        },
        "buyerReference": {
          "type": "string",
          "maxLength": 70,
          "x-nullable": true
        },
        "orderNumber": {
          "type": "string",
          "maxLength": 70,
          "x-nullable": true
        },
        "contractNumber": {
          "type": "string",
          "maxLength": 70,
          "x-nullable": true
        },
        "ourReference": {
          "type": "string",
          "maxLength": 70,
          "x-nullable": true
        },
        "noteBeforeLines": {
          "type": "string",
          "maxLength": 2000,
          "x-nullable": true
        },
        "noteAfterLines": {
          "type": "string",
          "maxLength": 2000,
          "x-nullable": true
        },
        "expectedUpdatedAt": {
          "type": "string"
        }
      },
      "additionalProperties": false
    },
    "DeleteInvoiceDraftDto": {
      "type": "object",
      "properties": {
        "reason": {
          "type": "string",
          "maxLength": 500
        }
      },
      "additionalProperties": false
    },
    "InvoiceOkResponseDto": {
      "type": "object",
      "properties": {
        "ok": {
          "type": "boolean"
        }
      },
      "required": [
        "ok"
      ]
    },
    "AddManualLineDto": {
      "type": "object",
      "properties": {
        "description": {
          "type": "string",
          "minLength": 1,
          "maxLength": 500
        },
        "quantity": {
          "default": 1,
          "type": "number",
          "exclusiveMinimum": true,
          "maximum": 9999999,
          "minimum": 0
        },
        "unit": {
          "default": "fixed",
          "type": "string",
          "enum": [
            "hour",
            "piece",
            "day",
            "km",
            "fixed"
          ]
        },
        "unitPriceCents": {
          "type": "integer",
          "minimum": -2147483647,
          "maximum": 2147483647
        },
        "discountPercent": {
          "type": "number",
          "minimum": 0,
          "maximum": 100,
          "x-nullable": true
        },
        "vatRate": {
          "type": "number",
          "minimum": 0,
          "maximum": 100
        },
        "sortOrder": {
          "type": "integer",
          "minimum": 0,
          "maximum": 100000
        },
        "groupKey": {
          "type": "string",
          "maxLength": 64,
          "x-nullable": true
        },
        "groupTitle": {
          "type": "string",
          "maxLength": 200,
          "x-nullable": true
        },
        "projectId": {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
          "x-nullable": true
        },
        "taskId": {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
          "x-nullable": true
        },
        "orderReference": {
          "type": "string",
          "maxLength": 70,
          "x-nullable": true
        },
        "source": {
          "default": "manual",
          "type": "string",
          "enum": [
            "manual",
            "discount"
          ]
        }
      },
      "required": [
        "description",
        "unitPriceCents"
      ],
      "additionalProperties": false
    },
    "UpdateDraftLineDto": {
      "type": "object",
      "properties": {
        "description": {
          "type": "string",
          "minLength": 1,
          "maxLength": 500
        },
        "quantity": {
          "type": "number",
          "exclusiveMinimum": true,
          "maximum": 9999999,
          "minimum": 0
        },
        "unitPriceCents": {
          "type": "integer",
          "minimum": -2147483647,
          "maximum": 2147483647
        },
        "discountPercent": {
          "type": "number",
          "minimum": 0,
          "maximum": 100,
          "x-nullable": true
        },
        "vatRate": {
          "type": "number",
          "minimum": 0,
          "maximum": 100
        },
        "sortOrder": {
          "type": "integer",
          "minimum": 0,
          "maximum": 100000
        },
        "groupKey": {
          "type": "string",
          "maxLength": 64,
          "x-nullable": true
        },
        "groupTitle": {
          "type": "string",
          "maxLength": 200,
          "x-nullable": true
        },
        "disposition": {
          "type": "string",
          "enum": [
            "bill",
            "later",
            "write_off"
          ]
        },
        "writeOffReason": {
          "type": "string",
          "minLength": 1,
          "maxLength": 500,
          "x-nullable": true
        },
        "orderReference": {
          "type": "string",
          "maxLength": 70,
          "x-nullable": true
        },
        "projectId": {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
          "x-nullable": true
        }
      },
      "additionalProperties": false
    },
    "ReorderDraftLinesDto": {
      "type": "object",
      "properties": {
        "lineIds": {
          "minItems": 1,
          "maxItems": 1000,
          "type": "array",
          "items": {
            "type": "string",
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
          }
        }
      },
      "required": [
        "lineIds"
      ],
      "additionalProperties": false
    },
    "SetInvoiceReviewDto": {
      "type": "object",
      "properties": {
        "reviewStatus": {
          "type": "string",
          "enum": [
            "requested",
            "approved"
          ]
        },
        "comment": {
          "type": "string",
          "maxLength": 1000
        }
      },
      "required": [
        "reviewStatus"
      ],
      "additionalProperties": false
    },
    "IssueInvoiceDto": {
      "type": "object",
      "properties": {
        "expectedTotalGrossCents": {
          "type": "integer",
          "minimum": -2147483647,
          "maximum": 2147483647
        },
        "invoiceDate": {
          "type": "string",
          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
        },
        "expectedUpdatedAt": {
          "type": "string"
        }
      },
      "additionalProperties": false
    },
    "IssueResultDto": {
      "type": "object",
      "properties": {
        "invoiceId": {
          "type": "string"
        },
        "invoiceNumber": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991
        },
        "invoiceNumberText": {
          "type": "string"
        },
        "invoiceDate": {
          "type": "string",
          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
        },
        "dueDate": {
          "type": "string",
          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
        },
        "referenceNumber": {
          "type": "string"
        },
        "netTotalCents": {
          "type": "integer",
          "minimum": -2147483647,
          "maximum": 2147483647
        },
        "vatTotalCents": {
          "type": "integer",
          "minimum": -2147483647,
          "maximum": 2147483647
        },
        "grossTotalCents": {
          "type": "integer",
          "minimum": -2147483647,
          "maximum": 2147483647
        },
        "releasedSourceCount": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991
        },
        "writeOffLineCount": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991
        }
      },
      "required": [
        "invoiceId",
        "invoiceNumber",
        "invoiceNumberText",
        "invoiceDate",
        "dueDate",
        "referenceNumber",
        "netTotalCents",
        "vatTotalCents",
        "grossTotalCents",
        "releasedSourceCount",
        "writeOffLineCount"
      ]
    },
    "CreditNoteDto": {
      "type": "object",
      "properties": {
        "lines": {
          "maxItems": 500,
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "lineId": {
                "type": "string",
                "format": "uuid",
                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
              },
              "quantity": {
                "type": "number",
                "exclusiveMinimum": true,
                "maximum": 9999999,
                "minimum": 0
              },
              "amountCents": {
                "type": "integer",
                "minimum": 0,
                "maximum": 9007199254740991
              },
              "releaseSources": {
                "type": "boolean"
              },
              "writeOffReason": {
                "type": "string",
                "minLength": 1,
                "maxLength": 500
              }
            },
            "required": [
              "lineId"
            ],
            "additionalProperties": false
          }
        },
        "releaseSources": {
          "default": false,
          "type": "boolean"
        },
        "writeOffReason": {
          "type": "string",
          "minLength": 1,
          "maxLength": 500
        },
        "reissue": {
          "default": false,
          "type": "boolean"
        },
        "reason": {
          "type": "string",
          "minLength": 1,
          "maxLength": 500
        }
      },
      "required": [
        "reason"
      ],
      "additionalProperties": false
    },
    "CreditNoteResultDto": {
      "type": "object",
      "properties": {
        "creditNoteId": {
          "type": "string"
        },
        "originalInvoiceId": {
          "type": "string"
        },
        "netTotalCents": {
          "type": "integer",
          "minimum": -2147483647,
          "maximum": 2147483647
        },
        "vatTotalCents": {
          "type": "integer",
          "minimum": -2147483647,
          "maximum": 2147483647
        },
        "grossTotalCents": {
          "type": "integer",
          "minimum": -2147483647,
          "maximum": 2147483647
        },
        "releasedSourceCount": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991
        },
        "reissuedDraftInvoiceId": {
          "type": "string",
          "x-nullable": true
        }
      },
      "required": [
        "creditNoteId",
        "originalInvoiceId",
        "netTotalCents",
        "vatTotalCents",
        "grossTotalCents",
        "releasedSourceCount",
        "reissuedDraftInvoiceId"
      ]
    },
    "InvoiceDispatchListResponseDto": {
      "type": "object",
      "properties": {
        "dispatches": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "invoiceId": {
                "type": "string"
              },
              "channel": {
                "type": "string",
                "enum": [
                  "einvoice",
                  "email",
                  "manual",
                  "print"
                ]
              },
              "status": {
                "type": "string",
                "enum": [
                  "queued",
                  "sending",
                  "sent",
                  "delivered",
                  "failed"
                ]
              },
              "recipient": {
                "type": "string"
              },
              "operatorMessageId": {
                "type": "string",
                "x-nullable": true
              },
              "errorCode": {
                "type": "string",
                "x-nullable": true
              },
              "testMode": {
                "type": "boolean"
              },
              "attemptNumber": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "artifactAttachmentId": {
                "type": "string",
                "x-nullable": true
              },
              "sentAt": {
                "type": "string",
                "x-nullable": true
              },
              "deliveredAt": {
                "type": "string",
                "x-nullable": true
              },
              "createdAt": {
                "type": "string"
              },
              "updatedAt": {
                "type": "string"
              }
            },
            "required": [
              "id",
              "invoiceId",
              "channel",
              "status",
              "recipient",
              "operatorMessageId",
              "errorCode",
              "testMode",
              "attemptNumber",
              "artifactAttachmentId",
              "sentAt",
              "deliveredAt",
              "createdAt",
              "updatedAt"
            ]
          }
        }
      },
      "required": [
        "dispatches"
      ]
    },
    "DispatchRequestDto": {
      "type": "object",
      "properties": {
        "channel": {
          "type": "string",
          "enum": [
            "einvoice",
            "email",
            "manual",
            "print"
          ]
        },
        "recipientOverride": {
          "type": "string",
          "maxLength": 320
        },
        "note": {
          "type": "string",
          "maxLength": 1000
        }
      },
      "additionalProperties": false
    },
    "InvoiceDispatchViewDto": {
      "type": "object",
      "properties": {
        "id": {
          "type": "string"
        },
        "invoiceId": {
          "type": "string"
        },
        "channel": {
          "type": "string",
          "enum": [
            "einvoice",
            "email",
            "manual",
            "print"
          ]
        },
        "status": {
          "type": "string",
          "enum": [
            "queued",
            "sending",
            "sent",
            "delivered",
            "failed"
          ]
        },
        "recipient": {
          "type": "string"
        },
        "operatorMessageId": {
          "type": "string",
          "x-nullable": true
        },
        "errorCode": {
          "type": "string",
          "x-nullable": true
        },
        "testMode": {
          "type": "boolean"
        },
        "attemptNumber": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991
        },
        "artifactAttachmentId": {
          "type": "string",
          "x-nullable": true
        },
        "sentAt": {
          "type": "string",
          "x-nullable": true
        },
        "deliveredAt": {
          "type": "string",
          "x-nullable": true
        },
        "createdAt": {
          "type": "string"
        },
        "updatedAt": {
          "type": "string"
        }
      },
      "required": [
        "id",
        "invoiceId",
        "channel",
        "status",
        "recipient",
        "operatorMessageId",
        "errorCode",
        "testMode",
        "attemptNumber",
        "artifactAttachmentId",
        "sentAt",
        "deliveredAt",
        "createdAt",
        "updatedAt"
      ]
    },
    "PaymentPageResponseDto": {
      "type": "object",
      "properties": {
        "items": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "paymentDate": {
                "type": "string",
                "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
              },
              "amountCents": {
                "type": "integer",
                "minimum": -2147483647,
                "maximum": 2147483647
              },
              "reference": {
                "type": "string",
                "x-nullable": true
              },
              "payerName": {
                "type": "string",
                "x-nullable": true
              },
              "source": {
                "type": "string",
                "enum": [
                  "manual",
                  "netvisor",
                  "camt054"
                ]
              },
              "sourceRef": {
                "type": "string",
                "x-nullable": true
              },
              "bankImportId": {
                "type": "string",
                "x-nullable": true
              },
              "note": {
                "type": "string",
                "x-nullable": true
              },
              "allocatedCents": {
                "type": "integer",
                "minimum": -2147483647,
                "maximum": 2147483647
              },
              "unallocatedCents": {
                "type": "integer",
                "minimum": -2147483647,
                "maximum": 2147483647
              },
              "allocations": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "paymentId": {
                      "type": "string"
                    },
                    "invoiceId": {
                      "type": "string"
                    },
                    "invoiceNumberText": {
                      "type": "string",
                      "x-nullable": true
                    },
                    "customerName": {
                      "type": "string",
                      "x-nullable": true
                    },
                    "amountCents": {
                      "type": "integer",
                      "minimum": -2147483647,
                      "maximum": 2147483647
                    },
                    "createdAt": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "id",
                    "paymentId",
                    "invoiceId",
                    "invoiceNumberText",
                    "customerName",
                    "amountCents",
                    "createdAt"
                  ]
                }
              },
              "createdByName": {
                "type": "string",
                "x-nullable": true
              },
              "createdAt": {
                "type": "string"
              }
            },
            "required": [
              "id",
              "paymentDate",
              "amountCents",
              "reference",
              "payerName",
              "source",
              "sourceRef",
              "bankImportId",
              "note",
              "allocatedCents",
              "unallocatedCents",
              "allocations",
              "createdByName",
              "createdAt"
            ]
          }
        },
        "pageInfo": {
          "type": "object",
          "properties": {
            "nextCursor": {
              "type": "string",
              "x-nullable": true
            },
            "hasMore": {
              "type": "boolean"
            }
          },
          "required": [
            "nextCursor",
            "hasMore"
          ]
        }
      },
      "required": [
        "items",
        "pageInfo"
      ]
    },
    "RecordPaymentDto": {
      "type": "object",
      "properties": {
        "paymentDate": {
          "type": "string",
          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
        },
        "amountCents": {
          "type": "integer",
          "minimum": -2147483647,
          "maximum": 2147483647
        },
        "reference": {
          "type": "string",
          "maxLength": 35
        },
        "payerName": {
          "type": "string",
          "maxLength": 200
        },
        "note": {
          "type": "string",
          "maxLength": 500
        },
        "allocations": {
          "maxItems": 100,
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "invoiceId": {
                "type": "string",
                "format": "uuid",
                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
              },
              "amountCents": {
                "type": "integer",
                "minimum": -2147483647,
                "maximum": 2147483647
              }
            },
            "required": [
              "invoiceId",
              "amountCents"
            ],
            "additionalProperties": false
          }
        }
      },
      "required": [
        "paymentDate",
        "amountCents"
      ],
      "additionalProperties": false
    },
    "PaymentViewDto": {
      "type": "object",
      "properties": {
        "id": {
          "type": "string"
        },
        "paymentDate": {
          "type": "string",
          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
        },
        "amountCents": {
          "type": "integer",
          "minimum": -2147483647,
          "maximum": 2147483647
        },
        "reference": {
          "type": "string",
          "x-nullable": true
        },
        "payerName": {
          "type": "string",
          "x-nullable": true
        },
        "source": {
          "type": "string",
          "enum": [
            "manual",
            "netvisor",
            "camt054"
          ]
        },
        "sourceRef": {
          "type": "string",
          "x-nullable": true
        },
        "bankImportId": {
          "type": "string",
          "x-nullable": true
        },
        "note": {
          "type": "string",
          "x-nullable": true
        },
        "allocatedCents": {
          "type": "integer",
          "minimum": -2147483647,
          "maximum": 2147483647
        },
        "unallocatedCents": {
          "type": "integer",
          "minimum": -2147483647,
          "maximum": 2147483647
        },
        "allocations": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "paymentId": {
                "type": "string"
              },
              "invoiceId": {
                "type": "string"
              },
              "invoiceNumberText": {
                "type": "string",
                "x-nullable": true
              },
              "customerName": {
                "type": "string",
                "x-nullable": true
              },
              "amountCents": {
                "type": "integer",
                "minimum": -2147483647,
                "maximum": 2147483647
              },
              "createdAt": {
                "type": "string"
              }
            },
            "required": [
              "id",
              "paymentId",
              "invoiceId",
              "invoiceNumberText",
              "customerName",
              "amountCents",
              "createdAt"
            ]
          }
        },
        "createdByName": {
          "type": "string",
          "x-nullable": true
        },
        "createdAt": {
          "type": "string"
        }
      },
      "required": [
        "id",
        "paymentDate",
        "amountCents",
        "reference",
        "payerName",
        "source",
        "sourceRef",
        "bankImportId",
        "note",
        "allocatedCents",
        "unallocatedCents",
        "allocations",
        "createdByName",
        "createdAt"
      ]
    },
    "ArAgingResponseDto": {
      "type": "object",
      "properties": {
        "asOf": {
          "type": "string",
          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
        },
        "rows": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "customerId": {
                "type": "string"
              },
              "customerName": {
                "type": "string"
              },
              "invoiceCount": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "notDueCents": {
                "type": "integer",
                "minimum": -2147483647,
                "maximum": 2147483647
              },
              "days0to30Cents": {
                "type": "integer",
                "minimum": -2147483647,
                "maximum": 2147483647
              },
              "days31to60Cents": {
                "type": "integer",
                "minimum": -2147483647,
                "maximum": 2147483647
              },
              "days61to90Cents": {
                "type": "integer",
                "minimum": -2147483647,
                "maximum": 2147483647
              },
              "days90PlusCents": {
                "type": "integer",
                "minimum": -2147483647,
                "maximum": 2147483647
              },
              "overdueCents": {
                "type": "integer",
                "minimum": -2147483647,
                "maximum": 2147483647
              },
              "totalOpenCents": {
                "type": "integer",
                "minimum": -2147483647,
                "maximum": 2147483647
              }
            },
            "required": [
              "customerId",
              "customerName",
              "invoiceCount",
              "notDueCents",
              "days0to30Cents",
              "days31to60Cents",
              "days61to90Cents",
              "days90PlusCents",
              "overdueCents",
              "totalOpenCents"
            ]
          }
        },
        "totals": {
          "type": "object",
          "properties": {
            "invoiceCount": {
              "type": "integer",
              "minimum": -9007199254740991,
              "maximum": 9007199254740991
            },
            "notDueCents": {
              "type": "integer",
              "minimum": -2147483647,
              "maximum": 2147483647
            },
            "days0to30Cents": {
              "type": "integer",
              "minimum": -2147483647,
              "maximum": 2147483647
            },
            "days31to60Cents": {
              "type": "integer",
              "minimum": -2147483647,
              "maximum": 2147483647
            },
            "days61to90Cents": {
              "type": "integer",
              "minimum": -2147483647,
              "maximum": 2147483647
            },
            "days90PlusCents": {
              "type": "integer",
              "minimum": -2147483647,
              "maximum": 2147483647
            },
            "overdueCents": {
              "type": "integer",
              "minimum": -2147483647,
              "maximum": 2147483647
            },
            "totalOpenCents": {
              "type": "integer",
              "minimum": -2147483647,
              "maximum": 2147483647
            }
          },
          "required": [
            "invoiceCount",
            "notDueCents",
            "days0to30Cents",
            "days31to60Cents",
            "days61to90Cents",
            "days90PlusCents",
            "overdueCents",
            "totalOpenCents"
          ]
        }
      },
      "required": [
        "asOf",
        "rows",
        "totals"
      ]
    },
    "BankImportListResponseDto": {
      "type": "object",
      "properties": {
        "imports": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "importId": {
                "type": "string"
              },
              "fileName": {
                "type": "string"
              },
              "importedAt": {
                "type": "string"
              },
              "rowCount": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "matchedCount": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "unmatchedCount": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "duplicateCount": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "totalAmountCents": {
                "type": "integer",
                "minimum": -2147483647,
                "maximum": 2147483647
              },
              "importedByName": {
                "type": "string",
                "x-nullable": true
              }
            },
            "required": [
              "importId",
              "fileName",
              "importedAt",
              "rowCount",
              "matchedCount",
              "unmatchedCount",
              "duplicateCount",
              "totalAmountCents",
              "importedByName"
            ]
          }
        }
      },
      "required": [
        "imports"
      ]
    },
    "ImportBankFileDto": {
      "type": "object",
      "properties": {
        "fileName": {
          "type": "string",
          "minLength": 1,
          "maxLength": 255
        },
        "contentBase64": {
          "type": "string",
          "minLength": 1,
          "maxLength": 8000000
        }
      },
      "required": [
        "fileName",
        "contentBase64"
      ],
      "additionalProperties": false
    },
    "ImportResultViewDto": {
      "type": "object",
      "properties": {
        "importId": {
          "type": "string"
        },
        "fileName": {
          "type": "string"
        },
        "importedAt": {
          "type": "string"
        },
        "rowCount": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991
        },
        "matchedCount": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991
        },
        "unmatchedCount": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991
        },
        "duplicateCount": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991
        },
        "totalAmountCents": {
          "type": "integer",
          "minimum": -2147483647,
          "maximum": 2147483647
        },
        "rows": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "status": {
                "type": "string",
                "enum": [
                  "matched",
                  "unmatched",
                  "duplicate"
                ]
              },
              "valueDate": {
                "type": "string",
                "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
              },
              "amountCents": {
                "type": "integer",
                "minimum": -2147483647,
                "maximum": 2147483647
              },
              "reference": {
                "type": "string",
                "x-nullable": true
              },
              "payerName": {
                "type": "string",
                "x-nullable": true
              },
              "sourceRef": {
                "type": "string",
                "x-nullable": true
              },
              "paymentId": {
                "type": "string",
                "x-nullable": true
              },
              "invoiceId": {
                "type": "string",
                "x-nullable": true
              },
              "invoiceNumberText": {
                "type": "string",
                "x-nullable": true
              }
            },
            "required": [
              "status",
              "valueDate",
              "amountCents",
              "reference",
              "payerName",
              "sourceRef",
              "paymentId",
              "invoiceId",
              "invoiceNumberText"
            ]
          }
        }
      },
      "required": [
        "importId",
        "fileName",
        "importedAt",
        "rowCount",
        "matchedCount",
        "unmatchedCount",
        "duplicateCount",
        "totalAmountCents",
        "rows"
      ]
    },
    "CustomerPaymentBehaviourDto": {
      "type": "object",
      "properties": {
        "customerId": {
          "type": "string"
        },
        "averageDaysToPay": {
          "type": "number",
          "x-nullable": true
        },
        "paidInvoiceCount": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991
        },
        "overdueOpenCount": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991
        },
        "overdueOpenCents": {
          "type": "integer",
          "minimum": -2147483647,
          "maximum": 2147483647
        }
      },
      "required": [
        "customerId",
        "averageDaysToPay",
        "paidInvoiceCount",
        "overdueOpenCount",
        "overdueOpenCents"
      ]
    },
    "CustomerAdvanceBalanceResponseDto": {
      "type": "object",
      "properties": {
        "customerId": {
          "type": "string"
        },
        "availableCents": {
          "type": "integer",
          "minimum": -2147483647,
          "maximum": 2147483647
        },
        "advances": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "advanceInvoiceId": {
                "type": "string"
              },
              "invoiceNumberText": {
                "type": "string",
                "x-nullable": true
              },
              "invoiceDate": {
                "type": "string",
                "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
                "x-nullable": true
              },
              "grossTotalCents": {
                "type": "integer",
                "minimum": -2147483647,
                "maximum": 2147483647
              },
              "paidCents": {
                "type": "integer",
                "minimum": -2147483647,
                "maximum": 2147483647
              },
              "appliedCents": {
                "type": "integer",
                "minimum": -2147483647,
                "maximum": 2147483647
              },
              "availableCents": {
                "type": "integer",
                "minimum": -2147483647,
                "maximum": 2147483647
              }
            },
            "required": [
              "advanceInvoiceId",
              "invoiceNumberText",
              "invoiceDate",
              "grossTotalCents",
              "paidCents",
              "appliedCents",
              "availableCents"
            ]
          }
        }
      },
      "required": [
        "customerId",
        "availableCents",
        "advances"
      ]
    },
    "AllocatePaymentDto": {
      "type": "object",
      "properties": {
        "allocations": {
          "minItems": 1,
          "maxItems": 100,
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "invoiceId": {
                "type": "string",
                "format": "uuid",
                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
              },
              "amountCents": {
                "type": "integer",
                "minimum": -2147483647,
                "maximum": 2147483647
              }
            },
            "required": [
              "invoiceId",
              "amountCents"
            ],
            "additionalProperties": false
          }
        }
      },
      "required": [
        "allocations"
      ],
      "additionalProperties": false
    },
    "RecurringScheduleListResponseDto": {
      "type": "object",
      "properties": {
        "schedules": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "customerId": {
                "type": "string"
              },
              "customerName": {
                "type": "string"
              },
              "contactId": {
                "type": "string",
                "x-nullable": true
              },
              "contactName": {
                "type": "string",
                "x-nullable": true
              },
              "projectId": {
                "type": "string",
                "x-nullable": true
              },
              "projectName": {
                "type": "string",
                "x-nullable": true
              },
              "profileId": {
                "type": "string"
              },
              "cadence": {
                "type": "string",
                "enum": [
                  "monthly",
                  "quarterly",
                  "weekly"
                ]
              },
              "dayOfPeriod": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "weekday": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991,
                "x-nullable": true
              },
              "nextRunDate": {
                "type": "string",
                "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
                "x-nullable": true
              },
              "endDate": {
                "type": "string",
                "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
                "x-nullable": true
              },
              "includeTimeMaterials": {
                "type": "boolean"
              },
              "templateLines": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "description": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 500
                    },
                    "quantity": {
                      "default": 1,
                      "type": "number",
                      "exclusiveMinimum": true,
                      "maximum": 9999999,
                      "minimum": 0
                    },
                    "unit": {
                      "default": "fixed",
                      "type": "string",
                      "enum": [
                        "hour",
                        "piece",
                        "day",
                        "km",
                        "fixed"
                      ]
                    },
                    "unitPriceCents": {
                      "type": "integer",
                      "minimum": 0,
                      "maximum": 9007199254740991
                    },
                    "vatRate": {
                      "type": "number",
                      "minimum": 0,
                      "maximum": 100
                    },
                    "sortOrder": {
                      "type": "integer",
                      "minimum": 0,
                      "maximum": 100000
                    }
                  },
                  "required": [
                    "description",
                    "unitPriceCents"
                  ],
                  "additionalProperties": false
                }
              },
              "paymentTermDays": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991,
                "x-nullable": true
              },
              "language": {
                "type": "string",
                "enum": [
                  "fi",
                  "sv",
                  "en",
                  null
                ],
                "x-nullable": true
              },
              "active": {
                "type": "boolean"
              },
              "lastRunPeriod": {
                "type": "string",
                "x-nullable": true
              },
              "lastGeneratedInvoiceId": {
                "type": "string",
                "x-nullable": true
              },
              "createdAt": {
                "type": "string"
              },
              "updatedAt": {
                "type": "string"
              }
            },
            "required": [
              "id",
              "customerId",
              "customerName",
              "contactId",
              "contactName",
              "projectId",
              "projectName",
              "profileId",
              "cadence",
              "dayOfPeriod",
              "nextRunDate",
              "endDate",
              "includeTimeMaterials",
              "templateLines",
              "paymentTermDays",
              "language",
              "active",
              "lastRunPeriod",
              "lastGeneratedInvoiceId",
              "createdAt",
              "updatedAt"
            ]
          }
        }
      },
      "required": [
        "schedules"
      ]
    },
    "RecurringRunListResponseDto": {
      "type": "object",
      "properties": {
        "runs": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "scheduleId": {
                "type": "string",
                "x-nullable": true
              },
              "runAt": {
                "type": "string"
              },
              "trigger": {
                "type": "string",
                "enum": [
                  "tick",
                  "manual"
                ]
              },
              "createdCount": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "skippedCount": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "failedCount": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "triggeredByName": {
                "type": "string",
                "x-nullable": true
              },
              "details": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "scheduleId": {
                      "type": "string"
                    },
                    "customerName": {
                      "type": "string",
                      "x-nullable": true
                    },
                    "outcome": {
                      "type": "string",
                      "enum": [
                        "created",
                        "skipped",
                        "failed"
                      ]
                    },
                    "invoiceId": {
                      "type": "string",
                      "x-nullable": true
                    },
                    "code": {
                      "type": "string",
                      "x-nullable": true
                    }
                  },
                  "required": [
                    "scheduleId",
                    "customerName",
                    "outcome",
                    "invoiceId",
                    "code"
                  ]
                }
              }
            },
            "required": [
              "id",
              "scheduleId",
              "runAt",
              "trigger",
              "createdCount",
              "skippedCount",
              "failedCount",
              "triggeredByName",
              "details"
            ]
          }
        }
      },
      "required": [
        "runs"
      ]
    },
    "QuotePageResponseDto": {
      "type": "object",
      "properties": {
        "items": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "number": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "displayKey": {
                "type": "string"
              },
              "customerName": {
                "type": "string"
              },
              "title": {
                "type": "string"
              },
              "status": {
                "type": "string",
                "enum": [
                  "draft",
                  "sent",
                  "accepted",
                  "declined",
                  "expired"
                ]
              },
              "validUntil": {
                "type": "string",
                "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
                "x-nullable": true
              },
              "totalNetCents": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "totalGrossCents": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "projectId": {
                "type": "string",
                "x-nullable": true
              },
              "dealId": {
                "type": "string",
                "x-nullable": true
              },
              "templateName": {
                "type": "string",
                "x-nullable": true
              },
              "updatedAt": {
                "type": "string"
              },
              "createdAt": {
                "type": "string"
              }
            },
            "required": [
              "id",
              "number",
              "displayKey",
              "customerName",
              "title",
              "status",
              "validUntil",
              "totalNetCents",
              "totalGrossCents",
              "projectId",
              "dealId",
              "templateName",
              "updatedAt",
              "createdAt"
            ]
          }
        },
        "pageInfo": {
          "type": "object",
          "properties": {
            "nextCursor": {
              "type": "string",
              "x-nullable": true
            },
            "hasMore": {
              "type": "boolean"
            }
          },
          "required": [
            "nextCursor",
            "hasMore"
          ]
        },
        "meta": {
          "type": "object",
          "properties": {
            "byStatus": {
              "type": "array",
              "items": {
                "type": "object",
                "properties": {
                  "status": {
                    "type": "string",
                    "enum": [
                      "draft",
                      "sent",
                      "accepted",
                      "declined",
                      "expired"
                    ]
                  },
                  "count": {
                    "type": "integer",
                    "minimum": -9007199254740991,
                    "maximum": 9007199254740991
                  },
                  "netCents": {
                    "type": "integer",
                    "minimum": -9007199254740991,
                    "maximum": 9007199254740991
                  }
                },
                "required": [
                  "status",
                  "count",
                  "netCents"
                ]
              }
            }
          },
          "required": [
            "byStatus"
          ]
        }
      },
      "required": [
        "items",
        "pageInfo"
      ]
    },
    "CreateQuoteDto": {
      "type": "object",
      "properties": {
        "customerId": {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
        },
        "title": {
          "type": "string",
          "minLength": 1,
          "maxLength": 200
        },
        "language": {
          "default": "fi",
          "type": "string",
          "enum": [
            "fi",
            "sv",
            "en"
          ]
        },
        "validUntil": {
          "type": "string",
          "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
          "x-nullable": true
        },
        "dealId": {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
          "x-nullable": true
        },
        "contactId": {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
          "x-nullable": true
        },
        "projectId": {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
          "x-nullable": true
        }
      },
      "required": [
        "customerId",
        "title"
      ]
    },
    "QuoteIdResponseDto": {
      "type": "object",
      "properties": {
        "id": {
          "type": "string"
        }
      },
      "required": [
        "id"
      ]
    },
    "QuoteStatsResponseDto": {
      "type": "object",
      "properties": {
        "months": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "month": {
                "type": "string"
              },
              "sentCount": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "sentNetCents": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "acceptedCount": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "acceptedNetCents": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "declinedCount": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "hitratePct": {
                "type": "number",
                "x-nullable": true
              }
            },
            "required": [
              "month",
              "sentCount",
              "sentNetCents",
              "acceptedCount",
              "acceptedNetCents",
              "declinedCount",
              "hitratePct"
            ]
          }
        },
        "totals": {
          "type": "object",
          "properties": {
            "sentCount": {
              "type": "integer",
              "minimum": -9007199254740991,
              "maximum": 9007199254740991
            },
            "sentNetCents": {
              "type": "integer",
              "minimum": -9007199254740991,
              "maximum": 9007199254740991
            },
            "acceptedCount": {
              "type": "integer",
              "minimum": -9007199254740991,
              "maximum": 9007199254740991
            },
            "acceptedNetCents": {
              "type": "integer",
              "minimum": -9007199254740991,
              "maximum": 9007199254740991
            },
            "declinedCount": {
              "type": "integer",
              "minimum": -9007199254740991,
              "maximum": 9007199254740991
            },
            "hitratePct": {
              "type": "number",
              "x-nullable": true
            }
          },
          "required": [
            "sentCount",
            "sentNetCents",
            "acceptedCount",
            "acceptedNetCents",
            "declinedCount",
            "hitratePct"
          ]
        }
      },
      "required": [
        "months",
        "totals"
      ]
    },
    "QuoteViewDto": {
      "type": "object",
      "properties": {
        "id": {
          "type": "string"
        },
        "number": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991
        },
        "displayKey": {
          "type": "string"
        },
        "customerId": {
          "type": "string"
        },
        "customerName": {
          "type": "string"
        },
        "title": {
          "type": "string"
        },
        "language": {
          "type": "string",
          "enum": [
            "fi",
            "sv",
            "en"
          ]
        },
        "status": {
          "type": "string",
          "enum": [
            "draft",
            "sent",
            "accepted",
            "declined",
            "expired"
          ]
        },
        "validUntil": {
          "type": "string",
          "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
          "x-nullable": true
        },
        "introText": {
          "type": "string",
          "x-nullable": true
        },
        "termsText": {
          "type": "string",
          "x-nullable": true
        },
        "totalNetCents": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991
        },
        "totalVatCents": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991
        },
        "totalGrossCents": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991
        },
        "vatGroups": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "vatRate": {
                "type": "number"
              },
              "netCents": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "vatCents": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              }
            },
            "required": [
              "vatRate",
              "netCents",
              "vatCents"
            ]
          }
        },
        "sentAt": {
          "type": "string",
          "x-nullable": true
        },
        "decidedAt": {
          "type": "string",
          "x-nullable": true
        },
        "deciderName": {
          "type": "string",
          "x-nullable": true
        },
        "decisionComment": {
          "type": "string",
          "x-nullable": true
        },
        "projectId": {
          "type": "string",
          "x-nullable": true
        },
        "projectName": {
          "type": "string",
          "x-nullable": true
        },
        "dealId": {
          "type": "string",
          "x-nullable": true
        },
        "dealTitle": {
          "type": "string",
          "x-nullable": true
        },
        "contactId": {
          "type": "string",
          "x-nullable": true
        },
        "contactName": {
          "type": "string",
          "x-nullable": true
        },
        "hasActiveShare": {
          "type": "boolean"
        },
        "defaultWorkPriceCents": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991,
          "x-nullable": true
        },
        "defaultWorkCostCents": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991,
          "x-nullable": true
        },
        "templateName": {
          "type": "string",
          "x-nullable": true
        },
        "sections": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "title": {
                "type": "string"
              },
              "sortOrder": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              }
            },
            "required": [
              "id",
              "title",
              "sortOrder"
            ]
          }
        },
        "lines": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "sectionId": {
                "type": "string",
                "x-nullable": true
              },
              "sortOrder": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "kind": {
                "type": "string",
                "enum": [
                  "work",
                  "item",
                  "expense"
                ]
              },
              "description": {
                "type": "string"
              },
              "quantity": {
                "type": "number"
              },
              "unit": {
                "type": "string"
              },
              "unitPriceCents": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "vatRate": {
                "type": "number"
              },
              "discountPct": {
                "type": "number",
                "x-nullable": true
              },
              "unitCostCents": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991,
                "x-nullable": true
              },
              "netCents": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              }
            },
            "required": [
              "id",
              "sectionId",
              "sortOrder",
              "kind",
              "description",
              "quantity",
              "unit",
              "unitPriceCents",
              "vatRate",
              "discountPct",
              "unitCostCents",
              "netCents"
            ]
          }
        },
        "events": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "type": {
                "type": "string"
              },
              "actorName": {
                "type": "string",
                "x-nullable": true
              },
              "comment": {
                "type": "string",
                "x-nullable": true
              },
              "createdAt": {
                "type": "string"
              }
            },
            "required": [
              "id",
              "type",
              "actorName",
              "comment",
              "createdAt"
            ]
          }
        },
        "createdAt": {
          "type": "string"
        },
        "updatedAt": {
          "type": "string"
        }
      },
      "required": [
        "id",
        "number",
        "displayKey",
        "customerId",
        "customerName",
        "title",
        "language",
        "status",
        "validUntil",
        "introText",
        "termsText",
        "totalNetCents",
        "totalVatCents",
        "totalGrossCents",
        "vatGroups",
        "sentAt",
        "decidedAt",
        "deciderName",
        "decisionComment",
        "projectId",
        "projectName",
        "dealId",
        "dealTitle",
        "contactId",
        "contactName",
        "hasActiveShare",
        "defaultWorkPriceCents",
        "defaultWorkCostCents",
        "templateName",
        "sections",
        "lines",
        "events",
        "createdAt",
        "updatedAt"
      ]
    },
    "SendQuoteDto": {
      "type": "object",
      "properties": {
        "recipientEmail": {
          "type": "string",
          "format": "email",
          "pattern": "^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"
        },
        "recipientName": {
          "type": "string",
          "maxLength": 200
        },
        "message": {
          "type": "string",
          "maxLength": 2000
        }
      }
    },
    "SendQuoteResponseDto": {
      "type": "object",
      "properties": {
        "url": {
          "type": "string"
        },
        "emailed": {
          "type": "boolean"
        }
      },
      "required": [
        "url",
        "emailed"
      ]
    },
    "ConvertQuoteDto": {
      "type": "object",
      "properties": {
        "code": {
          "type": "string",
          "pattern": "^[a-z0-9][a-z0-9_-]{0,49}$"
        },
        "ownerMembershipId": {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
          "x-nullable": true
        },
        "billingModel": {
          "default": "fixed_price",
          "type": "string",
          "enum": [
            "fixed_price",
            "time_materials"
          ]
        },
        "startDate": {
          "type": "string",
          "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
          "x-nullable": true
        },
        "endDate": {
          "type": "string",
          "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
          "x-nullable": true
        },
        "createInstallmentsFromSections": {
          "default": false,
          "type": "boolean"
        }
      }
    },
    "BalanceAccountsResponseDto": {
      "type": "object",
      "properties": {
        "accounts": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "accountTypeId": {
                "type": "string"
              },
              "kind": {
                "type": "string",
                "enum": [
                  "flex",
                  "overtime_bank",
                  "worktime_bank",
                  "shorter_worktime"
                ]
              },
              "code": {
                "type": "string"
              },
              "nameFi": {
                "type": "string"
              },
              "nameSv": {
                "type": "string"
              },
              "nameEn": {
                "type": "string"
              },
              "totalMinutes": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "status": {
                "type": "string",
                "enum": [
                  "within-limits",
                  "over-max",
                  "under-min"
                ]
              },
              "capMaxMinutes": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991,
                "x-nullable": true
              },
              "capMinMinutes": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991,
                "x-nullable": true
              },
              "plannedDrawMinutes": {
                "default": 0,
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              }
            },
            "required": [
              "accountTypeId",
              "kind",
              "code",
              "nameFi",
              "nameSv",
              "nameEn",
              "totalMinutes",
              "status",
              "capMaxMinutes",
              "capMinMinutes"
            ]
          }
        }
      },
      "required": [
        "accounts"
      ]
    },
    "BulkCreateCustomersDto": {
      "type": "object",
      "properties": {
        "rows": {
          "minItems": 1,
          "maxItems": 500,
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "code": {
                "type": "string",
                "pattern": "^[a-z0-9][a-z0-9_-]{0,49}$"
              },
              "name": {
                "type": "string",
                "minLength": 1,
                "maxLength": 200
              },
              "businessId": {
                "type": "string",
                "maxLength": 20
              },
              "einvoiceAddress": {
                "type": "string",
                "maxLength": 50
              },
              "einvoiceOperator": {
                "type": "string",
                "maxLength": 50
              },
              "invoiceReference": {
                "type": "string",
                "maxLength": 50
              }
            },
            "required": [
              "name"
            ]
          }
        }
      },
      "required": [
        "rows"
      ]
    },
    "BulkImportResponseDto": {
      "type": "object",
      "properties": {
        "results": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "index": {
                "type": "integer",
                "minimum": 0,
                "maximum": 9007199254740991
              },
              "status": {
                "type": "string",
                "enum": [
                  "created",
                  "skipped",
                  "error"
                ]
              },
              "id": {
                "type": "string",
                "x-nullable": true
              },
              "code": {
                "type": "string",
                "x-nullable": true
              }
            },
            "required": [
              "index",
              "status",
              "id",
              "code"
            ]
          }
        }
      },
      "required": [
        "results"
      ]
    },
    "BulkCreateProjectsDto": {
      "type": "object",
      "properties": {
        "rows": {
          "minItems": 1,
          "maxItems": 500,
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "code": {
                "type": "string",
                "pattern": "^[a-z0-9][a-z0-9_-]{0,49}$"
              },
              "name": {
                "type": "string",
                "minLength": 1,
                "maxLength": 200
              },
              "customerCode": {
                "type": "string",
                "pattern": "^[a-z0-9][a-z0-9_-]{0,49}$"
              },
              "customerName": {
                "type": "string",
                "maxLength": 200
              },
              "ownerEmail": {
                "type": "string",
                "format": "email",
                "pattern": "^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"
              },
              "startDate": {
                "type": "string",
                "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
              },
              "endDate": {
                "type": "string",
                "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
              },
              "budgetMinutes": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "budgetAmountCents": {
                "type": "integer",
                "minimum": 0,
                "maximum": 9007199254740991
              },
              "billingModel": {
                "type": "string",
                "enum": [
                  "time_materials",
                  "fixed_price",
                  "non_billable",
                  "retainer"
                ]
              },
              "status": {
                "type": "string",
                "enum": [
                  "draft",
                  "active",
                  "on_hold",
                  "closed"
                ]
              }
            },
            "required": [
              "name"
            ]
          }
        },
        "createMissingCustomers": {
          "default": false,
          "type": "boolean"
        }
      },
      "required": [
        "rows"
      ]
    },
    "BulkCreateTasksDto": {
      "type": "object",
      "properties": {
        "rows": {
          "minItems": 1,
          "maxItems": 500,
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "projectCode": {
                "type": "string",
                "pattern": "^[a-z0-9][a-z0-9_-]{0,49}$"
              },
              "title": {
                "type": "string",
                "minLength": 1,
                "maxLength": 200
              },
              "description": {
                "type": "string",
                "maxLength": 8000
              },
              "assigneeEmail": {
                "type": "string",
                "format": "email",
                "pattern": "^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"
              },
              "startDate": {
                "type": "string",
                "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
              },
              "dueDate": {
                "type": "string",
                "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
              },
              "estimateMinutes": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "priority": {
                "type": "string",
                "enum": [
                  "low",
                  "normal",
                  "high",
                  "urgent"
                ]
              },
              "done": {
                "type": "boolean"
              }
            },
            "required": [
              "projectCode",
              "title"
            ]
          }
        }
      },
      "required": [
        "rows"
      ]
    },
    "BulkCreateLeadsDto": {
      "type": "object",
      "properties": {
        "rows": {
          "minItems": 1,
          "maxItems": 500,
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "title": {
                "type": "string",
                "minLength": 1,
                "maxLength": 200
              },
              "companyName": {
                "type": "string",
                "maxLength": 200
              },
              "businessId": {
                "type": "string",
                "maxLength": 20
              },
              "personName": {
                "type": "string",
                "maxLength": 200
              },
              "email": {
                "type": "string",
                "maxLength": 200,
                "format": "email",
                "pattern": "^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"
              },
              "phone": {
                "type": "string",
                "maxLength": 50
              },
              "notes": {
                "type": "string",
                "maxLength": 4000
              },
              "source": {
                "default": "import",
                "type": "string",
                "enum": [
                  "manual",
                  "intake",
                  "import",
                  "website",
                  "referral",
                  "other"
                ]
              }
            },
            "required": [
              "title"
            ]
          }
        }
      },
      "required": [
        "rows"
      ]
    },
    "BulkImportWithDuplicatesResponseDto": {
      "type": "object",
      "properties": {
        "results": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "index": {
                "type": "integer",
                "minimum": 0,
                "maximum": 9007199254740991
              },
              "status": {
                "type": "string",
                "enum": [
                  "created",
                  "skipped",
                  "error"
                ]
              },
              "id": {
                "type": "string",
                "x-nullable": true
              },
              "code": {
                "type": "string",
                "x-nullable": true
              }
            },
            "required": [
              "index",
              "status",
              "id",
              "code"
            ]
          }
        },
        "duplicates": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "index": {
                "type": "integer",
                "minimum": 0,
                "maximum": 9007199254740991
              },
              "reason": {
                "type": "string",
                "enum": [
                  "email",
                  "title_company"
                ]
              },
              "existingId": {
                "type": "string"
              }
            },
            "required": [
              "index",
              "reason",
              "existingId"
            ]
          }
        }
      },
      "required": [
        "results",
        "duplicates"
      ]
    },
    "BulkCreateContactsDto": {
      "type": "object",
      "properties": {
        "rows": {
          "minItems": 1,
          "maxItems": 500,
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "customerCode": {
                "type": "string",
                "pattern": "^[a-z0-9][a-z0-9_-]{0,49}$"
              },
              "firstName": {
                "type": "string",
                "minLength": 1,
                "maxLength": 100
              },
              "lastName": {
                "type": "string",
                "minLength": 1,
                "maxLength": 100
              },
              "title": {
                "type": "string",
                "maxLength": 100
              },
              "email": {
                "type": "string",
                "maxLength": 200,
                "format": "email",
                "pattern": "^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"
              },
              "phone": {
                "type": "string",
                "maxLength": 50
              },
              "role": {
                "type": "string",
                "maxLength": 100
              },
              "isPrimary": {
                "type": "boolean"
              }
            },
            "required": [
              "customerCode",
              "firstName",
              "lastName"
            ]
          }
        }
      },
      "required": [
        "rows"
      ]
    },
    "IntakeListResponseDto": {
      "type": "object",
      "properties": {
        "items": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "title": {
                "type": "string"
              },
              "details": {
                "type": "string",
                "x-nullable": true
              },
              "customerId": {
                "type": "string",
                "x-nullable": true
              },
              "customerName": {
                "type": "string",
                "x-nullable": true
              },
              "requesterName": {
                "type": "string",
                "x-nullable": true
              },
              "status": {
                "type": "string",
                "enum": [
                  "new",
                  "accepted",
                  "dismissed"
                ]
              },
              "createdByName": {
                "type": "string",
                "x-nullable": true
              },
              "createdAt": {
                "type": "string",
                "format": "date-time",
                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
              },
              "resolvedAt": {
                "type": "string",
                "format": "date-time",
                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$",
                "x-nullable": true
              },
              "projectId": {
                "type": "string",
                "x-nullable": true
              },
              "taskId": {
                "type": "string",
                "x-nullable": true
              },
              "leadId": {
                "type": "string",
                "x-nullable": true
              },
              "dismissReason": {
                "type": "string",
                "x-nullable": true
              }
            },
            "required": [
              "id",
              "title",
              "details",
              "customerId",
              "customerName",
              "requesterName",
              "status",
              "createdByName",
              "createdAt",
              "resolvedAt",
              "projectId",
              "taskId",
              "leadId",
              "dismissReason"
            ]
          }
        },
        "newCount": {
          "type": "integer",
          "minimum": 0,
          "maximum": 9007199254740991
        },
        "truncated": {
          "type": "boolean"
        }
      },
      "required": [
        "items",
        "newCount",
        "truncated"
      ]
    },
    "CreateIntakeItemDto": {
      "type": "object",
      "properties": {
        "title": {
          "type": "string",
          "minLength": 1,
          "maxLength": 200
        },
        "details": {
          "type": "string",
          "maxLength": 2000,
          "x-nullable": true
        },
        "customerId": {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
          "x-nullable": true
        },
        "requesterName": {
          "type": "string",
          "maxLength": 200,
          "x-nullable": true
        }
      },
      "required": [
        "title"
      ]
    },
    "IntakeItemViewDto": {
      "type": "object",
      "properties": {
        "id": {
          "type": "string"
        },
        "title": {
          "type": "string"
        },
        "details": {
          "type": "string",
          "x-nullable": true
        },
        "customerId": {
          "type": "string",
          "x-nullable": true
        },
        "customerName": {
          "type": "string",
          "x-nullable": true
        },
        "requesterName": {
          "type": "string",
          "x-nullable": true
        },
        "status": {
          "type": "string",
          "enum": [
            "new",
            "accepted",
            "dismissed"
          ]
        },
        "createdByName": {
          "type": "string",
          "x-nullable": true
        },
        "createdAt": {
          "type": "string",
          "format": "date-time",
          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
        },
        "resolvedAt": {
          "type": "string",
          "format": "date-time",
          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$",
          "x-nullable": true
        },
        "projectId": {
          "type": "string",
          "x-nullable": true
        },
        "taskId": {
          "type": "string",
          "x-nullable": true
        },
        "leadId": {
          "type": "string",
          "x-nullable": true
        },
        "dismissReason": {
          "type": "string",
          "x-nullable": true
        }
      },
      "required": [
        "id",
        "title",
        "details",
        "customerId",
        "customerName",
        "requesterName",
        "status",
        "createdByName",
        "createdAt",
        "resolvedAt",
        "projectId",
        "taskId",
        "leadId",
        "dismissReason"
      ]
    },
    "AcceptIntakeItemDto": {
      "type": "object",
      "properties": {
        "projectId": {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
        }
      },
      "required": [
        "projectId"
      ]
    },
    "RouteIntakeToLeadDto": {
      "type": "object",
      "properties": {
        "ownerMembershipId": {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
        }
      }
    },
    "DismissIntakeItemDto": {
      "type": "object",
      "properties": {
        "reason": {
          "type": "string",
          "maxLength": 500,
          "x-nullable": true
        }
      }
    },
    "ChangeOrderListResponseDto": {
      "type": "object",
      "properties": {
        "items": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "number": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "title": {
                "type": "string"
              },
              "description": {
                "type": "string",
                "x-nullable": true
              },
              "pricing": {
                "type": "string",
                "enum": [
                  "fixed",
                  "time_materials"
                ]
              },
              "amountCents": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991,
                "x-nullable": true
              },
              "status": {
                "type": "string",
                "enum": [
                  "draft",
                  "pending",
                  "approved",
                  "declined"
                ]
              },
              "approvedAt": {
                "type": "string",
                "format": "date-time",
                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$",
                "x-nullable": true
              },
              "approverContactId": {
                "type": "string",
                "x-nullable": true
              },
              "approverContactName": {
                "type": "string",
                "x-nullable": true
              },
              "approverName": {
                "type": "string",
                "x-nullable": true
              },
              "approvalComment": {
                "type": "string",
                "x-nullable": true
              },
              "approvedVia": {
                "type": "string",
                "enum": [
                  "link",
                  "manual",
                  null
                ],
                "x-nullable": true
              },
              "readyAt": {
                "type": "string",
                "format": "date-time",
                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$",
                "x-nullable": true
              },
              "invoiceState": {
                "type": "string",
                "enum": [
                  "none",
                  "draft_invoice",
                  "invoiced"
                ]
              },
              "createdAt": {
                "type": "string",
                "format": "date-time",
                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
              }
            },
            "required": [
              "id",
              "number",
              "title",
              "description",
              "pricing",
              "amountCents",
              "status",
              "approvedAt",
              "approverContactId",
              "approverContactName",
              "approverName",
              "approvalComment",
              "approvedVia",
              "readyAt",
              "invoiceState",
              "createdAt"
            ]
          }
        },
        "approvedCents": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991
        },
        "pendingCents": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991
        }
      },
      "required": [
        "items",
        "approvedCents",
        "pendingCents"
      ]
    },
    "CreateChangeOrderDto": {
      "type": "object",
      "properties": {
        "title": {
          "type": "string",
          "minLength": 1,
          "maxLength": 200
        },
        "description": {
          "type": "string",
          "maxLength": 4000,
          "x-nullable": true
        },
        "pricing": {
          "default": "fixed",
          "type": "string",
          "enum": [
            "fixed",
            "time_materials"
          ]
        },
        "amountCents": {
          "type": "integer",
          "exclusiveMinimum": 0,
          "maximum": 9007199254740991,
          "x-nullable": true
        }
      },
      "required": [
        "title"
      ]
    },
    "ChangeOrderViewDto": {
      "type": "object",
      "properties": {
        "id": {
          "type": "string"
        },
        "number": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991
        },
        "title": {
          "type": "string"
        },
        "description": {
          "type": "string",
          "x-nullable": true
        },
        "pricing": {
          "type": "string",
          "enum": [
            "fixed",
            "time_materials"
          ]
        },
        "amountCents": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991,
          "x-nullable": true
        },
        "status": {
          "type": "string",
          "enum": [
            "draft",
            "pending",
            "approved",
            "declined"
          ]
        },
        "approvedAt": {
          "type": "string",
          "format": "date-time",
          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$",
          "x-nullable": true
        },
        "approverContactId": {
          "type": "string",
          "x-nullable": true
        },
        "approverContactName": {
          "type": "string",
          "x-nullable": true
        },
        "approverName": {
          "type": "string",
          "x-nullable": true
        },
        "approvalComment": {
          "type": "string",
          "x-nullable": true
        },
        "approvedVia": {
          "type": "string",
          "enum": [
            "link",
            "manual",
            null
          ],
          "x-nullable": true
        },
        "readyAt": {
          "type": "string",
          "format": "date-time",
          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$",
          "x-nullable": true
        },
        "invoiceState": {
          "type": "string",
          "enum": [
            "none",
            "draft_invoice",
            "invoiced"
          ]
        },
        "createdAt": {
          "type": "string",
          "format": "date-time",
          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
        }
      },
      "required": [
        "id",
        "number",
        "title",
        "description",
        "pricing",
        "amountCents",
        "status",
        "approvedAt",
        "approverContactId",
        "approverContactName",
        "approverName",
        "approvalComment",
        "approvedVia",
        "readyAt",
        "invoiceState",
        "createdAt"
      ]
    },
    "ApproveChangeOrderDto": {
      "type": "object",
      "properties": {
        "approverName": {
          "type": "string",
          "minLength": 1,
          "maxLength": 100
        },
        "approverContactId": {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
          "x-nullable": true
        },
        "comment": {
          "type": "string",
          "maxLength": 2000,
          "x-nullable": true
        }
      },
      "required": [
        "approverName"
      ]
    },
    "SearchResponseDto": {
      "type": "object",
      "properties": {
        "people": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "membershipId": {
                "type": "string",
                "format": "uuid",
                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
              },
              "displayName": {
                "type": "string"
              },
              "email": {
                "type": "string"
              },
              "role": {
                "type": "string",
                "enum": [
                  "employee",
                  "manager",
                  "admin",
                  "payroll",
                  "hr"
                ]
              }
            },
            "required": [
              "membershipId",
              "displayName",
              "email",
              "role"
            ]
          }
        },
        "projects": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string",
                "format": "uuid",
                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
              },
              "name": {
                "type": "string"
              },
              "code": {
                "type": "string"
              },
              "customerName": {
                "type": "string",
                "x-nullable": true
              }
            },
            "required": [
              "id",
              "name",
              "code",
              "customerName"
            ]
          }
        },
        "tasks": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string",
                "format": "uuid",
                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
              },
              "title": {
                "type": "string"
              },
              "number": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "projectId": {
                "type": "string",
                "format": "uuid",
                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
              },
              "projectCode": {
                "type": "string"
              },
              "projectName": {
                "type": "string"
              }
            },
            "required": [
              "id",
              "title",
              "number",
              "projectId",
              "projectCode",
              "projectName"
            ]
          }
        },
        "customers": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string",
                "format": "uuid",
                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
              },
              "name": {
                "type": "string"
              },
              "code": {
                "type": "string"
              },
              "active": {
                "type": "boolean"
              }
            },
            "required": [
              "id",
              "name",
              "code",
              "active"
            ]
          }
        },
        "quotes": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string",
                "format": "uuid",
                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
              },
              "title": {
                "type": "string"
              },
              "displayKey": {
                "type": "string"
              },
              "customerName": {
                "type": "string"
              }
            },
            "required": [
              "id",
              "title",
              "displayKey",
              "customerName"
            ]
          }
        },
        "tesRulesets": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string",
                "format": "uuid",
                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
              },
              "key": {
                "type": "string"
              },
              "nameFi": {
                "type": "string"
              },
              "nameSv": {
                "type": "string"
              },
              "nameEn": {
                "type": "string"
              }
            },
            "required": [
              "id",
              "key",
              "nameFi",
              "nameSv",
              "nameEn"
            ]
          }
        },
        "deals": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string",
                "format": "uuid",
                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
              },
              "title": {
                "type": "string"
              },
              "customerId": {
                "type": "string",
                "format": "uuid",
                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
              },
              "customerName": {
                "type": "string"
              }
            },
            "required": [
              "id",
              "title",
              "customerId",
              "customerName"
            ]
          }
        },
        "leads": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string",
                "format": "uuid",
                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
              },
              "title": {
                "type": "string"
              },
              "companyName": {
                "type": "string",
                "x-nullable": true
              },
              "personName": {
                "type": "string",
                "x-nullable": true
              }
            },
            "required": [
              "id",
              "title",
              "companyName",
              "personName"
            ]
          }
        },
        "contacts": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string",
                "format": "uuid",
                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
              },
              "customerId": {
                "type": "string",
                "format": "uuid",
                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
              },
              "firstName": {
                "type": "string",
                "x-nullable": true
              },
              "lastName": {
                "type": "string",
                "x-nullable": true
              },
              "email": {
                "type": "string",
                "x-nullable": true
              },
              "customerName": {
                "type": "string"
              }
            },
            "required": [
              "id",
              "customerId",
              "firstName",
              "lastName",
              "email",
              "customerName"
            ]
          }
        },
        "activities": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string",
                "format": "uuid",
                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
              },
              "subject": {
                "type": "string"
              },
              "type": {
                "type": "string",
                "enum": [
                  "call",
                  "meeting",
                  "email",
                  "note",
                  "task"
                ]
              },
              "customerId": {
                "type": "string",
                "format": "uuid",
                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                "x-nullable": true
              },
              "dealId": {
                "type": "string",
                "format": "uuid",
                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                "x-nullable": true
              },
              "customerName": {
                "type": "string",
                "x-nullable": true
              }
            },
            "required": [
              "id",
              "subject",
              "type",
              "customerId",
              "dealId",
              "customerName"
            ]
          }
        }
      },
      "required": [
        "people",
        "projects",
        "tasks",
        "customers",
        "quotes",
        "tesRulesets",
        "deals",
        "leads",
        "contacts",
        "activities"
      ]
    },
    "ExpenseTypeListResponseDto": {
      "type": "object",
      "properties": {
        "expenseTypes": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "code": {
                "type": "string"
              },
              "nameFi": {
                "type": "string"
              },
              "nameSv": {
                "type": "string"
              },
              "nameEn": {
                "type": "string"
              },
              "kind": {
                "type": "string",
                "enum": [
                  "actual",
                  "unit_rate",
                  "tes"
                ]
              },
              "unit": {
                "type": "string",
                "enum": [
                  "piece",
                  "km",
                  "day"
                ]
              },
              "rateKey": {
                "type": "string",
                "x-nullable": true
              },
              "defaultReimbursable": {
                "type": "boolean"
              },
              "defaultBillable": {
                "type": "boolean"
              },
              "taxFree": {
                "type": "boolean"
              },
              "payComponentCode": {
                "type": "string",
                "x-nullable": true
              },
              "glAccount": {
                "type": "string",
                "x-nullable": true
              },
              "vatRate": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991,
                "x-nullable": true
              },
              "vatDeductible": {
                "type": "boolean"
              },
              "reportingClass": {
                "type": "string",
                "enum": [
                  "reported_tax_free",
                  "reported_taxable",
                  "not_reported"
                ]
              },
              "incomeType": {
                "type": "string",
                "x-nullable": true
              },
              "active": {
                "type": "boolean"
              },
              "isSystem": {
                "type": "boolean"
              },
              "locked": {
                "type": "boolean"
              },
              "sortOrder": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              }
            },
            "required": [
              "id",
              "code",
              "nameFi",
              "nameSv",
              "nameEn",
              "kind",
              "unit",
              "rateKey",
              "defaultReimbursable",
              "defaultBillable",
              "taxFree",
              "payComponentCode",
              "glAccount",
              "vatRate",
              "vatDeductible",
              "reportingClass",
              "incomeType",
              "active",
              "isSystem",
              "locked",
              "sortOrder"
            ]
          }
        }
      },
      "required": [
        "expenseTypes"
      ]
    },
    "ExpenseIdResponseDto": {
      "type": "object",
      "properties": {
        "id": {
          "type": "string"
        }
      },
      "required": [
        "id"
      ]
    },
    "ExpenseOkResponseDto": {
      "type": "object",
      "properties": {
        "ok": {
          "type": "boolean"
        }
      },
      "required": [
        "ok"
      ]
    },
    "ExpenseListResponseDto": {
      "type": "object",
      "properties": {
        "items": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "membershipId": {
                "type": "string"
              },
              "memberName": {
                "type": "string"
              },
              "expenseDate": {
                "type": "string",
                "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
              },
              "type": {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "string"
                  },
                  "code": {
                    "type": "string"
                  },
                  "nameFi": {
                    "type": "string"
                  },
                  "nameSv": {
                    "type": "string"
                  },
                  "nameEn": {
                    "type": "string"
                  },
                  "kind": {
                    "type": "string",
                    "enum": [
                      "actual",
                      "unit_rate",
                      "tes"
                    ]
                  },
                  "unit": {
                    "type": "string",
                    "enum": [
                      "piece",
                      "km",
                      "day"
                    ]
                  }
                },
                "required": [
                  "id",
                  "code",
                  "nameFi",
                  "nameSv",
                  "nameEn",
                  "kind",
                  "unit"
                ]
              },
              "description": {
                "type": "string",
                "x-nullable": true
              },
              "quantity": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991,
                "x-nullable": true
              },
              "amountCents": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "vatCents": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991,
                "x-nullable": true
              },
              "vatBreakdown": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "rateBps": {
                      "type": "integer",
                      "minimum": 0,
                      "maximum": 10000
                    },
                    "grossCents": {
                      "type": "integer",
                      "minimum": 0,
                      "maximum": 9007199254740991
                    },
                    "vatCents": {
                      "type": "integer",
                      "minimum": 0,
                      "maximum": 9007199254740991
                    }
                  },
                  "required": [
                    "rateBps",
                    "grossCents",
                    "vatCents"
                  ]
                },
                "x-nullable": true
              },
              "paidBy": {
                "type": "string",
                "enum": [
                  "company",
                  "employee"
                ]
              },
              "reimbursable": {
                "type": "boolean"
              },
              "billable": {
                "type": "boolean"
              },
              "billableAmountCents": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991,
                "x-nullable": true
              },
              "billingMode": {
                "type": "string",
                "enum": [
                  "billable_amount",
                  "cost",
                  "cost_multiplier",
                  "manual"
                ]
              },
              "billingMultiplierPermille": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991,
                "x-nullable": true
              },
              "dimensionValueId": {
                "type": "string",
                "x-nullable": true
              },
              "valueName": {
                "type": "string",
                "x-nullable": true
              },
              "allocations": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "dimensionId": {
                      "type": "string"
                    },
                    "valueId": {
                      "type": "string"
                    },
                    "valueName": {
                      "type": "string",
                      "x-nullable": true
                    }
                  },
                  "required": [
                    "dimensionId",
                    "valueId",
                    "valueName"
                  ]
                }
              },
              "status": {
                "type": "string",
                "enum": [
                  "draft",
                  "submitted",
                  "reviewed",
                  "approved"
                ]
              },
              "submittedAt": {
                "type": "string",
                "format": "date-time",
                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$",
                "x-nullable": true
              },
              "returnReason": {
                "type": "string",
                "x-nullable": true
              },
              "tripId": {
                "type": "string",
                "x-nullable": true
              },
              "tripDayId": {
                "type": "string",
                "x-nullable": true
              },
              "maxTaxFreeCents": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991,
                "x-nullable": true
              },
              "originalCurrency": {
                "type": "string",
                "x-nullable": true
              },
              "originalAmountCents": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991,
                "x-nullable": true
              },
              "mileage": {
                "type": "object",
                "properties": {
                  "kmHundredths": {
                    "type": "integer",
                    "minimum": -9007199254740991,
                    "maximum": 9007199254740991
                  },
                  "fromText": {
                    "type": "string",
                    "x-nullable": true
                  },
                  "toText": {
                    "type": "string",
                    "x-nullable": true
                  },
                  "roundTrip": {
                    "type": "boolean"
                  },
                  "additions": {
                    "type": "object",
                    "properties": {
                      "passengers": {
                        "type": "integer",
                        "minimum": 0,
                        "maximum": 9
                      },
                      "trailer": {
                        "type": "boolean"
                      },
                      "caravan": {
                        "type": "boolean"
                      },
                      "heavyLoad": {
                        "type": "boolean"
                      },
                      "machine": {
                        "type": "boolean"
                      },
                      "dog": {
                        "type": "boolean"
                      },
                      "forest": {
                        "type": "boolean"
                      }
                    },
                    "x-nullable": true
                  },
                  "source": {
                    "type": "string",
                    "enum": [
                      "manual",
                      "route",
                      "odometer",
                      "gps"
                    ]
                  },
                  "route": {
                    "type": "object",
                    "properties": {
                      "fromPlace": {
                        "type": "object",
                        "properties": {
                          "text": {
                            "type": "string",
                            "minLength": 1,
                            "maxLength": 160
                          },
                          "lat": {
                            "type": "number",
                            "minimum": -90,
                            "maximum": 90
                          },
                          "lon": {
                            "type": "number",
                            "minimum": -180,
                            "maximum": 180
                          }
                        },
                        "required": [
                          "text"
                        ]
                      },
                      "toPlace": {
                        "type": "object",
                        "properties": {
                          "text": {
                            "type": "string",
                            "minLength": 1,
                            "maxLength": 160
                          },
                          "lat": {
                            "type": "number",
                            "minimum": -90,
                            "maximum": 90
                          },
                          "lon": {
                            "type": "number",
                            "minimum": -180,
                            "maximum": 180
                          }
                        },
                        "required": [
                          "text"
                        ]
                      },
                      "waypoints": {
                        "maxItems": 15,
                        "type": "array",
                        "items": {
                          "type": "object",
                          "properties": {
                            "text": {
                              "type": "string",
                              "minLength": 1,
                              "maxLength": 160
                            },
                            "lat": {
                              "type": "number",
                              "minimum": -90,
                              "maximum": 90
                            },
                            "lon": {
                              "type": "number",
                              "minimum": -180,
                              "maximum": 180
                            }
                          },
                          "required": [
                            "text"
                          ]
                        }
                      },
                      "computedKmHundredths": {
                        "type": "integer",
                        "minimum": 0,
                        "maximum": 9007199254740991
                      },
                      "provider": {
                        "type": "string",
                        "maxLength": 40
                      },
                      "alternativeIndex": {
                        "type": "integer",
                        "minimum": 0,
                        "maximum": 9007199254740991
                      }
                    },
                    "required": [
                      "fromPlace",
                      "toPlace",
                      "computedKmHundredths"
                    ],
                    "x-nullable": true
                  },
                  "odometer": {
                    "type": "object",
                    "properties": {
                      "startKm": {
                        "type": "integer",
                        "minimum": 0,
                        "maximum": 9007199254740991
                      },
                      "endKm": {
                        "type": "integer",
                        "minimum": 0,
                        "maximum": 9007199254740991
                      }
                    },
                    "required": [
                      "startKm",
                      "endKm"
                    ],
                    "x-nullable": true
                  },
                  "vehicleId": {
                    "type": "string",
                    "x-nullable": true
                  }
                },
                "required": [
                  "kmHundredths",
                  "fromText",
                  "toText",
                  "roundTrip",
                  "additions",
                  "source",
                  "route",
                  "odometer",
                  "vehicleId"
                ],
                "x-nullable": true
              },
              "policyFlags": {
                "type": "array",
                "items": {
                  "type": "string",
                  "enum": [
                    "over_limit",
                    "receipt_required",
                    "project_required",
                    "meal_allowance_with_per_diem",
                    "possible_duplicate"
                  ]
                }
              },
              "hasReceipt": {
                "type": "boolean"
              },
              "exportedAt": {
                "type": "string",
                "x-nullable": true
              },
              "policyMaxPerExpenseCents": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991,
                "x-nullable": true
              }
            },
            "required": [
              "id",
              "membershipId",
              "memberName",
              "expenseDate",
              "type",
              "description",
              "quantity",
              "amountCents",
              "vatCents",
              "vatBreakdown",
              "paidBy",
              "reimbursable",
              "billable",
              "billableAmountCents",
              "dimensionValueId",
              "valueName",
              "allocations",
              "status",
              "submittedAt",
              "returnReason",
              "tripId",
              "tripDayId",
              "maxTaxFreeCents",
              "originalCurrency",
              "originalAmountCents",
              "mileage",
              "policyFlags",
              "hasReceipt",
              "exportedAt",
              "policyMaxPerExpenseCents"
            ]
          }
        },
        "pageInfo": {
          "type": "object",
          "properties": {
            "nextCursor": {
              "type": "string",
              "x-nullable": true
            },
            "hasMore": {
              "type": "boolean"
            }
          },
          "required": [
            "nextCursor",
            "hasMore"
          ]
        }
      },
      "required": [
        "items",
        "pageInfo"
      ]
    },
    "CreateExpenseDto": {
      "type": "object",
      "properties": {
        "expenseTypeId": {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
        },
        "expenseDate": {
          "type": "string",
          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
        },
        "description": {
          "type": "string",
          "maxLength": 500
        },
        "quantity": {
          "type": "integer",
          "minimum": 0,
          "maximum": 9007199254740991
        },
        "amountCents": {
          "type": "integer",
          "minimum": 0,
          "maximum": 9007199254740991
        },
        "vatCents": {
          "type": "integer",
          "minimum": 0,
          "maximum": 9007199254740991,
          "x-nullable": true
        },
        "vatBreakdown": {
          "maxItems": 4,
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "rateBps": {
                "type": "integer",
                "minimum": 0,
                "maximum": 10000
              },
              "grossCents": {
                "type": "integer",
                "minimum": 0,
                "maximum": 9007199254740991
              },
              "vatCents": {
                "type": "integer",
                "minimum": 0,
                "maximum": 9007199254740991
              }
            },
            "required": [
              "rateBps",
              "grossCents",
              "vatCents"
            ]
          },
          "x-nullable": true
        },
        "paidBy": {
          "type": "string",
          "enum": [
            "company",
            "employee"
          ]
        },
        "reimbursable": {
          "type": "boolean"
        },
        "billable": {
          "type": "boolean"
        },
        "billableAmountCents": {
          "type": "integer",
          "minimum": 0,
          "maximum": 9007199254740991,
          "x-nullable": true
        },
        "billingMode": {
          "type": "string",
          "enum": [
            "billable_amount",
            "cost",
            "cost_multiplier",
            "manual"
          ]
        },
        "billingMultiplierPermille": {
          "type": "integer",
          "minimum": 0,
          "maximum": 100000,
          "x-nullable": true
        },
        "dimensionValueId": {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
          "x-nullable": true
        },
        "allocations": {
          "maxItems": 20,
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "dimensionId": {
                "type": "string",
                "format": "uuid",
                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
              },
              "valueId": {
                "type": "string",
                "format": "uuid",
                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
              }
            },
            "required": [
              "dimensionId",
              "valueId"
            ]
          }
        },
        "tripId": {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
          "x-nullable": true
        },
        "tripDayId": {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
          "x-nullable": true
        },
        "originalCurrency": {
          "type": "string",
          "pattern": "^[A-Za-z]{3}$",
          "x-nullable": true
        },
        "originalAmountCents": {
          "type": "integer",
          "minimum": 0,
          "maximum": 9007199254740991,
          "x-nullable": true
        },
        "mileage": {
          "type": "object",
          "properties": {
            "kmHundredths": {
              "type": "integer",
              "minimum": 0,
              "maximum": 9007199254740991
            },
            "fromText": {
              "type": "string",
              "maxLength": 120
            },
            "toText": {
              "type": "string",
              "maxLength": 120
            },
            "roundTrip": {
              "type": "boolean"
            },
            "additions": {
              "type": "object",
              "properties": {
                "passengers": {
                  "type": "integer",
                  "minimum": 0,
                  "maximum": 9
                },
                "trailer": {
                  "type": "boolean"
                },
                "caravan": {
                  "type": "boolean"
                },
                "heavyLoad": {
                  "type": "boolean"
                },
                "machine": {
                  "type": "boolean"
                },
                "dog": {
                  "type": "boolean"
                },
                "forest": {
                  "type": "boolean"
                }
              }
            },
            "source": {
              "type": "string",
              "enum": [
                "manual",
                "route",
                "odometer",
                "gps"
              ]
            },
            "route": {
              "type": "object",
              "properties": {
                "fromPlace": {
                  "type": "object",
                  "properties": {
                    "text": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 160
                    },
                    "lat": {
                      "type": "number",
                      "minimum": -90,
                      "maximum": 90
                    },
                    "lon": {
                      "type": "number",
                      "minimum": -180,
                      "maximum": 180
                    }
                  },
                  "required": [
                    "text"
                  ]
                },
                "toPlace": {
                  "type": "object",
                  "properties": {
                    "text": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 160
                    },
                    "lat": {
                      "type": "number",
                      "minimum": -90,
                      "maximum": 90
                    },
                    "lon": {
                      "type": "number",
                      "minimum": -180,
                      "maximum": 180
                    }
                  },
                  "required": [
                    "text"
                  ]
                },
                "waypoints": {
                  "maxItems": 15,
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "text": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 160
                      },
                      "lat": {
                        "type": "number",
                        "minimum": -90,
                        "maximum": 90
                      },
                      "lon": {
                        "type": "number",
                        "minimum": -180,
                        "maximum": 180
                      }
                    },
                    "required": [
                      "text"
                    ]
                  }
                },
                "computedKmHundredths": {
                  "type": "integer",
                  "minimum": 0,
                  "maximum": 9007199254740991
                },
                "provider": {
                  "type": "string",
                  "maxLength": 40
                },
                "alternativeIndex": {
                  "type": "integer",
                  "minimum": 0,
                  "maximum": 9007199254740991
                }
              },
              "required": [
                "fromPlace",
                "toPlace",
                "computedKmHundredths"
              ]
            },
            "odometer": {
              "type": "object",
              "properties": {
                "startKm": {
                  "type": "integer",
                  "minimum": 0,
                  "maximum": 9007199254740991
                },
                "endKm": {
                  "type": "integer",
                  "minimum": 0,
                  "maximum": 9007199254740991
                }
              },
              "required": [
                "startKm",
                "endKm"
              ]
            },
            "vehicleId": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          "required": [
            "kmHundredths"
          ]
        }
      },
      "required": [
        "expenseTypeId",
        "expenseDate"
      ]
    },
    "UpdateExpenseDto": {
      "type": "object",
      "properties": {
        "expenseTypeId": {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
        },
        "expenseDate": {
          "type": "string",
          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
        },
        "description": {
          "type": "string",
          "maxLength": 500
        },
        "quantity": {
          "type": "integer",
          "minimum": 0,
          "maximum": 9007199254740991
        },
        "amountCents": {
          "type": "integer",
          "minimum": 0,
          "maximum": 9007199254740991
        },
        "vatCents": {
          "type": "integer",
          "minimum": 0,
          "maximum": 9007199254740991,
          "x-nullable": true
        },
        "vatBreakdown": {
          "maxItems": 4,
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "rateBps": {
                "type": "integer",
                "minimum": 0,
                "maximum": 10000
              },
              "grossCents": {
                "type": "integer",
                "minimum": 0,
                "maximum": 9007199254740991
              },
              "vatCents": {
                "type": "integer",
                "minimum": 0,
                "maximum": 9007199254740991
              }
            },
            "required": [
              "rateBps",
              "grossCents",
              "vatCents"
            ]
          },
          "x-nullable": true
        },
        "paidBy": {
          "type": "string",
          "enum": [
            "company",
            "employee"
          ]
        },
        "reimbursable": {
          "type": "boolean"
        },
        "billable": {
          "type": "boolean"
        },
        "billableAmountCents": {
          "type": "integer",
          "minimum": 0,
          "maximum": 9007199254740991,
          "x-nullable": true
        },
        "billingMode": {
          "type": "string",
          "enum": [
            "billable_amount",
            "cost",
            "cost_multiplier",
            "manual"
          ]
        },
        "billingMultiplierPermille": {
          "type": "integer",
          "minimum": 0,
          "maximum": 100000,
          "x-nullable": true
        },
        "dimensionValueId": {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
          "x-nullable": true
        },
        "allocations": {
          "maxItems": 20,
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "dimensionId": {
                "type": "string",
                "format": "uuid",
                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
              },
              "valueId": {
                "type": "string",
                "format": "uuid",
                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
              }
            },
            "required": [
              "dimensionId",
              "valueId"
            ]
          }
        },
        "tripId": {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
          "x-nullable": true
        },
        "tripDayId": {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
          "x-nullable": true
        },
        "originalCurrency": {
          "type": "string",
          "pattern": "^[A-Za-z]{3}$",
          "x-nullable": true
        },
        "originalAmountCents": {
          "type": "integer",
          "minimum": 0,
          "maximum": 9007199254740991,
          "x-nullable": true
        },
        "mileage": {
          "type": "object",
          "properties": {
            "kmHundredths": {
              "type": "integer",
              "minimum": 0,
              "maximum": 9007199254740991
            },
            "fromText": {
              "type": "string",
              "maxLength": 120
            },
            "toText": {
              "type": "string",
              "maxLength": 120
            },
            "roundTrip": {
              "type": "boolean"
            },
            "additions": {
              "type": "object",
              "properties": {
                "passengers": {
                  "type": "integer",
                  "minimum": 0,
                  "maximum": 9
                },
                "trailer": {
                  "type": "boolean"
                },
                "caravan": {
                  "type": "boolean"
                },
                "heavyLoad": {
                  "type": "boolean"
                },
                "machine": {
                  "type": "boolean"
                },
                "dog": {
                  "type": "boolean"
                },
                "forest": {
                  "type": "boolean"
                }
              }
            },
            "source": {
              "type": "string",
              "enum": [
                "manual",
                "route",
                "odometer",
                "gps"
              ]
            },
            "route": {
              "type": "object",
              "properties": {
                "fromPlace": {
                  "type": "object",
                  "properties": {
                    "text": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 160
                    },
                    "lat": {
                      "type": "number",
                      "minimum": -90,
                      "maximum": 90
                    },
                    "lon": {
                      "type": "number",
                      "minimum": -180,
                      "maximum": 180
                    }
                  },
                  "required": [
                    "text"
                  ]
                },
                "toPlace": {
                  "type": "object",
                  "properties": {
                    "text": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 160
                    },
                    "lat": {
                      "type": "number",
                      "minimum": -90,
                      "maximum": 90
                    },
                    "lon": {
                      "type": "number",
                      "minimum": -180,
                      "maximum": 180
                    }
                  },
                  "required": [
                    "text"
                  ]
                },
                "waypoints": {
                  "maxItems": 15,
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "text": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 160
                      },
                      "lat": {
                        "type": "number",
                        "minimum": -90,
                        "maximum": 90
                      },
                      "lon": {
                        "type": "number",
                        "minimum": -180,
                        "maximum": 180
                      }
                    },
                    "required": [
                      "text"
                    ]
                  }
                },
                "computedKmHundredths": {
                  "type": "integer",
                  "minimum": 0,
                  "maximum": 9007199254740991
                },
                "provider": {
                  "type": "string",
                  "maxLength": 40
                },
                "alternativeIndex": {
                  "type": "integer",
                  "minimum": 0,
                  "maximum": 9007199254740991
                }
              },
              "required": [
                "fromPlace",
                "toPlace",
                "computedKmHundredths"
              ]
            },
            "odometer": {
              "type": "object",
              "properties": {
                "startKm": {
                  "type": "integer",
                  "minimum": 0,
                  "maximum": 9007199254740991
                },
                "endKm": {
                  "type": "integer",
                  "minimum": 0,
                  "maximum": 9007199254740991
                }
              },
              "required": [
                "startKm",
                "endKm"
              ]
            },
            "vehicleId": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          "required": [
            "kmHundredths"
          ]
        }
      }
    },
    "ReturnExpenseDto": {
      "type": "object",
      "properties": {
        "reason": {
          "type": "string",
          "minLength": 1,
          "maxLength": 500
        }
      },
      "required": [
        "reason"
      ]
    },
    "PunchSessionStateDto": {
      "type": "object",
      "properties": {
        "enabled": {
          "type": "boolean"
        },
        "open": {
          "type": "boolean"
        },
        "onBreak": {
          "type": "boolean"
        },
        "workDate": {
          "type": "string",
          "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
          "x-nullable": true
        },
        "startedAt": {
          "type": "string",
          "x-nullable": true
        },
        "workMinutesSoFar": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991
        },
        "breakMinutesSoFar": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991
        },
        "completedBreakMinutes": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991
        },
        "breakStartedAt": {
          "type": "string",
          "x-nullable": true
        },
        "entryTypeId": {
          "type": "string",
          "x-nullable": true
        },
        "allocations": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "dimensionId": {
                "type": "string",
                "format": "uuid",
                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
              },
              "valueId": {
                "type": "string",
                "format": "uuid",
                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
              },
              "weightBp": {
                "default": 10000,
                "type": "integer",
                "minimum": 1,
                "maximum": 10000
              }
            },
            "required": [
              "dimensionId",
              "valueId"
            ]
          }
        },
        "task": {
          "type": "object",
          "properties": {
            "id": {
              "type": "string"
            },
            "taskKey": {
              "type": "string"
            },
            "title": {
              "type": "string"
            },
            "projectId": {
              "type": "string"
            }
          },
          "required": [
            "id",
            "taskKey",
            "title",
            "projectId"
          ],
          "x-nullable": true
        },
        "source": {
          "type": "string",
          "enum": [
            "web",
            "mobile",
            "device",
            "system",
            null
          ],
          "x-nullable": true
        },
        "locationCapture": {
          "type": "string",
          "enum": [
            "off",
            "site",
            "geofence",
            "coordinates"
          ]
        },
        "locationRequired": {
          "type": "boolean"
        },
        "locationPurposeTextFi": {
          "type": "string",
          "x-nullable": true
        },
        "locationPurposeTextSv": {
          "type": "string",
          "x-nullable": true
        },
        "locationPurposeTextEn": {
          "type": "string",
          "x-nullable": true
        },
        "sites": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "dimensionValueId": {
                "type": "string",
                "x-nullable": true
              },
              "nameFi": {
                "type": "string",
                "minLength": 1,
                "maxLength": 100
              },
              "nameSv": {
                "type": "string",
                "minLength": 1,
                "maxLength": 100
              },
              "nameEn": {
                "type": "string",
                "minLength": 1,
                "maxLength": 100
              },
              "latitude": {
                "type": "number"
              },
              "longitude": {
                "type": "number"
              },
              "radiusM": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              }
            },
            "required": [
              "id",
              "dimensionValueId",
              "nameFi",
              "nameSv",
              "nameEn",
              "latitude",
              "longitude",
              "radiusM"
            ]
          }
        },
        "prompts": {
          "type": "object",
          "properties": {
            "entryType": {
              "type": "string",
              "enum": [
                "hidden",
                "optional",
                "required"
              ]
            },
            "allocations": {
              "type": "string",
              "enum": [
                "hidden",
                "optional",
                "required"
              ]
            },
            "billable": {
              "type": "string",
              "enum": [
                "hidden",
                "optional",
                "required"
              ]
            },
            "note": {
              "type": "string",
              "enum": [
                "hidden",
                "optional",
                "required"
              ]
            },
            "clockOutReason": {
              "type": "string",
              "enum": [
                "hidden",
                "optional",
                "required"
              ]
            }
          },
          "required": [
            "entryType",
            "allocations",
            "billable",
            "note",
            "clockOutReason"
          ]
        },
        "backdatedPunchAllowed": {
          "default": true,
          "type": "boolean"
        },
        "backdatedPunchMaxHours": {
          "default": 72,
          "type": "integer",
          "minimum": 1,
          "maximum": 9007199254740991
        },
        "forgottenSessionAfterMinutes": {
          "default": 720,
          "type": "integer",
          "minimum": 0,
          "maximum": 9007199254740991
        },
        "returnGap": {
          "type": "object",
          "properties": {
            "fromDate": {
              "type": "string",
              "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
            },
            "toDate": {
              "type": "string",
              "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
            },
            "workdayCount": {
              "type": "integer",
              "minimum": 0,
              "maximum": 9007199254740991
            }
          },
          "required": [
            "fromDate",
            "toDate",
            "workdayCount"
          ],
          "default": null,
          "x-nullable": true
        },
        "noted": {
          "type": "object",
          "properties": {
            "code": {
              "type": "string"
            },
            "occurredAt": {
              "type": "string"
            }
          },
          "required": [
            "code",
            "occurredAt"
          ],
          "default": null,
          "x-nullable": true
        }
      },
      "required": [
        "enabled",
        "open",
        "onBreak",
        "workDate",
        "startedAt",
        "workMinutesSoFar",
        "breakMinutesSoFar",
        "completedBreakMinutes",
        "breakStartedAt",
        "entryTypeId",
        "allocations",
        "task",
        "source",
        "locationCapture",
        "locationRequired",
        "locationPurposeTextFi",
        "locationPurposeTextSv",
        "locationPurposeTextEn",
        "sites",
        "prompts"
      ]
    },
    "ClockInDto": {
      "type": "object",
      "properties": {
        "source": {
          "type": "string",
          "enum": [
            "web",
            "mobile"
          ]
        },
        "occurredAt": {
          "type": "string",
          "format": "date-time",
          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
        },
        "occurredAtSource": {
          "type": "string",
          "enum": [
            "captured",
            "entered"
          ]
        },
        "entryTypeId": {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
        },
        "allocations": {
          "maxItems": 10,
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "dimensionId": {
                "type": "string",
                "format": "uuid",
                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
              },
              "valueId": {
                "type": "string",
                "format": "uuid",
                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
              },
              "weightBp": {
                "default": 10000,
                "type": "integer",
                "minimum": 1,
                "maximum": 10000
              }
            },
            "required": [
              "dimensionId",
              "valueId"
            ]
          }
        },
        "taskId": {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
        },
        "billable": {
          "type": "boolean"
        },
        "note": {
          "type": "string",
          "maxLength": 500
        },
        "location": {
          "type": "object",
          "properties": {
            "mode": {
              "type": "string",
              "enum": [
                "site",
                "geofence",
                "coordinates"
              ]
            },
            "siteId": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            },
            "qrToken": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200
            },
            "latitude": {
              "type": "number",
              "minimum": -90,
              "maximum": 90
            },
            "longitude": {
              "type": "number",
              "minimum": -180,
              "maximum": 180
            },
            "accuracyMeters": {
              "type": "integer",
              "minimum": 0,
              "maximum": 9007199254740991
            }
          },
          "required": [
            "mode"
          ]
        },
        "clientPunchId": {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
        }
      },
      "required": [
        "source"
      ]
    },
    "PunchMarkDto": {
      "type": "object",
      "properties": {
        "source": {
          "type": "string",
          "enum": [
            "web",
            "mobile"
          ]
        },
        "occurredAt": {
          "type": "string",
          "format": "date-time",
          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
        },
        "occurredAtSource": {
          "type": "string",
          "enum": [
            "captured",
            "entered"
          ]
        },
        "location": {
          "type": "object",
          "properties": {
            "mode": {
              "type": "string",
              "enum": [
                "site",
                "geofence",
                "coordinates"
              ]
            },
            "siteId": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            },
            "qrToken": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200
            },
            "latitude": {
              "type": "number",
              "minimum": -90,
              "maximum": 90
            },
            "longitude": {
              "type": "number",
              "minimum": -180,
              "maximum": 180
            },
            "accuracyMeters": {
              "type": "integer",
              "minimum": 0,
              "maximum": 9007199254740991
            }
          },
          "required": [
            "mode"
          ]
        },
        "reasonId": {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
        },
        "expectedReturnDate": {
          "type": "string",
          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
        },
        "paid": {
          "type": "boolean"
        },
        "clientPunchId": {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
        }
      },
      "required": [
        "source"
      ]
    },
    "RecordAbsenceGapDto": {
      "type": "object",
      "properties": {
        "reasonId": {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
        },
        "fromDate": {
          "type": "string",
          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
        },
        "toDate": {
          "type": "string",
          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
        }
      },
      "required": [
        "reasonId",
        "fromDate",
        "toDate"
      ]
    },
    "SetPunchAllocationDto": {
      "type": "object",
      "properties": {
        "allocations": {
          "maxItems": 10,
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "dimensionId": {
                "type": "string",
                "format": "uuid",
                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
              },
              "valueId": {
                "type": "string",
                "format": "uuid",
                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
              },
              "weightBp": {
                "default": 10000,
                "type": "integer",
                "minimum": 1,
                "maximum": 10000
              }
            },
            "required": [
              "dimensionId",
              "valueId"
            ]
          }
        },
        "taskId": {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
        }
      }
    },
    "PunchDayViewDto": {
      "type": "object",
      "properties": {
        "workDate": {
          "type": "string",
          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
        },
        "events": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "kind": {
                "type": "string",
                "enum": [
                  "clock_in",
                  "clock_out",
                  "break_start",
                  "break_end"
                ]
              },
              "atMinutes": {
                "type": "integer",
                "minimum": 0,
                "maximum": 2880
              },
              "occurredAt": {
                "type": "string"
              },
              "occurredAtSource": {
                "type": "string",
                "enum": [
                  "captured",
                  "entered"
                ]
              },
              "recordedAt": {
                "type": "string",
                "x-nullable": true
              },
              "source": {
                "type": "string",
                "enum": [
                  "web",
                  "mobile",
                  "device",
                  "system"
                ]
              },
              "atSite": {
                "type": "boolean",
                "x-nullable": true
              },
              "reasonId": {
                "type": "string",
                "x-nullable": true
              },
              "paid": {
                "type": "boolean",
                "x-nullable": true
              },
              "noteCode": {
                "type": "string",
                "x-nullable": true
              },
              "counted": {
                "type": "boolean"
              }
            },
            "required": [
              "kind",
              "atMinutes",
              "occurredAt",
              "occurredAtSource",
              "recordedAt",
              "source",
              "atSite",
              "reasonId",
              "paid",
              "noteCode",
              "counted"
            ]
          }
        },
        "punchedStartMinutes": {
          "type": "integer",
          "minimum": 0,
          "maximum": 2880,
          "x-nullable": true
        },
        "punchedEndMinutes": {
          "type": "integer",
          "minimum": 1,
          "maximum": 2880,
          "x-nullable": true
        },
        "punchedWorkMinutes": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991
        },
        "punchedBreakMinutes": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991
        },
        "punchedPaidBreakMinutes": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991
        },
        "anomalies": {
          "default": [],
          "type": "array",
          "items": {
            "type": "string",
            "enum": [
              "out_of_range",
              "non_monotonic",
              "duplicate_clock_in",
              "clock_out_without_session",
              "break_without_session",
              "duplicate_break_start",
              "break_end_without_break",
              "open_session",
              "dst_repeated_hour",
              "overlap"
            ]
          }
        },
        "lockedPunchCount": {
          "default": 0,
          "type": "integer",
          "minimum": 0,
          "maximum": 9007199254740991
        }
      },
      "required": [
        "workDate",
        "events",
        "punchedStartMinutes",
        "punchedEndMinutes",
        "punchedWorkMinutes",
        "punchedBreakMinutes",
        "punchedPaidBreakMinutes"
      ]
    },
    "TeamPresenceViewDto": {
      "type": "object",
      "properties": {
        "items": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "membershipId": {
                "type": "string"
              },
              "displayName": {
                "type": "string"
              },
              "open": {
                "type": "boolean"
              },
              "onBreak": {
                "type": "boolean"
              },
              "startedAt": {
                "type": "string",
                "x-nullable": true
              },
              "workMinutesSoFar": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "atSite": {
                "type": "boolean",
                "x-nullable": true
              },
              "sincePreviousDay": {
                "default": false,
                "type": "boolean"
              },
              "workDate": {
                "type": "string",
                "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
                "default": null,
                "x-nullable": true
              },
              "openMinutes": {
                "default": 0,
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              }
            },
            "required": [
              "membershipId",
              "displayName",
              "open",
              "onBreak",
              "startedAt",
              "workMinutesSoFar",
              "atSite"
            ]
          }
        },
        "pageInfo": {
          "type": "object",
          "properties": {
            "nextCursor": {
              "type": "string",
              "x-nullable": true
            },
            "hasMore": {
              "type": "boolean"
            }
          },
          "required": [
            "nextCursor",
            "hasMore"
          ]
        },
        "coverage": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "requirementId": {
                "type": "string"
              },
              "planningUnitId": {
                "type": "string"
              },
              "planningUnitName": {
                "type": "string"
              },
              "startMinutes": {
                "type": "integer",
                "minimum": 0,
                "maximum": 1440
              },
              "endMinutes": {
                "type": "integer",
                "minimum": 1,
                "maximum": 2880
              },
              "requiredCount": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "positionId": {
                "type": "string",
                "x-nullable": true
              },
              "presentCount": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "shortfall": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              }
            },
            "required": [
              "requirementId",
              "planningUnitId",
              "planningUnitName",
              "startMinutes",
              "endMinutes",
              "requiredCount",
              "positionId",
              "presentCount",
              "shortfall"
            ]
          }
        },
        "absences": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "membershipId": {
                "type": "string"
              },
              "displayName": {
                "type": "string"
              },
              "nameFi": {
                "type": "string"
              },
              "nameSv": {
                "type": "string"
              },
              "nameEn": {
                "type": "string"
              },
              "source": {
                "type": "string",
                "enum": [
                  "leave",
                  "punch_intent"
                ]
              },
              "expectedReturnDate": {
                "type": "string",
                "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
                "x-nullable": true
              }
            },
            "required": [
              "membershipId",
              "displayName",
              "nameFi",
              "nameSv",
              "nameEn",
              "source",
              "expectedReturnDate"
            ]
          }
        }
      },
      "required": [
        "items",
        "pageInfo"
      ]
    },
    "PayrollPeriodLockListResponseDto": {
      "type": "object",
      "properties": {
        "locks": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "periodStart": {
                "type": "string",
                "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
              },
              "periodEnd": {
                "type": "string",
                "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
              },
              "note": {
                "type": "string",
                "x-nullable": true
              },
              "lockedByName": {
                "type": "string",
                "x-nullable": true
              },
              "lockedAt": {
                "type": "string"
              },
              "liftedAt": {
                "type": "string",
                "x-nullable": true
              },
              "liftedByName": {
                "type": "string",
                "x-nullable": true
              },
              "liftReason": {
                "type": "string",
                "x-nullable": true
              }
            },
            "required": [
              "id",
              "periodStart",
              "periodEnd",
              "note",
              "lockedByName",
              "lockedAt",
              "liftedAt",
              "liftedByName",
              "liftReason"
            ]
          }
        }
      },
      "required": [
        "locks"
      ]
    },
    "PublicReportTypesResponseDto": {
      "type": "object",
      "properties": {
        "types": {
          "type": "array",
          "items": {
            "type": "string",
            "enum": [
              "personal-time",
              "team-period",
              "team-absence",
              "overtime-balance",
              "missing-entries",
              "punch-log",
              "inspection",
              "supplement-breakdown",
              "exceptions",
              "staffing-coverage",
              "open-shift-activity",
              "gap-fill-activity",
              "projects",
              "tasks",
              "project-allocations",
              "project-realization",
              "project-utilization",
              "leave-balances",
              "leave-liability",
              "leave-bookkeeping",
              "travel-summary",
              "driving-log",
              "hr",
              "qualification-matrix",
              "corrections",
              "payroll-comparison",
              "schedule-adherence",
              "roster-compliance",
              "plan-vs-actual",
              "publish-compliance"
            ]
          }
        }
      },
      "required": [
        "types"
      ]
    },
    "ApprovalQueueResponseDto": {
      "type": "object",
      "properties": {
        "items": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "kind": {
                "type": "string",
                "enum": [
                  "work_week",
                  "expense",
                  "trip",
                  "leave",
                  "swap",
                  "training",
                  "open_shift_claim",
                  "leave_save"
                ]
              },
              "subject": {
                "type": "object",
                "properties": {
                  "membershipId": {
                    "type": "string"
                  },
                  "name": {
                    "type": "string"
                  },
                  "initials": {
                    "type": "string"
                  }
                },
                "required": [
                  "membershipId",
                  "name",
                  "initials"
                ]
              },
              "display": {
                "oneOf": [
                  {
                    "type": "object",
                    "properties": {
                      "kind": {
                        "type": "string",
                        "enum": [
                          "work_week"
                        ]
                      },
                      "mondayIso": {
                        "type": "string",
                        "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
                      },
                      "sundayIso": {
                        "type": "string",
                        "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
                      },
                      "dayCount": {
                        "type": "integer",
                        "minimum": 0,
                        "maximum": 9007199254740991
                      },
                      "netDeltaMinutes": {
                        "type": "integer",
                        "minimum": -9007199254740991,
                        "maximum": 9007199254740991
                      },
                      "workedMinutes": {
                        "type": "integer",
                        "minimum": 0,
                        "maximum": 9007199254740991
                      },
                      "targetMinutes": {
                        "type": "integer",
                        "minimum": 0,
                        "maximum": 9007199254740991
                      },
                      "supplementCount": {
                        "default": 0,
                        "type": "integer",
                        "minimum": 0,
                        "maximum": 9007199254740991
                      },
                      "attentionThresholdMinutes": {
                        "default": 0,
                        "type": "integer",
                        "minimum": 0,
                        "maximum": 9007199254740991
                      },
                      "appliedCreditMinutes": {
                        "default": 0,
                        "type": "integer",
                        "minimum": -9007199254740991,
                        "maximum": 9007199254740991
                      },
                      "weekSignals": {
                        "default": [],
                        "type": "array",
                        "items": {
                          "type": "object",
                          "properties": {
                            "type": {
                              "type": "string",
                              "enum": [
                                "insufficient-daily-rest",
                                "insufficient-weekly-rest",
                                "weekly-hours-high",
                                "consecutive-work-days-high"
                              ]
                            },
                            "workDate": {
                              "type": "string",
                              "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
                            },
                            "value": {
                              "type": "integer",
                              "minimum": 0,
                              "maximum": 9007199254740991
                            },
                            "limit": {
                              "type": "integer",
                              "minimum": 0,
                              "maximum": 9007199254740991
                            }
                          },
                          "required": [
                            "type",
                            "workDate",
                            "value",
                            "limit"
                          ]
                        }
                      }
                    },
                    "required": [
                      "kind",
                      "mondayIso",
                      "sundayIso",
                      "dayCount",
                      "netDeltaMinutes",
                      "workedMinutes",
                      "targetMinutes"
                    ]
                  },
                  {
                    "type": "object",
                    "properties": {
                      "kind": {
                        "type": "string",
                        "enum": [
                          "expense"
                        ]
                      },
                      "type": {
                        "type": "object",
                        "properties": {
                          "nameFi": {
                            "type": "string"
                          },
                          "nameSv": {
                            "type": "string"
                          },
                          "nameEn": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "nameFi",
                          "nameSv",
                          "nameEn"
                        ]
                      },
                      "description": {
                        "type": "string",
                        "x-nullable": true
                      },
                      "expenseDate": {
                        "type": "string",
                        "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
                      },
                      "amountCents": {
                        "type": "integer",
                        "minimum": -9007199254740991,
                        "maximum": 9007199254740991
                      },
                      "vatCents": {
                        "type": "integer",
                        "minimum": -9007199254740991,
                        "maximum": 9007199254740991,
                        "x-nullable": true
                      },
                      "paidBy": {
                        "type": "string",
                        "enum": [
                          "company",
                          "employee"
                        ]
                      },
                      "reimbursable": {
                        "type": "boolean"
                      },
                      "billable": {
                        "type": "boolean"
                      },
                      "billableAmountCents": {
                        "type": "integer",
                        "minimum": -9007199254740991,
                        "maximum": 9007199254740991,
                        "x-nullable": true
                      },
                      "valueName": {
                        "type": "string",
                        "x-nullable": true
                      },
                      "allocations": {
                        "type": "array",
                        "items": {
                          "type": "object",
                          "properties": {
                            "dimensionId": {
                              "type": "string"
                            },
                            "valueId": {
                              "type": "string"
                            },
                            "valueName": {
                              "type": "string",
                              "x-nullable": true
                            }
                          },
                          "required": [
                            "dimensionId",
                            "valueId",
                            "valueName"
                          ]
                        }
                      },
                      "maxTaxFreeCents": {
                        "type": "integer",
                        "minimum": -9007199254740991,
                        "maximum": 9007199254740991,
                        "x-nullable": true
                      },
                      "originalCurrency": {
                        "type": "string",
                        "x-nullable": true
                      },
                      "originalAmountCents": {
                        "type": "integer",
                        "minimum": -9007199254740991,
                        "maximum": 9007199254740991,
                        "x-nullable": true
                      },
                      "hasReceipt": {
                        "type": "boolean"
                      },
                      "policyMaxPerExpenseCents": {
                        "type": "integer",
                        "minimum": -9007199254740991,
                        "maximum": 9007199254740991,
                        "x-nullable": true
                      },
                      "mileage": {
                        "type": "object",
                        "properties": {
                          "fromText": {
                            "type": "string",
                            "x-nullable": true
                          },
                          "toText": {
                            "type": "string",
                            "x-nullable": true
                          },
                          "kmHundredths": {
                            "type": "integer",
                            "minimum": -9007199254740991,
                            "maximum": 9007199254740991
                          },
                          "roundTrip": {
                            "type": "boolean"
                          }
                        },
                        "required": [
                          "fromText",
                          "toText",
                          "kmHundredths",
                          "roundTrip"
                        ],
                        "x-nullable": true
                      }
                    },
                    "required": [
                      "kind",
                      "type",
                      "description",
                      "expenseDate",
                      "amountCents",
                      "vatCents",
                      "paidBy",
                      "reimbursable",
                      "billable",
                      "billableAmountCents",
                      "valueName",
                      "allocations",
                      "maxTaxFreeCents",
                      "originalCurrency",
                      "originalAmountCents",
                      "hasReceipt",
                      "policyMaxPerExpenseCents",
                      "mileage"
                    ]
                  },
                  {
                    "type": "object",
                    "properties": {
                      "kind": {
                        "type": "string",
                        "enum": [
                          "trip"
                        ]
                      },
                      "destination": {
                        "type": "string"
                      },
                      "scope": {
                        "type": "string",
                        "enum": [
                          "domestic",
                          "foreign"
                        ]
                      },
                      "startDate": {
                        "type": "string",
                        "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
                      },
                      "endDate": {
                        "type": "string",
                        "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
                      },
                      "dayCount": {
                        "type": "integer",
                        "minimum": 0,
                        "maximum": 9007199254740991
                      },
                      "taxFreeTotalCents": {
                        "type": "integer",
                        "minimum": -9007199254740991,
                        "maximum": 9007199254740991
                      },
                      "taxableTotalCents": {
                        "type": "integer",
                        "minimum": -9007199254740991,
                        "maximum": 9007199254740991
                      },
                      "reimbursableTotalCents": {
                        "type": "integer",
                        "minimum": -9007199254740991,
                        "maximum": 9007199254740991
                      },
                      "valueName": {
                        "type": "string",
                        "x-nullable": true
                      },
                      "allocations": {
                        "type": "array",
                        "items": {
                          "type": "object",
                          "properties": {
                            "dimensionId": {
                              "type": "string"
                            },
                            "valueId": {
                              "type": "string"
                            },
                            "valueName": {
                              "type": "string",
                              "x-nullable": true
                            }
                          },
                          "required": [
                            "dimensionId",
                            "valueId",
                            "valueName"
                          ]
                        }
                      },
                      "billable": {
                        "type": "boolean"
                      }
                    },
                    "required": [
                      "kind",
                      "destination",
                      "scope",
                      "startDate",
                      "endDate",
                      "dayCount",
                      "taxFreeTotalCents",
                      "taxableTotalCents",
                      "reimbursableTotalCents",
                      "valueName",
                      "allocations",
                      "billable"
                    ]
                  },
                  {
                    "type": "object",
                    "properties": {
                      "kind": {
                        "type": "string",
                        "enum": [
                          "leave"
                        ]
                      },
                      "policy": {
                        "type": "object",
                        "properties": {
                          "nameFi": {
                            "type": "string"
                          },
                          "nameSv": {
                            "type": "string"
                          },
                          "nameEn": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "nameFi",
                          "nameSv",
                          "nameEn"
                        ]
                      },
                      "sensitivity": {
                        "type": "string",
                        "enum": [
                          "normal",
                          "restricted",
                          "health"
                        ]
                      },
                      "startDate": {
                        "type": "string",
                        "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
                      },
                      "endDate": {
                        "type": "string",
                        "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
                      },
                      "startHalfDay": {
                        "type": "boolean"
                      },
                      "endHalfDay": {
                        "type": "boolean"
                      },
                      "consumesQuarterDays": {
                        "type": "integer",
                        "minimum": 0,
                        "maximum": 9007199254740991
                      },
                      "consumesMinutes": {
                        "type": "integer",
                        "minimum": 0,
                        "maximum": 9007199254740991
                      },
                      "certificateRequired": {
                        "type": "boolean"
                      },
                      "certificateStatus": {
                        "type": "string",
                        "enum": [
                          "missing",
                          "provided",
                          "waived",
                          null
                        ],
                        "x-nullable": true
                      }
                    },
                    "required": [
                      "kind",
                      "policy",
                      "sensitivity",
                      "startDate",
                      "endDate",
                      "startHalfDay",
                      "endHalfDay",
                      "consumesQuarterDays",
                      "consumesMinutes",
                      "certificateRequired",
                      "certificateStatus"
                    ]
                  },
                  {
                    "type": "object",
                    "properties": {
                      "kind": {
                        "type": "string",
                        "enum": [
                          "swap"
                        ]
                      },
                      "requesterName": {
                        "type": "string"
                      },
                      "requesterDate": {
                        "type": "string",
                        "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
                      },
                      "counterpartyMembershipId": {
                        "type": "string",
                        "x-nullable": true
                      },
                      "counterpartyName": {
                        "type": "string",
                        "x-nullable": true
                      },
                      "counterpartyDate": {
                        "type": "string",
                        "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
                        "x-nullable": true
                      },
                      "isGiveAway": {
                        "type": "boolean"
                      },
                      "reason": {
                        "type": "string",
                        "x-nullable": true
                      }
                    },
                    "required": [
                      "kind",
                      "requesterName",
                      "requesterDate",
                      "counterpartyMembershipId",
                      "counterpartyName",
                      "counterpartyDate",
                      "isGiveAway",
                      "reason"
                    ]
                  },
                  {
                    "type": "object",
                    "properties": {
                      "kind": {
                        "type": "string",
                        "enum": [
                          "training"
                        ]
                      },
                      "courseName": {
                        "type": "string"
                      },
                      "justification": {
                        "type": "string"
                      },
                      "costCenter": {
                        "type": "string",
                        "x-nullable": true
                      },
                      "proposedDate": {
                        "type": "string",
                        "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
                        "x-nullable": true
                      }
                    },
                    "required": [
                      "kind",
                      "courseName",
                      "justification",
                      "costCenter",
                      "proposedDate"
                    ]
                  },
                  {
                    "type": "object",
                    "properties": {
                      "kind": {
                        "type": "string",
                        "enum": [
                          "open_shift_claim"
                        ]
                      },
                      "date": {
                        "type": "string",
                        "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
                      },
                      "startMinutes": {
                        "type": "integer",
                        "minimum": 0,
                        "maximum": 1440,
                        "x-nullable": true
                      },
                      "endMinutes": {
                        "type": "integer",
                        "minimum": 1,
                        "maximum": 2880,
                        "x-nullable": true
                      },
                      "unitName": {
                        "type": "string"
                      },
                      "claimantName": {
                        "type": "string"
                      },
                      "otherClaimantCount": {
                        "type": "integer",
                        "minimum": 0,
                        "maximum": 9007199254740991
                      }
                    },
                    "required": [
                      "kind",
                      "date",
                      "startMinutes",
                      "endMinutes",
                      "unitName",
                      "claimantName",
                      "otherClaimantCount"
                    ]
                  },
                  {
                    "type": "object",
                    "properties": {
                      "kind": {
                        "type": "string",
                        "enum": [
                          "leave_save"
                        ]
                      },
                      "quarterDays": {
                        "type": "integer",
                        "exclusiveMinimum": true,
                        "maximum": 9007199254740991,
                        "minimum": 0
                      },
                      "annualBalanceQuarterDays": {
                        "type": "integer",
                        "minimum": -9007199254740991,
                        "maximum": 9007199254740991
                      },
                      "saveableQuarterDays": {
                        "type": "integer",
                        "minimum": 0,
                        "maximum": 9007199254740991
                      },
                      "reason": {
                        "type": "string",
                        "x-nullable": true
                      }
                    },
                    "required": [
                      "kind",
                      "quarterDays",
                      "annualBalanceQuarterDays",
                      "saveableQuarterDays",
                      "reason"
                    ]
                  }
                ]
              },
              "submittedAt": {
                "type": "string",
                "format": "date-time",
                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
              },
              "attention": {
                "type": "object",
                "properties": {
                  "level": {
                    "type": "string",
                    "enum": [
                      "clean",
                      "attention"
                    ]
                  },
                  "reasons": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  }
                },
                "required": [
                  "level",
                  "reasons"
                ]
              },
              "bulkEligible": {
                "type": "boolean"
              },
              "notices": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "code": {
                      "type": "string"
                    },
                    "dates": {
                      "default": [],
                      "type": "array",
                      "items": {
                        "type": "string",
                        "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
                      }
                    }
                  },
                  "required": [
                    "code"
                  ]
                }
              },
              "entity": {
                "oneOf": [
                  {
                    "type": "object",
                    "properties": {
                      "kind": {
                        "type": "string",
                        "enum": [
                          "work_week"
                        ]
                      },
                      "membershipId": {
                        "type": "string"
                      },
                      "mondayIso": {
                        "type": "string",
                        "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
                      },
                      "workDayIds": {
                        "type": "array",
                        "items": {
                          "type": "string"
                        }
                      }
                    },
                    "required": [
                      "kind",
                      "membershipId",
                      "mondayIso",
                      "workDayIds"
                    ]
                  },
                  {
                    "type": "object",
                    "properties": {
                      "kind": {
                        "type": "string",
                        "enum": [
                          "expense"
                        ]
                      },
                      "expenseId": {
                        "type": "string"
                      }
                    },
                    "required": [
                      "kind",
                      "expenseId"
                    ]
                  },
                  {
                    "type": "object",
                    "properties": {
                      "kind": {
                        "type": "string",
                        "enum": [
                          "trip"
                        ]
                      },
                      "tripId": {
                        "type": "string"
                      }
                    },
                    "required": [
                      "kind",
                      "tripId"
                    ]
                  },
                  {
                    "type": "object",
                    "properties": {
                      "kind": {
                        "type": "string",
                        "enum": [
                          "leave"
                        ]
                      },
                      "periodId": {
                        "type": "string"
                      }
                    },
                    "required": [
                      "kind",
                      "periodId"
                    ]
                  },
                  {
                    "type": "object",
                    "properties": {
                      "kind": {
                        "type": "string",
                        "enum": [
                          "swap"
                        ]
                      },
                      "swapId": {
                        "type": "string"
                      },
                      "planningUnitId": {
                        "type": "string"
                      }
                    },
                    "required": [
                      "kind",
                      "swapId",
                      "planningUnitId"
                    ]
                  },
                  {
                    "type": "object",
                    "properties": {
                      "kind": {
                        "type": "string",
                        "enum": [
                          "training"
                        ]
                      },
                      "requestId": {
                        "type": "string"
                      }
                    },
                    "required": [
                      "kind",
                      "requestId"
                    ]
                  },
                  {
                    "type": "object",
                    "properties": {
                      "kind": {
                        "type": "string",
                        "enum": [
                          "open_shift_claim"
                        ]
                      },
                      "openShiftId": {
                        "type": "string"
                      },
                      "membershipId": {
                        "type": "string"
                      },
                      "planningUnitId": {
                        "type": "string"
                      }
                    },
                    "required": [
                      "kind",
                      "openShiftId",
                      "membershipId",
                      "planningUnitId"
                    ]
                  },
                  {
                    "type": "object",
                    "properties": {
                      "kind": {
                        "type": "string",
                        "enum": [
                          "leave_save"
                        ]
                      },
                      "proposalId": {
                        "type": "string"
                      }
                    },
                    "required": [
                      "kind",
                      "proposalId"
                    ]
                  }
                ]
              },
              "can": {
                "type": "object",
                "properties": {
                  "approve": {
                    "type": "boolean"
                  },
                  "return": {
                    "type": "boolean"
                  }
                },
                "required": [
                  "approve",
                  "return"
                ]
              },
              "lockToken": {
                "type": "string",
                "x-nullable": true
              }
            },
            "required": [
              "id",
              "kind",
              "subject",
              "display",
              "submittedAt",
              "attention",
              "bulkEligible",
              "entity",
              "can",
              "lockToken"
            ]
          }
        },
        "pageInfo": {
          "type": "object",
          "properties": {
            "nextCursor": {
              "type": "string",
              "x-nullable": true
            },
            "hasMore": {
              "type": "boolean"
            }
          },
          "required": [
            "nextCursor",
            "hasMore"
          ]
        },
        "counts": {
          "type": "object",
          "properties": {
            "total": {
              "type": "integer",
              "minimum": 0,
              "maximum": 9007199254740991
            },
            "byKind": {
              "type": "object",
              "properties": {
                "work_week": {
                  "type": "integer",
                  "minimum": 0,
                  "maximum": 9007199254740991
                },
                "expense": {
                  "type": "integer",
                  "minimum": 0,
                  "maximum": 9007199254740991
                },
                "trip": {
                  "type": "integer",
                  "minimum": 0,
                  "maximum": 9007199254740991
                },
                "leave": {
                  "type": "integer",
                  "minimum": 0,
                  "maximum": 9007199254740991
                },
                "swap": {
                  "type": "integer",
                  "minimum": 0,
                  "maximum": 9007199254740991
                },
                "training": {
                  "type": "integer",
                  "minimum": 0,
                  "maximum": 9007199254740991
                },
                "open_shift_claim": {
                  "type": "integer",
                  "minimum": 0,
                  "maximum": 9007199254740991
                },
                "leave_save": {
                  "type": "integer",
                  "minimum": 0,
                  "maximum": 9007199254740991
                }
              },
              "required": [
                "work_week",
                "expense",
                "trip",
                "leave",
                "swap",
                "training",
                "open_shift_claim",
                "leave_save"
              ]
            },
            "attention": {
              "type": "integer",
              "minimum": 0,
              "maximum": 9007199254740991
            },
            "bulkEligible": {
              "type": "integer",
              "minimum": 0,
              "maximum": 9007199254740991
            }
          },
          "required": [
            "total",
            "byKind",
            "attention",
            "bulkEligible"
          ]
        },
        "truncated": {
          "type": "boolean"
        }
      },
      "required": [
        "items",
        "pageInfo",
        "counts",
        "truncated"
      ]
    },
    "Problem": {
      "type": "object",
      "description": "RFC 9457 problem document. Branch on `code`, never on `title` or `detail`: `code` is a stable machine-readable identifier, the human-readable fields exist for logs and may change.",
      "required": [
        "type",
        "title",
        "status",
        "code"
      ],
      "properties": {
        "type": {
          "type": "string",
          "description": "Problem type URI. Points at the documentation anchor for `code` when the code is catalogued, otherwise `about:blank`.",
          "example": "https://kelomo.fi/developers/guides/error-codes/#code-read_only_key"
        },
        "title": {
          "type": "string",
          "description": "Short human-readable phrase for the status class."
        },
        "status": {
          "type": "integer",
          "description": "HTTP status code, repeated in the body."
        },
        "detail": {
          "type": "string",
          "x-nullable": true,
          "description": "Human-readable specifics for this occurrence. Never a translated message."
        },
        "code": {
          "type": "string",
          "description": "Stable machine-readable error identifier — the field to branch on. Catalogued at /developers/guides/error-codes/.",
          "example": "read_only_key"
        },
        "requestId": {
          "type": "string",
          "description": "Identifier of this request, mirrored in the `X-Request-Id` response header. Quote it in support requests."
        }
      }
    }
  },
  "securityDefinitions": {
    "bearer": {
      "type": "apiKey",
      "in": "header",
      "name": "Authorization",
      "description": "API key sent as a bearer token: `Bearer kelomo_…`"
    }
  },
  "security": [
    {
      "bearer": []
    }
  ]
}