/* eslint-disable */
// AUTO-GENERATED FILE. DO NOT EDIT.
// Generated by ee/scripts/generate-chat-registry.mjs
import type { ChatApiRegistryEntry } from '@alga-psa/agent-tooling/registry/schema';

export const chatApiRegistry: ChatApiRegistryEntry[] = [
  {
    "id": "get-_api_auth_google_callback",
    "method": "get",
    "path": "/api/auth/google/callback",
    "displayName": "Handle Google OAuth callback",
    "summary": "Handle Google OAuth callback",
    "description": "Browser popup callback for the Gmail email-provider OAuth flow. Google redirects here with an authorization code and state. The handler decodes the state to find the tenant and email provider, exchanges the code for Google access and refresh tokens, stores them on the provider configuration, marks the provider connected, and may provision Gmail watch/Pub/Sub resources. This endpoint is public and protected by the OAuth state parameter; it always responds with text/html that posts the success or error payload to the opener window rather than returning JSON.",
    "tags": [
      "Auth"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "code",
        "in": "query",
        "required": false,
        "description": "OAuth 2.0 authorization code. Required unless the provider returned error.",
        "schema": {
          "type": "string",
          "description": "OAuth 2.0 authorization code. Required unless the provider returned error."
        }
      },
      {
        "name": "state",
        "in": "query",
        "required": false,
        "description": "Base64-encoded JSON state object generated when the OAuth flow was initiated. It carries tenant context, providerId, redirectUri, timestamp, and nonce values used to complete the callback.",
        "schema": {
          "type": "string",
          "description": "Base64-encoded JSON state object generated when the OAuth flow was initiated. It carries tenant context, providerId, redirectUri, timestamp, and nonce values used to complete the callback."
        }
      },
      {
        "name": "error",
        "in": "query",
        "required": false,
        "description": "OAuth error code returned by the provider, such as access_denied.",
        "schema": {
          "type": "string",
          "description": "OAuth error code returned by the provider, such as access_denied."
        }
      },
      {
        "name": "error_description",
        "in": "query",
        "required": false,
        "description": "Human-readable OAuth error description returned by the provider.",
        "schema": {
          "type": "string",
          "description": "Human-readable OAuth error description returned by the provider."
        }
      }
    ]
  },
  {
    "id": "get-_api_auth_microsoft_callback",
    "method": "get",
    "path": "/api/auth/microsoft/callback",
    "displayName": "Handle Microsoft OAuth callback",
    "summary": "Handle Microsoft OAuth callback",
    "description": "Browser popup callback for the Microsoft Graph email-provider OAuth flow. Microsoft redirects here with an authorization code and state. The handler decodes tenant/provider context from state, resolves the tenant Microsoft profile credentials, exchanges the code for Microsoft Graph tokens, stores them on the email provider, marks the provider connected, and best-effort registers a Graph webhook subscription. This endpoint is public and protected by the OAuth state parameter; it always responds with text/html that posts the success or error payload to the opener window rather than returning JSON.",
    "tags": [
      "Auth"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "code",
        "in": "query",
        "required": false,
        "description": "OAuth 2.0 authorization code. Required unless the provider returned error.",
        "schema": {
          "type": "string",
          "description": "OAuth 2.0 authorization code. Required unless the provider returned error."
        }
      },
      {
        "name": "state",
        "in": "query",
        "required": false,
        "description": "Base64-encoded JSON state object generated when the OAuth flow was initiated. It carries tenant context, providerId, redirectUri, timestamp, and nonce values used to complete the callback.",
        "schema": {
          "type": "string",
          "description": "Base64-encoded JSON state object generated when the OAuth flow was initiated. It carries tenant context, providerId, redirectUri, timestamp, and nonce values used to complete the callback."
        }
      },
      {
        "name": "error",
        "in": "query",
        "required": false,
        "description": "OAuth error code returned by the provider, such as access_denied.",
        "schema": {
          "type": "string",
          "description": "OAuth error code returned by the provider, such as access_denied."
        }
      },
      {
        "name": "error_description",
        "in": "query",
        "required": false,
        "description": "Human-readable OAuth error description returned by the provider.",
        "schema": {
          "type": "string",
          "description": "Human-readable OAuth error description returned by the provider."
        }
      }
    ]
  },
  {
    "id": "get-_api_auth_nextauth",
    "method": "get",
    "path": "/api/auth/{nextauth}",
    "displayName": "Handle NextAuth GET action",
    "summary": "Handle NextAuth GET action",
    "description": "Catch-all Auth.js/NextAuth GET endpoint. The nextauth path segment selects the action: csrf returns a CSRF token and sets the CSRF cookie, providers returns configured provider metadata, session returns the current session or {}, signin/signout/error/verify-request render or redirect to configured pages, and callback/{provider} handles OAuth provider redirects. This route is the authentication surface itself and does not require API-key authentication.",
    "tags": [
      "Auth"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "nextauth",
        "in": "path",
        "required": true,
        "description": "NextAuth catch-all action path. Common values include csrf, providers, signin, signout, session, error, verify-request, webauthn-options, callback/credentials, callback/google, callback/azure-ad, and callback/keycloak.",
        "schema": {
          "type": "string",
          "description": "NextAuth catch-all action path. Common values include csrf, providers, signin, signout, session, error, verify-request, webauthn-options, callback/credentials, callback/google, callback/azure-ad, and callback/keycloak."
        }
      },
      {
        "name": "callbackUrl",
        "in": "query",
        "required": false,
        "description": "Optional URL to redirect to after sign-in or sign-out flows.",
        "schema": {
          "type": "string",
          "description": "Optional URL to redirect to after sign-in or sign-out flows."
        }
      },
      {
        "name": "error",
        "in": "query",
        "required": false,
        "description": "Optional NextAuth/OAuth error code shown by sign-in or error pages.",
        "schema": {
          "type": "string",
          "description": "Optional NextAuth/OAuth error code shown by sign-in or error pages."
        }
      },
      {
        "name": "code",
        "in": "query",
        "required": false,
        "description": "OAuth authorization code for provider callback sub-routes.",
        "schema": {
          "type": "string",
          "description": "OAuth authorization code for provider callback sub-routes."
        }
      },
      {
        "name": "state",
        "in": "query",
        "required": false,
        "description": "OAuth state value for provider callback sub-routes.",
        "schema": {
          "type": "string",
          "description": "OAuth state value for provider callback sub-routes."
        }
      },
      {
        "name": "error_description",
        "in": "query",
        "required": false,
        "description": "Human-readable provider error description for OAuth callback sub-routes.",
        "schema": {
          "type": "string",
          "description": "Human-readable provider error description for OAuth callback sub-routes."
        }
      }
    ],
    "responseBodySchema": {
      "anyOf": [
        {
          "$ref": "#/components/schemas/AuthSessionAuthenticatedResponse"
        },
        {
          "$ref": "#/components/schemas/EmptyObjectResponse"
        },
        {
          "$ref": "#/components/schemas/CsrfTokenResponse"
        },
        {
          "$ref": "#/components/schemas/AuthProvidersResponse"
        },
        {
          "$ref": "#/components/schemas/OAuthCallbackHtmlResponse"
        },
        {
          "$ref": "#/components/schemas/EmptyObjectResponse"
        }
      ],
      "description": "Representative successful GET response for the NextAuth catch-all route. The exact payload depends on the nextauth action: session returns a session object or {}, csrf returns csrfToken, providers returns a provider map, and page actions return HTML or redirects."
    }
  },
  {
    "id": "post-_api_auth_nextauth",
    "method": "post",
    "path": "/api/auth/{nextauth}",
    "displayName": "Handle NextAuth POST action",
    "summary": "Handle NextAuth POST action",
    "description": "Catch-all Auth.js/NextAuth POST endpoint. The nextauth path segment selects the action: callback/credentials authenticates email and password credentials, callback/{provider} handles OAuth callback form posts, signout clears the current session, session returns or updates session data, and csrf returns a CSRF token. Mutating actions require the csrfToken body field matching the Auth.js CSRF cookie. Credential success sets the encrypted Auth.js session cookie and redirects; failures typically redirect to /auth/signin with an error code.",
    "tags": [
      "Auth"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "nextauth",
        "in": "path",
        "required": true,
        "description": "NextAuth catch-all action path. Common values include csrf, providers, signin, signout, session, error, verify-request, webauthn-options, callback/credentials, callback/google, callback/azure-ad, and callback/keycloak.",
        "schema": {
          "type": "string",
          "description": "NextAuth catch-all action path. Common values include csrf, providers, signin, signout, session, error, verify-request, webauthn-options, callback/credentials, callback/google, callback/azure-ad, and callback/keycloak."
        }
      }
    ],
    "responseBodySchema": {
      "anyOf": [
        {
          "$ref": "#/components/schemas/AuthSessionAuthenticatedResponse"
        },
        {
          "$ref": "#/components/schemas/EmptyObjectResponse"
        },
        {
          "$ref": "#/components/schemas/CsrfTokenResponse"
        },
        {
          "$ref": "#/components/schemas/EmptyObjectResponse"
        }
      ]
    }
  },
  {
    "id": "get-_api_auth_session",
    "method": "get",
    "path": "/api/auth/session",
    "displayName": "Get current Auth.js session",
    "summary": "Get current Auth.js session",
    "description": "Returns the current Auth.js/NextAuth session by reading the session cookie and running the full auth handler, including session revocation checks. Authenticated responses include the user profile, tenant context, session_id from the sessions table, and login method. If no valid session cookie is present, the route still returns HTTP 200 with an empty object.",
    "tags": [
      "Auth"
    ],
    "approvalRequired": false,
    "parameters": [],
    "responseBodySchema": {
      "anyOf": [
        {
          "$ref": "#/components/schemas/AuthSessionAuthenticatedResponse"
        },
        {
          "$ref": "#/components/schemas/EmptyObjectResponse"
        }
      ],
      "description": "Authenticated session data, or an empty object when the request has no valid session cookie."
    }
  },
  {
    "id": "post-_api_auth_validateapikey",
    "method": "post",
    "path": "/api/auth/validate-api-key",
    "displayName": "Validate API key",
    "summary": "Validate API key",
    "description": "Validates a plaintext API key supplied in the x-api-key header. The key is hashed before lookup. If the api_keys record exists, is active, has not expired, and has not exhausted its usage limit, the response returns the owning user UUID and tenant from that record. This route is the credential validation endpoint itself and does not require a separate session, tenant header, or RBAC permission.",
    "tags": [
      "Auth"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "x-api-key",
        "in": "header",
        "required": true,
        "description": "Plaintext API key to validate. The service hashes this value before looking up the api_keys record.",
        "schema": {
          "type": "string",
          "minLength": 1,
          "description": "Plaintext API key to validate. The service hashes this value before looking up the api_keys record."
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "isValid": {
          "type": "boolean",
          "enum": [
            true
          ],
          "description": "Indicates that the API key is active and valid."
        },
        "userId": {
          "type": "string",
          "format": "uuid",
          "description": "UUID of the user who owns the API key, from api_keys.user_id."
        },
        "tenant": {
          "type": "string",
          "description": "Tenant identifier scoped to this API key, from api_keys.tenant."
        }
      },
      "required": [
        "isValid",
        "userId",
        "tenant"
      ]
    }
  },
  {
    "id": "post-_api_auth_validatetoken",
    "method": "post",
    "path": "/api/auth/validate-token",
    "displayName": "Validate session token",
    "summary": "Validate session token",
    "description": "Checks whether the request carries a valid Auth.js session token, either in the session cookie or in an Authorization: Bearer header. A valid token returns the user type and tenant copied from the session JWT. No request body is read.",
    "tags": [
      "Auth"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "authorization",
        "in": "header",
        "required": false,
        "description": "Optional Bearer token fallback. The route also accepts the Auth.js session token cookie.",
        "schema": {
          "type": "string",
          "description": "Optional Bearer token fallback. The route also accepts the Auth.js session token cookie."
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "isValid": {
          "type": "boolean",
          "enum": [
            true
          ],
          "description": "Indicates that the request contains a valid Auth.js session token."
        },
        "userType": {
          "type": "string",
          "enum": [
            "internal",
            "client"
          ],
          "description": "User classification from users.user_type in the session JWT."
        },
        "tenant": {
          "type": "string",
          "description": "Tenant identifier from the session JWT."
        }
      },
      "required": [
        "isValid",
        "userType",
        "tenant"
      ]
    }
  },
  {
    "id": "get-_api_v1_admin_telemetrysettings",
    "method": "get",
    "path": "/api/v1/admin/telemetry-settings",
    "displayName": "Get telemetry settings",
    "summary": "Get telemetry settings",
    "description": "Returns tenant admin telemetry status derived from the ALGA_USAGE_STATS environment variable. The handler resolves the tenant with createTenantKnex, requires an authenticated current user, and checks the tenant-scoped users.role value for admin or owner. The route does not read or write tenant telemetry settings from the database. Because this session-authenticated route is not currently in apiKeySkipPaths, API middleware also requires an x-api-key header to be present before the handler can run.",
    "tags": [
      "Admin",
      "Telemetry"
    ],
    "approvalRequired": false,
    "parameters": [],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "usageStatsEnabled": {
          "type": "boolean",
          "description": "Whether usage statistics are enabled by the ALGA_USAGE_STATS environment variable."
        },
        "environmentVariable": {
          "type": "string",
          "enum": [
            "ALGA_USAGE_STATS"
          ],
          "description": "Environment variable controlling telemetry collection."
        },
        "currentValue": {
          "type": "string",
          "description": "Raw ALGA_USAGE_STATS environment value, or not set when absent."
        },
        "controlledBy": {
          "type": "string",
          "enum": [
            "environment"
          ],
          "description": "Telemetry is controlled by process environment, not runtime API writes."
        },
        "message": {
          "type": "string",
          "description": "Human-readable explanation of the current telemetry setting."
        }
      },
      "required": [
        "usageStatsEnabled",
        "environmentVariable",
        "currentValue",
        "controlledBy",
        "message"
      ]
    }
  },
  {
    "id": "post-_api_v1_admin_telemetrysettings",
    "method": "post",
    "path": "/api/v1/admin/telemetry-settings",
    "displayName": "Check telemetry settings update status",
    "summary": "Check telemetry settings update status",
    "description": "No-op endpoint for telemetry settings. The handler authenticates the current user, verifies the tenant-scoped users.role is admin or owner, ignores the request body, performs no database write, and returns the current ALGA_USAGE_STATS-derived status with a message explaining that telemetry cannot be changed through the API. Because this session-authenticated route is not currently in apiKeySkipPaths, API middleware also requires an x-api-key header to be present before the handler can run.",
    "tags": [
      "Admin",
      "Telemetry"
    ],
    "approvalRequired": false,
    "parameters": [],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "usageStatsEnabled": {
          "type": "boolean",
          "description": "Whether usage statistics are enabled by the ALGA_USAGE_STATS environment variable."
        },
        "controlledBy": {
          "type": "string",
          "enum": [
            "environment"
          ],
          "description": "Telemetry is controlled by process environment, not runtime API writes."
        },
        "message": {
          "type": "string",
          "description": "Explains that telemetry settings cannot be changed through this API."
        }
      },
      "required": [
        "usageStatsEnabled",
        "controlledBy",
        "message"
      ]
    }
  },
  {
    "id": "post-_api_v1_permissionchecks",
    "method": "post",
    "path": "/api/v1/permission-checks",
    "displayName": "Check user permissions",
    "summary": "Check user permissions",
    "description": "Checks one or more resource/action pairs for the requested user (or current API-key user).",
    "tags": [
      "Access Control & Users v1"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "user_id": {
          "type": "string",
          "format": "uuid"
        },
        "permissions": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "resource": {
                "type": "string"
              },
              "action": {
                "type": "string"
              }
            },
            "required": [
              "resource",
              "action"
            ]
          },
          "minItems": 1
        }
      },
      "required": [
        "permissions"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_permissions",
    "method": "get",
    "path": "/api/v1/permissions",
    "displayName": "List permissions",
    "summary": "List permissions",
    "description": "Lists permissions with optional resource/action filters.",
    "tags": [
      "Access Control & Users v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "page",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "limit",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "sort",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "order",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "asc",
            "desc"
          ]
        }
      },
      {
        "name": "resource",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "action",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "type": "array",
          "items": {
            "type": "object",
            "additionalProperties": {}
          }
        },
        "pagination": {
          "type": "object",
          "properties": {
            "page": {
              "type": "integer"
            },
            "limit": {
              "type": "integer"
            },
            "total": {
              "type": "integer"
            },
            "totalPages": {
              "type": "integer"
            },
            "hasNext": {
              "type": "boolean"
            },
            "hasPrev": {
              "type": "boolean"
            }
          },
          "required": [
            "page",
            "limit",
            "total",
            "totalPages",
            "hasNext",
            "hasPrev"
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data",
        "pagination"
      ]
    }
  },
  {
    "id": "post-_api_v1_permissions",
    "method": "post",
    "path": "/api/v1/permissions",
    "displayName": "Create permission",
    "summary": "Create permission",
    "description": "Creates one tenant-scoped permission row.",
    "tags": [
      "Access Control & Users v1"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "resource": {
          "type": "string"
        },
        "action": {
          "type": "string"
        },
        "description": {
          "type": "string"
        }
      },
      "required": [
        "resource",
        "action"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_permissions_categories",
    "method": "get",
    "path": "/api/v1/permissions/categories",
    "displayName": "List permission categories",
    "summary": "List permission categories",
    "description": "Returns grouped permissions by resource.",
    "tags": [
      "Access Control & Users v1"
    ],
    "approvalRequired": false,
    "parameters": [],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_permissions_id",
    "method": "get",
    "path": "/api/v1/permissions/{id}",
    "displayName": "Get permission",
    "summary": "Get permission",
    "description": "Loads one permission by permission UUID.",
    "tags": [
      "Access Control & Users v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Permission UUID from permissions.permission_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Permission UUID from permissions.permission_id."
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "put-_api_v1_permissions_id",
    "method": "put",
    "path": "/api/v1/permissions/{id}",
    "displayName": "Update permission",
    "summary": "Update permission",
    "description": "Updates permission metadata by permission UUID.",
    "tags": [
      "Access Control & Users v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Permission UUID from permissions.permission_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Permission UUID from permissions.permission_id."
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "resource": {
          "type": "string"
        },
        "action": {
          "type": "string"
        },
        "description": {
          "type": "string"
        }
      }
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "delete-_api_v1_permissions_id",
    "method": "delete",
    "path": "/api/v1/permissions/{id}",
    "displayName": "Delete permission",
    "summary": "Delete permission",
    "description": "Deletes a permission by permission UUID.",
    "tags": [
      "Access Control & Users v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Permission UUID from permissions.permission_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Permission UUID from permissions.permission_id."
        }
      }
    ]
  },
  {
    "id": "get-_api_v1_permissions_id_roles",
    "method": "get",
    "path": "/api/v1/permissions/{id}/roles",
    "displayName": "List roles using permission",
    "summary": "List roles using permission",
    "description": "Lists roles currently assigned the specified permission UUID.",
    "tags": [
      "Access Control & Users v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Permission UUID from permissions.permission_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Permission UUID from permissions.permission_id."
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_rbac_analytics",
    "method": "get",
    "path": "/api/v1/rbac/analytics",
    "displayName": "Get RBAC analytics",
    "summary": "Get RBAC analytics",
    "description": "Returns access-control metrics from PermissionRoleService.getAccessControlMetrics().",
    "tags": [
      "Access Control & Users v1"
    ],
    "approvalRequired": false,
    "parameters": [],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_rbac_audit",
    "method": "get",
    "path": "/api/v1/rbac/audit",
    "displayName": "Get RBAC audit log",
    "summary": "Get RBAC audit log",
    "description": "Lists RBAC audit-log entries from audit_logs (roles, permissions, role_permissions, user_roles), newest first. Supports page/limit pagination and user_id, operation, table_name, record_id, start_date, and end_date filters. Gated on role:read.",
    "tags": [
      "Access Control & Users v1"
    ],
    "approvalRequired": false,
    "parameters": [],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_roles",
    "method": "get",
    "path": "/api/v1/roles",
    "displayName": "List roles",
    "summary": "List roles",
    "description": "Lists tenant roles with role-name and permission filters.",
    "tags": [
      "Access Control & Users v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "page",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "limit",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "sort",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "order",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "asc",
            "desc"
          ]
        }
      },
      {
        "name": "role_name",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "has_permissions",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ]
        }
      },
      {
        "name": "permission_resource",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "permission_action",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "is_template",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ]
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "type": "array",
          "items": {
            "type": "object",
            "additionalProperties": {}
          }
        },
        "pagination": {
          "type": "object",
          "properties": {
            "page": {
              "type": "integer"
            },
            "limit": {
              "type": "integer"
            },
            "total": {
              "type": "integer"
            },
            "totalPages": {
              "type": "integer"
            },
            "hasNext": {
              "type": "boolean"
            },
            "hasPrev": {
              "type": "boolean"
            }
          },
          "required": [
            "page",
            "limit",
            "total",
            "totalPages",
            "hasNext",
            "hasPrev"
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data",
        "pagination"
      ]
    }
  },
  {
    "id": "post-_api_v1_roles",
    "method": "post",
    "path": "/api/v1/roles",
    "displayName": "Create role",
    "summary": "Create role",
    "description": "Creates one tenant role, optionally with initial permission assignments.",
    "tags": [
      "Access Control & Users v1"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "role_name": {
          "type": "string"
        },
        "description": {
          "type": "string"
        },
        "permissions": {
          "type": "array",
          "items": {
            "type": "string",
            "format": "uuid"
          }
        },
        "copy_from_role_id": {
          "type": "string",
          "format": "uuid"
        },
        "is_template": {
          "type": "boolean"
        }
      },
      "required": [
        "role_name"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "post-_api_v1_roles_bulk",
    "method": "post",
    "path": "/api/v1/roles/bulk",
    "displayName": "Bulk create roles",
    "summary": "Bulk create roles",
    "description": "Processes an array of role payloads and returns per-item success/error entries.",
    "tags": [
      "Access Control & Users v1"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "roles": {
          "type": "array",
          "items": {
            "$ref": "#/components/schemas/AccessCreateRoleBodyV1"
          },
          "minItems": 1
        }
      },
      "required": [
        "roles"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_roles_templates",
    "method": "get",
    "path": "/api/v1/roles/templates",
    "displayName": "List role templates",
    "summary": "List role templates",
    "description": "Returns predefined role templates for the tenant context.",
    "tags": [
      "Access Control & Users v1"
    ],
    "approvalRequired": false,
    "parameters": [],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_roles_id",
    "method": "get",
    "path": "/api/v1/roles/{id}",
    "displayName": "Get role",
    "summary": "Get role",
    "description": "Loads role by role UUID.",
    "tags": [
      "Access Control & Users v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Role UUID from roles.role_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Role UUID from roles.role_id."
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "put-_api_v1_roles_id",
    "method": "put",
    "path": "/api/v1/roles/{id}",
    "displayName": "Update role",
    "summary": "Update role",
    "description": "Updates role metadata and optional permission references.",
    "tags": [
      "Access Control & Users v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Role UUID from roles.role_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Role UUID from roles.role_id."
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "role_name": {
          "type": "string"
        },
        "description": {
          "type": "string"
        },
        "permissions": {
          "type": "array",
          "items": {
            "type": "string",
            "format": "uuid"
          }
        },
        "is_template": {
          "type": "boolean"
        }
      }
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "delete-_api_v1_roles_id",
    "method": "delete",
    "path": "/api/v1/roles/{id}",
    "displayName": "Delete role",
    "summary": "Delete role",
    "description": "Deletes role by role UUID.",
    "tags": [
      "Access Control & Users v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Role UUID from roles.role_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Role UUID from roles.role_id."
        }
      }
    ]
  },
  {
    "id": "post-_api_v1_roles_id_clone",
    "method": "post",
    "path": "/api/v1/roles/{id}/clone",
    "displayName": "Clone role",
    "summary": "Clone role",
    "description": "Clones role configuration into a new role record.",
    "tags": [
      "Access Control & Users v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Role UUID from roles.role_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Role UUID from roles.role_id."
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "new_role_name": {
          "type": "string"
        },
        "new_description": {
          "type": "string"
        },
        "copy_permissions": {
          "type": "boolean"
        },
        "copy_user_assignments": {
          "type": "boolean"
        }
      },
      "required": [
        "new_role_name"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_roles_id_permissions",
    "method": "get",
    "path": "/api/v1/roles/{id}/permissions",
    "displayName": "Get role permissions",
    "summary": "Get role permissions",
    "description": "Returns permission set currently linked to the role UUID.",
    "tags": [
      "Access Control & Users v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Role UUID from roles.role_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Role UUID from roles.role_id."
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "put-_api_v1_roles_id_permissions",
    "method": "put",
    "path": "/api/v1/roles/{id}/permissions",
    "displayName": "Replace role permissions",
    "summary": "Replace role permissions",
    "description": "Assigns provided permission UUIDs to the role and returns updated role payload.",
    "tags": [
      "Access Control & Users v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Role UUID from roles.role_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Role UUID from roles.role_id."
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "permission_ids": {
          "type": "array",
          "items": {
            "type": "string",
            "format": "uuid"
          },
          "minItems": 1
        }
      },
      "required": [
        "permission_ids"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_teams",
    "method": "get",
    "path": "/api/v1/teams",
    "displayName": "List teams",
    "summary": "List teams",
    "description": "Lists teams through ApiBaseController list behavior.",
    "tags": [
      "Access Control & Users v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "page",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "limit",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "sort",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "order",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "asc",
            "desc"
          ]
        }
      },
      {
        "name": "team_name",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "manager_id",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      },
      {
        "name": "fields",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "type": "array",
          "items": {
            "type": "object",
            "additionalProperties": {}
          }
        },
        "pagination": {
          "type": "object",
          "properties": {
            "page": {
              "type": "integer"
            },
            "limit": {
              "type": "integer"
            },
            "total": {
              "type": "integer"
            },
            "totalPages": {
              "type": "integer"
            },
            "hasNext": {
              "type": "boolean"
            },
            "hasPrev": {
              "type": "boolean"
            }
          },
          "required": [
            "page",
            "limit",
            "total",
            "totalPages",
            "hasNext",
            "hasPrev"
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data",
        "pagination"
      ]
    }
  },
  {
    "id": "post-_api_v1_teams",
    "method": "post",
    "path": "/api/v1/teams",
    "displayName": "Create team",
    "summary": "Create team",
    "description": "Creates one team with optional manager and embedded members.",
    "tags": [
      "Access Control & Users v1"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "team_name": {
          "type": "string"
        },
        "manager_id": {
          "type": "string",
          "format": "uuid"
        },
        "members": {
          "type": "array",
          "items": {
            "type": "object",
            "additionalProperties": {}
          }
        }
      },
      "required": [
        "team_name"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "put-_api_v1_teams_bulk",
    "method": "put",
    "path": "/api/v1/teams/bulk",
    "displayName": "Bulk update teams",
    "summary": "Bulk update teams",
    "description": "Updates many teams using {team_ids, updates} payload.",
    "tags": [
      "Access Control & Users v1"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "team_ids": {
          "type": "array",
          "items": {
            "type": "string",
            "format": "uuid"
          },
          "minItems": 1
        },
        "updates": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "team_ids",
        "updates"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "delete-_api_v1_teams_bulk",
    "method": "delete",
    "path": "/api/v1/teams/bulk",
    "displayName": "Bulk delete teams",
    "summary": "Bulk delete teams",
    "description": "Deletes many teams using {team_ids} payload.",
    "tags": [
      "Access Control & Users v1"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "team_ids": {
          "type": "array",
          "items": {
            "type": "string",
            "format": "uuid"
          },
          "minItems": 1
        }
      },
      "required": [
        "team_ids"
      ]
    }
  },
  {
    "id": "get-_api_v1_teams_hierarchy",
    "method": "get",
    "path": "/api/v1/teams/hierarchy",
    "displayName": "Get team hierarchy",
    "summary": "Get team hierarchy",
    "description": "Current controller parses team id from URL tail; this route passes literal \"hierarchy\" as id and can fail validation/service lookup.",
    "tags": [
      "Access Control & Users v1"
    ],
    "approvalRequired": false,
    "parameters": [],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_teams_search",
    "method": "get",
    "path": "/api/v1/teams/search",
    "displayName": "Search teams",
    "summary": "Search teams",
    "description": "Runs advanced team search filters and returns paginated data.",
    "tags": [
      "Access Control & Users v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "query",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "page",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "limit",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "manager_id",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      },
      {
        "name": "has_manager",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ]
        }
      },
      {
        "name": "sort",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "order",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "asc",
            "desc"
          ]
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "type": "array",
          "items": {
            "type": "object",
            "additionalProperties": {}
          }
        },
        "pagination": {
          "type": "object",
          "properties": {
            "page": {
              "type": "integer"
            },
            "limit": {
              "type": "integer"
            },
            "total": {
              "type": "integer"
            },
            "totalPages": {
              "type": "integer"
            },
            "hasNext": {
              "type": "boolean"
            },
            "hasPrev": {
              "type": "boolean"
            }
          },
          "required": [
            "page",
            "limit",
            "total",
            "totalPages",
            "hasNext",
            "hasPrev"
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data",
        "pagination"
      ]
    }
  },
  {
    "id": "get-_api_v1_teams_stats",
    "method": "get",
    "path": "/api/v1/teams/stats",
    "displayName": "Get team stats",
    "summary": "Get team stats",
    "description": "Returns aggregate team statistics for the tenant.",
    "tags": [
      "Access Control & Users v1"
    ],
    "approvalRequired": false,
    "parameters": [],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_teams_id",
    "method": "get",
    "path": "/api/v1/teams/{id}",
    "displayName": "Get team",
    "summary": "Get team",
    "description": "Loads team by team UUID.",
    "tags": [
      "Access Control & Users v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Team UUID from teams.team_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Team UUID from teams.team_id."
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "put-_api_v1_teams_id",
    "method": "put",
    "path": "/api/v1/teams/{id}",
    "displayName": "Update team",
    "summary": "Update team",
    "description": "Updates team metadata by team UUID.",
    "tags": [
      "Access Control & Users v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Team UUID from teams.team_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Team UUID from teams.team_id."
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "team_name": {
          "type": "string"
        },
        "manager_id": {
          "type": "string",
          "format": "uuid"
        },
        "members": {
          "type": "array",
          "items": {
            "type": "object",
            "additionalProperties": {}
          }
        }
      }
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "delete-_api_v1_teams_id",
    "method": "delete",
    "path": "/api/v1/teams/{id}",
    "displayName": "Delete team",
    "summary": "Delete team",
    "description": "Deletes a team by team UUID.",
    "tags": [
      "Access Control & Users v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Team UUID from teams.team_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Team UUID from teams.team_id."
        }
      }
    ]
  },
  {
    "id": "get-_api_v1_teams_id_analytics",
    "method": "get",
    "path": "/api/v1/teams/{id}/analytics",
    "displayName": "Get team analytics",
    "summary": "Get team analytics",
    "description": "Returns team analytics for the target team UUID.",
    "tags": [
      "Access Control & Users v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Team UUID from teams.team_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Team UUID from teams.team_id."
        }
      },
      {
        "name": "start_date",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "end_date",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "include_metrics",
        "in": "query",
        "required": false,
        "description": "Controller query parser provides strings; schema expects metric array.",
        "schema": {
          "type": "string",
          "description": "Controller query parser provides strings; schema expects metric array."
        }
      },
      {
        "name": "granularity",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "daily",
            "weekly",
            "monthly"
          ]
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "post-_api_v1_teams_id_hierarchy",
    "method": "post",
    "path": "/api/v1/teams/{id}/hierarchy",
    "displayName": "Attach team to parent hierarchy",
    "summary": "Attach team to parent hierarchy",
    "description": "Creates parent relationship for team UUID using parent_team_id payload.",
    "tags": [
      "Access Control & Users v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Team UUID from teams.team_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Team UUID from teams.team_id."
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "parent_team_id": {
          "type": [
            "string",
            "null"
          ],
          "format": "uuid"
        }
      }
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "delete-_api_v1_teams_id_hierarchy",
    "method": "delete",
    "path": "/api/v1/teams/{id}/hierarchy",
    "displayName": "Detach team from hierarchy",
    "summary": "Detach team from hierarchy",
    "description": "Removes hierarchy relationship for team UUID.",
    "tags": [
      "Access Control & Users v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Team UUID from teams.team_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Team UUID from teams.team_id."
        }
      }
    ]
  },
  {
    "id": "put-_api_v1_teams_id_manager",
    "method": "put",
    "path": "/api/v1/teams/{id}/manager",
    "displayName": "Assign team manager",
    "summary": "Assign team manager",
    "description": "Assigns manager_id to team UUID.",
    "tags": [
      "Access Control & Users v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Team UUID from teams.team_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Team UUID from teams.team_id."
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "manager_id": {
          "type": "string",
          "format": "uuid"
        }
      },
      "required": [
        "manager_id"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_teams_id_members",
    "method": "get",
    "path": "/api/v1/teams/{id}/members",
    "displayName": "List team members",
    "summary": "List team members",
    "description": "Returns members for team UUID.",
    "tags": [
      "Access Control & Users v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Team UUID from teams.team_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Team UUID from teams.team_id."
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "post-_api_v1_teams_id_members",
    "method": "post",
    "path": "/api/v1/teams/{id}/members",
    "displayName": "Add team member",
    "summary": "Add team member",
    "description": "Adds one user to team UUID.",
    "tags": [
      "Access Control & Users v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Team UUID from teams.team_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Team UUID from teams.team_id."
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "user_id": {
          "type": "string",
          "format": "uuid"
        }
      },
      "required": [
        "user_id"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "post-_api_v1_teams_id_members_bulk",
    "method": "post",
    "path": "/api/v1/teams/{id}/members/bulk",
    "displayName": "Bulk add team members",
    "summary": "Bulk add team members",
    "description": "Adds many users to team UUID.",
    "tags": [
      "Access Control & Users v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Team UUID from teams.team_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Team UUID from teams.team_id."
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "user_ids": {
          "type": "array",
          "items": {
            "type": "string",
            "format": "uuid"
          },
          "minItems": 1
        }
      },
      "required": [
        "user_ids"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "delete-_api_v1_teams_id_members_userid",
    "method": "delete",
    "path": "/api/v1/teams/{id}/members/{userId}",
    "displayName": "Remove team member",
    "summary": "Remove team member",
    "description": "Removes one user from team UUID.",
    "tags": [
      "Access Control & Users v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Team UUID from teams.team_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Team UUID from teams.team_id."
        }
      },
      {
        "name": "userId",
        "in": "path",
        "required": true,
        "description": "User UUID from users.user_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "User UUID from users.user_id."
        }
      }
    ]
  },
  {
    "id": "get-_api_v1_teams_id_permissions",
    "method": "get",
    "path": "/api/v1/teams/{id}/permissions",
    "displayName": "List team permissions",
    "summary": "List team permissions",
    "description": "Lists ACL records attached to team UUID.",
    "tags": [
      "Access Control & Users v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Team UUID from teams.team_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Team UUID from teams.team_id."
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "post-_api_v1_teams_id_permissions",
    "method": "post",
    "path": "/api/v1/teams/{id}/permissions",
    "displayName": "Grant team permission",
    "summary": "Grant team permission",
    "description": "Creates one permission grant for team UUID.",
    "tags": [
      "Access Control & Users v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Team UUID from teams.team_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Team UUID from teams.team_id."
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "resource": {
          "type": "string",
          "description": "Controller also accepts permission alias field."
        },
        "permission": {
          "type": "string"
        },
        "action": {
          "type": "string"
        },
        "expires_at": {
          "type": "string"
        }
      }
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "delete-_api_v1_teams_id_permissions_permissionid",
    "method": "delete",
    "path": "/api/v1/teams/{id}/permissions/{permissionId}",
    "displayName": "Revoke team permission",
    "summary": "Revoke team permission",
    "description": "Revokes permission grant. Controller extracts permission id from path and does not use team id during revocation call.",
    "tags": [
      "Access Control & Users v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Team UUID from teams.team_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Team UUID from teams.team_id."
        }
      },
      {
        "name": "permissionId",
        "in": "path",
        "required": true,
        "description": "Permission UUID from permissions.permission_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Permission UUID from permissions.permission_id."
        }
      }
    ]
  },
  {
    "id": "get-_api_v1_teams_id_projects",
    "method": "get",
    "path": "/api/v1/teams/{id}/projects",
    "displayName": "List team projects",
    "summary": "List team projects",
    "description": "Lists projects associated with team UUID.",
    "tags": [
      "Access Control & Users v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Team UUID from teams.team_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Team UUID from teams.team_id."
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_userroles",
    "method": "get",
    "path": "/api/v1/user-roles",
    "displayName": "List users with roles",
    "summary": "List users with roles",
    "description": "Returns paginated users plus their role assignments.",
    "tags": [
      "Access Control & Users v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "page",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "limit",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "search",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "is_inactive",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ]
        }
      },
      {
        "name": "sort",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "order",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "asc",
            "desc"
          ]
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "type": "array",
          "items": {
            "type": "object",
            "additionalProperties": {}
          }
        },
        "pagination": {
          "type": "object",
          "properties": {
            "page": {
              "type": "integer"
            },
            "limit": {
              "type": "integer"
            },
            "total": {
              "type": "integer"
            },
            "totalPages": {
              "type": "integer"
            },
            "hasNext": {
              "type": "boolean"
            },
            "hasPrev": {
              "type": "boolean"
            }
          },
          "required": [
            "page",
            "limit",
            "total",
            "totalPages",
            "hasNext",
            "hasPrev"
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data",
        "pagination"
      ]
    }
  },
  {
    "id": "get-_api_v1_users",
    "method": "get",
    "path": "/api/v1/users",
    "displayName": "List Users",
    "summary": "Fetch users/technicians",
    "description": "Lists tenant users. Use this to discover the user_id for the assignee field on a ticket.",
    "tags": [
      "Access Control & Users v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "search_term",
        "in": "query",
        "required": false,
        "description": "Match against name or email.",
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "team_id",
        "in": "query",
        "required": false,
        "description": "Filter users belonging to a specific team.",
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      },
      {
        "name": "limit",
        "in": "query",
        "required": false,
        "description": "Number of users per page (default 25, max 100).",
        "schema": {
          "type": "integer",
          "minimum": 1,
          "maximum": 100
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "type": "array",
          "items": {
            "type": "object",
            "additionalProperties": {}
          }
        },
        "pagination": {
          "type": "object",
          "properties": {
            "page": {
              "type": "integer"
            },
            "limit": {
              "type": "integer"
            },
            "total": {
              "type": "integer"
            },
            "totalPages": {
              "type": "integer"
            },
            "hasNext": {
              "type": "boolean"
            },
            "hasPrev": {
              "type": "boolean"
            }
          },
          "required": [
            "page",
            "limit",
            "total",
            "totalPages",
            "hasNext",
            "hasPrev"
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data",
        "pagination"
      ]
    },
    "examples": [
      {
        "name": "Find a technician",
        "request": {
          "query": {
            "search_term": "Samantha",
            "limit": 5
          }
        },
        "notes": "Use the result set to map the human name back to a user_id for the assigned_to field."
      }
    ]
  },
  {
    "id": "post-_api_v1_users",
    "method": "post",
    "path": "/api/v1/users",
    "displayName": "Create user",
    "summary": "Create user",
    "description": "Creates one user using createUserSchema validation.",
    "tags": [
      "Access Control & Users v1"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "username": {
          "type": "string",
          "minLength": 3
        },
        "email": {
          "type": "string",
          "format": "email"
        },
        "password": {
          "type": "string",
          "minLength": 8
        },
        "first_name": {
          "type": "string"
        },
        "last_name": {
          "type": "string"
        },
        "phone": {
          "type": "string"
        },
        "timezone": {
          "type": "string"
        },
        "user_type": {
          "type": "string",
          "enum": [
            "internal",
            "client",
            "admin",
            "contractor"
          ]
        },
        "contact_id": {
          "type": "string",
          "format": "uuid"
        },
        "two_factor_enabled": {
          "type": "boolean"
        },
        "is_google_user": {
          "type": "boolean"
        },
        "is_inactive": {
          "type": "boolean"
        },
        "role_ids": {
          "type": "array",
          "items": {
            "type": "string",
            "format": "uuid"
          }
        }
      },
      "required": [
        "username",
        "email",
        "password"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_users_activity",
    "method": "get",
    "path": "/api/v1/users/activity",
    "displayName": "List global user activity",
    "summary": "List global user activity",
    "description": "Returns paginated activity feed across users.",
    "tags": [
      "Access Control & Users v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "page",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "limit",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "from_date",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "to_date",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "activity_type",
        "in": "query",
        "required": false,
        "description": "Controller converts single query value to one-element array for service filter.",
        "schema": {
          "type": "string",
          "description": "Controller converts single query value to one-element array for service filter."
        }
      },
      {
        "name": "ip_address",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "type": "array",
          "items": {
            "type": "object",
            "additionalProperties": {}
          }
        },
        "pagination": {
          "type": "object",
          "properties": {
            "page": {
              "type": "integer"
            },
            "limit": {
              "type": "integer"
            },
            "total": {
              "type": "integer"
            },
            "totalPages": {
              "type": "integer"
            },
            "hasNext": {
              "type": "boolean"
            },
            "hasPrev": {
              "type": "boolean"
            }
          },
          "required": [
            "page",
            "limit",
            "total",
            "totalPages",
            "hasNext",
            "hasPrev"
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data",
        "pagination"
      ]
    }
  },
  {
    "id": "post-_api_v1_users_bulk_create",
    "method": "post",
    "path": "/api/v1/users/bulk/create",
    "displayName": "Bulk create users (route currently mapped to single create)",
    "summary": "Bulk create users (route currently mapped to single create)",
    "description": "Route currently delegates to ApiUserController.create(), so behavior is single-user create schema rather than bulk payload handling.",
    "tags": [
      "Access Control & Users v1"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "username": {
          "type": "string",
          "minLength": 3
        },
        "email": {
          "type": "string",
          "format": "email"
        },
        "password": {
          "type": "string",
          "minLength": 8
        },
        "first_name": {
          "type": "string"
        },
        "last_name": {
          "type": "string"
        },
        "phone": {
          "type": "string"
        },
        "timezone": {
          "type": "string"
        },
        "user_type": {
          "type": "string",
          "enum": [
            "internal",
            "client",
            "admin",
            "contractor"
          ]
        },
        "contact_id": {
          "type": "string",
          "format": "uuid"
        },
        "two_factor_enabled": {
          "type": "boolean"
        },
        "is_google_user": {
          "type": "boolean"
        },
        "is_inactive": {
          "type": "boolean"
        },
        "role_ids": {
          "type": "array",
          "items": {
            "type": "string",
            "format": "uuid"
          }
        }
      },
      "required": [
        "username",
        "email",
        "password"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "put-_api_v1_users_bulk_deactivate",
    "method": "put",
    "path": "/api/v1/users/bulk/deactivate",
    "displayName": "Bulk deactivate users (route currently mapped to update-by-id)",
    "summary": "Bulk deactivate users (route currently mapped to update-by-id)",
    "description": "Route currently delegates to ApiUserController.update(); id extraction reads \"bulk\" from path and fails UUID validation.",
    "tags": [
      "Access Control & Users v1"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "username": {
          "type": "string",
          "minLength": 3
        },
        "email": {
          "type": "string",
          "format": "email"
        },
        "first_name": {
          "type": "string"
        },
        "last_name": {
          "type": "string"
        },
        "phone": {
          "type": "string"
        },
        "timezone": {
          "type": "string"
        },
        "user_type": {
          "type": "string",
          "enum": [
            "internal",
            "client",
            "admin",
            "contractor"
          ]
        },
        "contact_id": {
          "type": "string",
          "format": "uuid"
        },
        "two_factor_enabled": {
          "type": "boolean"
        },
        "is_google_user": {
          "type": "boolean"
        },
        "is_inactive": {
          "type": "boolean"
        },
        "role_ids": {
          "type": "array",
          "items": {
            "type": "string",
            "format": "uuid"
          }
        }
      }
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_users_search",
    "method": "get",
    "path": "/api/v1/users/search",
    "displayName": "Search users",
    "summary": "Search users",
    "description": "Searches users with optional NM-store system context support and query validation.",
    "tags": [
      "Access Control & Users v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "query",
        "in": "query",
        "required": true,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "fields",
        "in": "query",
        "required": false,
        "description": "Controller query parser sends strings; schema expects an array of field names.",
        "schema": {
          "type": "string",
          "description": "Controller query parser sends strings; schema expects an array of field names."
        }
      },
      {
        "name": "user_type",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "internal",
            "client",
            "admin",
            "contractor"
          ]
        }
      },
      {
        "name": "role_id",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      },
      {
        "name": "team_id",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      },
      {
        "name": "include_inactive",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ]
        }
      },
      {
        "name": "limit",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "type": "array",
          "items": {
            "type": "object",
            "additionalProperties": {}
          }
        },
        "pagination": {
          "type": "object",
          "properties": {
            "page": {
              "type": "integer"
            },
            "limit": {
              "type": "integer"
            },
            "total": {
              "type": "integer"
            },
            "totalPages": {
              "type": "integer"
            },
            "hasNext": {
              "type": "boolean"
            },
            "hasPrev": {
              "type": "boolean"
            }
          },
          "required": [
            "page",
            "limit",
            "total",
            "totalPages",
            "hasNext",
            "hasPrev"
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data",
        "pagination"
      ]
    }
  },
  {
    "id": "get-_api_v1_users_stats",
    "method": "get",
    "path": "/api/v1/users/stats",
    "displayName": "Get user stats",
    "summary": "Get user stats",
    "description": "Returns aggregate user statistics.",
    "tags": [
      "Access Control & Users v1"
    ],
    "approvalRequired": false,
    "parameters": [],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_users_id",
    "method": "get",
    "path": "/api/v1/users/{id}",
    "displayName": "Get user",
    "summary": "Get user",
    "description": "Loads user by user UUID.",
    "tags": [
      "Access Control & Users v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "User UUID from users.user_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "User UUID from users.user_id."
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "put-_api_v1_users_id",
    "method": "put",
    "path": "/api/v1/users/{id}",
    "displayName": "Update user",
    "summary": "Update user",
    "description": "Updates user by user UUID.",
    "tags": [
      "Access Control & Users v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "User UUID from users.user_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "User UUID from users.user_id."
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "username": {
          "type": "string",
          "minLength": 3
        },
        "email": {
          "type": "string",
          "format": "email"
        },
        "first_name": {
          "type": "string"
        },
        "last_name": {
          "type": "string"
        },
        "phone": {
          "type": "string"
        },
        "timezone": {
          "type": "string"
        },
        "user_type": {
          "type": "string",
          "enum": [
            "internal",
            "client",
            "admin",
            "contractor"
          ]
        },
        "contact_id": {
          "type": "string",
          "format": "uuid"
        },
        "two_factor_enabled": {
          "type": "boolean"
        },
        "is_google_user": {
          "type": "boolean"
        },
        "is_inactive": {
          "type": "boolean"
        },
        "role_ids": {
          "type": "array",
          "items": {
            "type": "string",
            "format": "uuid"
          }
        }
      }
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "delete-_api_v1_users_id",
    "method": "delete",
    "path": "/api/v1/users/{id}",
    "displayName": "Delete user",
    "summary": "Delete user",
    "description": "Deletes user by user UUID.",
    "tags": [
      "Access Control & Users v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "User UUID from users.user_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "User UUID from users.user_id."
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "delete-_api_v1_users_id_2fa_disable",
    "method": "delete",
    "path": "/api/v1/users/{id}/2fa/disable",
    "displayName": "Disable user 2FA",
    "summary": "Disable user 2FA",
    "description": "Disables two-factor authentication for target user UUID.",
    "tags": [
      "Access Control & Users v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "User UUID from users.user_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "User UUID from users.user_id."
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "post-_api_v1_users_id_2fa_enable",
    "method": "post",
    "path": "/api/v1/users/{id}/2fa/enable",
    "displayName": "Enable user 2FA",
    "summary": "Enable user 2FA",
    "description": "Enables two-factor authentication using secret/token payload.",
    "tags": [
      "Access Control & Users v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "User UUID from users.user_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "User UUID from users.user_id."
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "secret": {
          "type": "string"
        },
        "token": {
          "type": "string"
        }
      },
      "required": [
        "secret",
        "token"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_users_id_activity",
    "method": "get",
    "path": "/api/v1/users/{id}/activity",
    "displayName": "Get user activity",
    "summary": "Get user activity",
    "description": "Returns activity log for one user UUID.",
    "tags": [
      "Access Control & Users v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "User UUID from users.user_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "User UUID from users.user_id."
        }
      },
      {
        "name": "page",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "limit",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "from_date",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "to_date",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "activity_type",
        "in": "query",
        "required": false,
        "description": "Controller converts single query value to one-element array for service filter.",
        "schema": {
          "type": "string",
          "description": "Controller converts single query value to one-element array for service filter."
        }
      },
      {
        "name": "ip_address",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "post-_api_v1_users_id_avatar",
    "method": "post",
    "path": "/api/v1/users/{id}/avatar",
    "displayName": "Upload user avatar",
    "summary": "Upload user avatar",
    "description": "Uploads avatar file from multipart form field avatar.",
    "tags": [
      "Access Control & Users v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "User UUID from users.user_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "User UUID from users.user_id."
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "avatar": {
          "type": "string",
          "description": "Multipart file field name expected by controller: avatar."
        }
      },
      "required": [
        "avatar"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "delete-_api_v1_users_id_avatar",
    "method": "delete",
    "path": "/api/v1/users/{id}/avatar",
    "displayName": "Delete user avatar",
    "summary": "Delete user avatar",
    "description": "Deletes avatar for target user UUID.",
    "tags": [
      "Access Control & Users v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "User UUID from users.user_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "User UUID from users.user_id."
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "put-_api_v1_users_id_password",
    "method": "put",
    "path": "/api/v1/users/{id}/password",
    "displayName": "Change user password",
    "summary": "Change user password",
    "description": "Changes password for self or another user with user:update permission.",
    "tags": [
      "Access Control & Users v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "User UUID from users.user_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "User UUID from users.user_id."
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "current_password": {
          "type": "string"
        },
        "new_password": {
          "type": "string",
          "minLength": 8
        },
        "confirm_password": {
          "type": "string"
        }
      },
      "required": [
        "new_password",
        "confirm_password"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_users_id_permissions",
    "method": "get",
    "path": "/api/v1/users/{id}/permissions",
    "displayName": "Get user effective permissions",
    "summary": "Get user effective permissions",
    "description": "Returns explicit/effective permissions and roles for user UUID.",
    "tags": [
      "Access Control & Users v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "User UUID from users.user_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "User UUID from users.user_id."
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_users_id_preferences",
    "method": "get",
    "path": "/api/v1/users/{id}/preferences",
    "displayName": "Get user preferences",
    "summary": "Get user preferences",
    "description": "Returns user preference map for user UUID.",
    "tags": [
      "Access Control & Users v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "User UUID from users.user_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "User UUID from users.user_id."
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "put-_api_v1_users_id_preferences",
    "method": "put",
    "path": "/api/v1/users/{id}/preferences",
    "displayName": "Update user preferences",
    "summary": "Update user preferences",
    "description": "Updates user preference payload without route-level schema validation.",
    "tags": [
      "Access Control & Users v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "User UUID from users.user_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "User UUID from users.user_id."
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "additionalProperties": {},
      "description": "Controller forwards request body directly to UserService.updateUserPreferences()."
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_users_id_roles",
    "method": "get",
    "path": "/api/v1/users/{id}/roles",
    "displayName": "List user roles",
    "summary": "List user roles",
    "description": "Lists roles assigned to user UUID.",
    "tags": [
      "Access Control & Users v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "User UUID from users.user_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "User UUID from users.user_id."
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "post-_api_v1_users_id_roles",
    "method": "post",
    "path": "/api/v1/users/{id}/roles",
    "displayName": "Assign user roles",
    "summary": "Assign user roles",
    "description": "Assigns provided role_ids to user UUID.",
    "tags": [
      "Access Control & Users v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "User UUID from users.user_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "User UUID from users.user_id."
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "role_ids": {
          "type": "array",
          "items": {
            "type": "string",
            "format": "uuid"
          },
          "minItems": 1
        }
      },
      "required": [
        "role_ids"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "put-_api_v1_users_id_roles",
    "method": "put",
    "path": "/api/v1/users/{id}/roles",
    "displayName": "Replace user roles",
    "summary": "Replace user roles",
    "description": "Replaces all role links for user UUID using transaction over user_roles.",
    "tags": [
      "Access Control & Users v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "User UUID from users.user_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "User UUID from users.user_id."
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "role_ids": {
          "type": "array",
          "items": {
            "type": "string",
            "format": "uuid"
          },
          "minItems": 1
        }
      },
      "required": [
        "role_ids"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "delete-_api_v1_users_id_roles",
    "method": "delete",
    "path": "/api/v1/users/{id}/roles",
    "displayName": "Remove user roles",
    "summary": "Remove user roles",
    "description": "Removes provided role_ids from user UUID.",
    "tags": [
      "Access Control & Users v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "User UUID from users.user_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "User UUID from users.user_id."
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "role_ids": {
          "type": "array",
          "items": {
            "type": "string",
            "format": "uuid"
          },
          "minItems": 1
        }
      },
      "required": [
        "role_ids"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_users_id_teams",
    "method": "get",
    "path": "/api/v1/users/{id}/teams",
    "displayName": "List user teams",
    "summary": "List user teams",
    "description": "Returns teams associated with user UUID.",
    "tags": [
      "Access Control & Users v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "User UUID from users.user_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "User UUID from users.user_id."
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "post-_api_v1_users_id_teams",
    "method": "post",
    "path": "/api/v1/users/{id}/teams",
    "displayName": "Add user to team (route currently mapped to user create)",
    "summary": "Add user to team (route currently mapped to user create)",
    "description": "Route currently delegates to ApiUserController.create(); payload is interpreted as create-user body rather than team membership.",
    "tags": [
      "Access Control & Users v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "User UUID from users.user_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "User UUID from users.user_id."
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "username": {
          "type": "string",
          "minLength": 3
        },
        "email": {
          "type": "string",
          "format": "email"
        },
        "password": {
          "type": "string",
          "minLength": 8
        },
        "first_name": {
          "type": "string"
        },
        "last_name": {
          "type": "string"
        },
        "phone": {
          "type": "string"
        },
        "timezone": {
          "type": "string"
        },
        "user_type": {
          "type": "string",
          "enum": [
            "internal",
            "client",
            "admin",
            "contractor"
          ]
        },
        "contact_id": {
          "type": "string",
          "format": "uuid"
        },
        "two_factor_enabled": {
          "type": "boolean"
        },
        "is_google_user": {
          "type": "boolean"
        },
        "is_inactive": {
          "type": "boolean"
        },
        "role_ids": {
          "type": "array",
          "items": {
            "type": "string",
            "format": "uuid"
          }
        }
      },
      "required": [
        "username",
        "email",
        "password"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "delete-_api_v1_users_id_teams_teamid",
    "method": "delete",
    "path": "/api/v1/users/{id}/teams/{teamId}",
    "displayName": "Remove user from team (route currently mapped to user delete)",
    "summary": "Remove user from team (route currently mapped to user delete)",
    "description": "Route currently delegates to ApiUserController.delete(); extracted id is user UUID and teamId path segment is ignored.",
    "tags": [
      "Access Control & Users v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "User UUID from users.user_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "User UUID from users.user_id."
        }
      },
      {
        "name": "teamId",
        "in": "path",
        "required": true,
        "description": "Team UUID from teams.team_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Team UUID from teams.team_id."
        }
      }
    ]
  },
  {
    "id": "get-_api_v1_assets",
    "method": "get",
    "path": "/api/v1/assets",
    "displayName": "List assets",
    "summary": "List assets",
    "description": "Lists assets for the authenticated tenant with pagination, sorting, and asset filters. The controller validates query parameters with assetListQuerySchema, queries assets filtered by assets.tenant, joins clients for client_name, computes warranty_status, and adds HATEOAS links from asset_id. The route is authenticated and tenant-scoped via withApiKeyRouteAuth (req.context is populated before the handler runs).",
    "tags": [
      "Assets"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "page",
        "in": "query",
        "required": false,
        "description": "Page number as a query string. Defaults to 1 after validation.",
        "schema": {
          "type": "string",
          "description": "Page number as a query string. Defaults to 1 after validation."
        }
      },
      {
        "name": "limit",
        "in": "query",
        "required": false,
        "description": "Page size as a query string. Must parse to 1 through 100; defaults to 25.",
        "schema": {
          "type": "string",
          "description": "Page size as a query string. Must parse to 1 through 100; defaults to 25."
        }
      },
      {
        "name": "sort",
        "in": "query",
        "required": false,
        "description": "Sort column. Defaults to created_at.",
        "schema": {
          "type": "string",
          "description": "Sort column. Defaults to created_at."
        }
      },
      {
        "name": "order",
        "in": "query",
        "required": false,
        "description": "Sort direction. Defaults to desc.",
        "schema": {
          "type": "string",
          "enum": [
            "asc",
            "desc"
          ],
          "description": "Sort direction. Defaults to desc."
        }
      },
      {
        "name": "search",
        "in": "query",
        "required": false,
        "description": "General search filter accepted by the shared filter schema. The current AssetService.list implementation does not apply this filter.",
        "schema": {
          "type": "string",
          "description": "General search filter accepted by the shared filter schema. The current AssetService.list implementation does not apply this filter."
        }
      },
      {
        "name": "created_from",
        "in": "query",
        "required": false,
        "description": "Accepted by validation, but not currently applied by AssetService.list.",
        "schema": {
          "type": "string",
          "format": "date-time",
          "description": "Accepted by validation, but not currently applied by AssetService.list."
        }
      },
      {
        "name": "created_to",
        "in": "query",
        "required": false,
        "description": "Accepted by validation, but not currently applied by AssetService.list.",
        "schema": {
          "type": "string",
          "format": "date-time",
          "description": "Accepted by validation, but not currently applied by AssetService.list."
        }
      },
      {
        "name": "updated_from",
        "in": "query",
        "required": false,
        "description": "Accepted by validation, but not currently applied by AssetService.list.",
        "schema": {
          "type": "string",
          "format": "date-time",
          "description": "Accepted by validation, but not currently applied by AssetService.list."
        }
      },
      {
        "name": "updated_to",
        "in": "query",
        "required": false,
        "description": "Accepted by validation, but not currently applied by AssetService.list.",
        "schema": {
          "type": "string",
          "format": "date-time",
          "description": "Accepted by validation, but not currently applied by AssetService.list."
        }
      },
      {
        "name": "is_active",
        "in": "query",
        "required": false,
        "description": "Accepted by validation, but not currently applied by AssetService.list.",
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ],
          "description": "Accepted by validation, but not currently applied by AssetService.list."
        }
      },
      {
        "name": "asset_tag",
        "in": "query",
        "required": false,
        "description": "Partial asset tag match using ILIKE.",
        "schema": {
          "type": "string",
          "description": "Partial asset tag match using ILIKE."
        }
      },
      {
        "name": "name",
        "in": "query",
        "required": false,
        "description": "Partial asset name match using ILIKE.",
        "schema": {
          "type": "string",
          "description": "Partial asset name match using ILIKE."
        }
      },
      {
        "name": "client_id",
        "in": "query",
        "required": false,
        "description": "Client UUID from clients.client_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Client UUID from clients.client_id."
        }
      },
      {
        "name": "location_id",
        "in": "query",
        "required": false,
        "description": "Client location UUID from client_locations.location_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Client location UUID from client_locations.location_id."
        }
      },
      {
        "name": "asset_type",
        "in": "query",
        "required": false,
        "description": "Asset type stored in assets.asset_type.",
        "schema": {
          "type": "string",
          "enum": [
            "workstation",
            "network_device",
            "server",
            "mobile_device",
            "printer",
            "unknown"
          ],
          "description": "Asset type stored in assets.asset_type."
        }
      },
      {
        "name": "status",
        "in": "query",
        "required": false,
        "description": "Exact asset status match.",
        "schema": {
          "type": "string",
          "description": "Exact asset status match."
        }
      },
      {
        "name": "location",
        "in": "query",
        "required": false,
        "description": "Partial location match using ILIKE.",
        "schema": {
          "type": "string",
          "description": "Partial location match using ILIKE."
        }
      },
      {
        "name": "client_name",
        "in": "query",
        "required": false,
        "description": "Partial client name match; joins clients on client_id and tenant.",
        "schema": {
          "type": "string",
          "description": "Partial client name match; joins clients on client_id and tenant."
        }
      },
      {
        "name": "has_warranty",
        "in": "query",
        "required": false,
        "description": "true requires warranty_end_date to be non-null; false requires it to be null.",
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ],
          "description": "true requires warranty_end_date to be non-null; false requires it to be null."
        }
      },
      {
        "name": "warranty_expired",
        "in": "query",
        "required": false,
        "description": "true filters warranty_end_date before now; false filters future warranty dates or no warranty.",
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ],
          "description": "true filters warranty_end_date before now; false filters future warranty dates or no warranty."
        }
      },
      {
        "name": "maintenance_due",
        "in": "query",
        "required": false,
        "description": "Accepted by validation, but not currently applied by AssetService.list.",
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ],
          "description": "Accepted by validation, but not currently applied by AssetService.list."
        }
      },
      {
        "name": "purchase_date_from",
        "in": "query",
        "required": false,
        "description": "Filter purchase_date greater than or equal to this timestamp.",
        "schema": {
          "type": "string",
          "format": "date-time",
          "description": "Filter purchase_date greater than or equal to this timestamp."
        }
      },
      {
        "name": "purchase_date_to",
        "in": "query",
        "required": false,
        "description": "Filter purchase_date less than or equal to this timestamp.",
        "schema": {
          "type": "string",
          "format": "date-time",
          "description": "Filter purchase_date less than or equal to this timestamp."
        }
      },
      {
        "name": "warranty_end_from",
        "in": "query",
        "required": false,
        "description": "Filter warranty_end_date greater than or equal to this timestamp.",
        "schema": {
          "type": "string",
          "format": "date-time",
          "description": "Filter warranty_end_date greater than or equal to this timestamp."
        }
      },
      {
        "name": "warranty_end_to",
        "in": "query",
        "required": false,
        "description": "Filter warranty_end_date less than or equal to this timestamp.",
        "schema": {
          "type": "string",
          "format": "date-time",
          "description": "Filter warranty_end_date less than or equal to this timestamp."
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "success": {
          "type": "boolean",
          "enum": [
            true
          ],
          "description": "Indicates the controller returned a successful response envelope."
        },
        "data": {
          "allOf": [
            {
              "$ref": "#/components/schemas/AssetListPayload"
            },
            {
              "description": "Nested payload passed to createApiResponse by ApiAssetController.list."
            }
          ]
        },
        "meta": {
          "$ref": "#/components/schemas/ApiResponseMeta"
        }
      },
      "required": [
        "success",
        "data",
        "meta"
      ]
    }
  },
  {
    "id": "post-_api_v1_assets",
    "method": "post",
    "path": "/api/v1/assets",
    "displayName": "Create asset",
    "summary": "Create asset",
    "description": "Creates an asset for the authenticated tenant. The request body is validated with createAssetWithExtensionSchema; client_id, asset_type, asset_tag, name, and status are required. AssetService.create writes assets.tenant from the request context, inserts the asset, optionally upserts asset-type-specific extension_data, publishes an ASSET_CREATED event, and returns getWithDetails with HATEOAS links.",
    "tags": [
      "Assets"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "client_id": {
          "type": "string",
          "format": "uuid",
          "description": "Client UUID from clients.client_id. Required."
        },
        "asset_type": {
          "type": "string",
          "enum": [
            "workstation",
            "network_device",
            "server",
            "mobile_device",
            "printer",
            "unknown"
          ],
          "description": "Asset type. Determines the optional extension data table."
        },
        "asset_tag": {
          "type": "string",
          "minLength": 1,
          "maxLength": 255,
          "description": "Required tenant-specific asset tag."
        },
        "name": {
          "type": "string",
          "minLength": 1,
          "maxLength": 255,
          "description": "Required asset name."
        },
        "status": {
          "type": "string",
          "minLength": 1,
          "description": "Required asset status."
        },
        "location_id": {
          "type": [
            "string",
            "null"
          ],
          "format": "uuid",
          "description": "Optional client_locations.location_id link. Validated to belong to client_id."
        },
        "location": {
          "type": "string",
          "description": "Optional free-text asset location."
        },
        "serial_number": {
          "type": "string",
          "description": "Optional serial number."
        },
        "purchase_date": {
          "type": "string",
          "format": "date-time",
          "description": "Optional purchase date/time."
        },
        "warranty_end_date": {
          "type": "string",
          "format": "date-time",
          "description": "Optional warranty end date/time."
        },
        "extension_data": {
          "$ref": "#/components/schemas/AssetExtensionData"
        }
      },
      "required": [
        "client_id",
        "asset_type",
        "asset_tag",
        "name",
        "status"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "success": {
          "type": "boolean",
          "enum": [
            true
          ]
        },
        "data": {
          "allOf": [
            {
              "$ref": "#/components/schemas/AssetResourcePayload"
            },
            {
              "description": "Nested payload passed to createApiResponse by ApiAssetController.create."
            }
          ]
        },
        "meta": {
          "$ref": "#/components/schemas/ApiResponseMeta"
        }
      },
      "required": [
        "success",
        "data",
        "meta"
      ]
    }
  },
  {
    "id": "put-_api_v1_assets_bulkstatus",
    "method": "put",
    "path": "/api/v1/assets/bulk-status",
    "displayName": "Bulk update asset status",
    "summary": "Bulk update asset status",
    "description": "Updates the status field for up to 50 assets in the authenticated tenant. The controller validates asset_ids and status with bulkAssetStatusSchema, then calls AssetService.update for each asset_id with { status }. Each update is tenant-scoped by assets.asset_id and assets.tenant and publishes an ASSET_UPDATED event.",
    "tags": [
      "Assets"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "asset_ids": {
          "type": "array",
          "items": {
            "type": "string",
            "format": "uuid"
          },
          "minItems": 1,
          "maxItems": 50,
          "description": "Asset UUIDs from assets.asset_id. Limited to 1 through 50 entries by validation."
        },
        "status": {
          "type": "string",
          "minLength": 1,
          "description": "New status assigned to every asset in asset_ids."
        }
      },
      "required": [
        "asset_ids",
        "status"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "success": {
          "type": "boolean",
          "enum": [
            true
          ]
        },
        "data": {
          "$ref": "#/components/schemas/AssetBulkUpdatePayload"
        },
        "meta": {
          "$ref": "#/components/schemas/ApiResponseMeta"
        }
      },
      "required": [
        "success",
        "data",
        "meta"
      ]
    }
  },
  {
    "id": "put-_api_v1_assets_bulkupdate",
    "method": "put",
    "path": "/api/v1/assets/bulk-update",
    "displayName": "Bulk update assets",
    "summary": "Bulk update assets",
    "description": "Updates up to 50 assets in the authenticated tenant. Each array item supplies an asset_id and partial update data validated with updateAssetSchema. The controller calls AssetService.update for every item, tenant-scoping each update by asset_id and context.tenant and publishing ASSET_UPDATED events.",
    "tags": [
      "Assets"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "assets": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "asset_id": {
                "type": "string",
                "format": "uuid",
                "description": "Asset UUID from assets.asset_id."
              },
              "data": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/AssetUpdateData"
                  },
                  {
                    "description": "Partial update data validated with updateAssetSchema."
                  }
                ]
              }
            },
            "required": [
              "asset_id",
              "data"
            ]
          },
          "minItems": 1,
          "maxItems": 50,
          "description": "Assets to update. Limited to 1 through 50 entries by validation."
        }
      },
      "required": [
        "assets"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "success": {
          "type": "boolean",
          "enum": [
            true
          ]
        },
        "data": {
          "$ref": "#/components/schemas/AssetBulkUpdatePayload"
        },
        "meta": {
          "$ref": "#/components/schemas/ApiResponseMeta"
        }
      },
      "required": [
        "success",
        "data",
        "meta"
      ]
    }
  },
  {
    "id": "delete-_api_v1_assets_documents_associationid",
    "method": "delete",
    "path": "/api/v1/assets/documents/{associationId}",
    "displayName": "Remove asset document association",
    "summary": "Remove asset document association",
    "description": "Removes a document association row by document_associations.association_id for the authenticated tenant. The service deletes rows where association_id and tenant match and does not verify entity_type in this method. The controller intends to return an empty success response after deletion, but currently calls createApiResponse(null, 204) inside NextResponse.json, which can throw because JSON responses cannot use status 204 with a body.",
    "tags": [
      "Assets"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "associationId",
        "in": "path",
        "required": true,
        "description": "Document association UUID from document_associations.association_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Document association UUID from document_associations.association_id."
        }
      }
    ]
  },
  {
    "id": "get-_api_v1_assets_export",
    "method": "get",
    "path": "/api/v1/assets/export",
    "displayName": "Export assets",
    "summary": "Export assets",
    "description": "Exports all assets for the authenticated tenant (paginated internally, not capped to the default list page). Optional set filters asset_types, statuses, and client_ids narrow the result; fields restricts the exported columns. format=csv (default) returns text/csv with Content-Disposition attachment filename=assets.csv; format=json returns the success envelope with the rows in data. The route is authenticated and tenant-scoped via withApiKeyRouteAuth.",
    "tags": [
      "Assets"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "format",
        "in": "query",
        "required": false,
        "description": "Export format. csv (default) returns text/csv as an attachment; json returns the success envelope with the rows in data.",
        "schema": {
          "type": "string",
          "enum": [
            "csv",
            "json"
          ],
          "description": "Export format. csv (default) returns text/csv as an attachment; json returns the success envelope with the rows in data."
        }
      },
      {
        "name": "asset_types",
        "in": "query",
        "required": false,
        "description": "Filter to these asset types. Repeat the param or pass a comma-separated list.",
        "schema": {
          "type": "array",
          "items": {
            "type": "string",
            "enum": [
              "workstation",
              "network_device",
              "server",
              "mobile_device",
              "printer",
              "unknown"
            ]
          },
          "description": "Filter to these asset types. Repeat the param or pass a comma-separated list."
        }
      },
      {
        "name": "statuses",
        "in": "query",
        "required": false,
        "description": "Filter to these asset statuses. Repeat the param or pass a comma-separated list.",
        "schema": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "description": "Filter to these asset statuses. Repeat the param or pass a comma-separated list."
        }
      },
      {
        "name": "client_ids",
        "in": "query",
        "required": false,
        "description": "Filter to these client UUIDs. Repeat the param or pass a comma-separated list.",
        "schema": {
          "type": "array",
          "items": {
            "type": "string",
            "format": "uuid"
          },
          "description": "Filter to these client UUIDs. Repeat the param or pass a comma-separated list."
        }
      },
      {
        "name": "fields",
        "in": "query",
        "required": false,
        "description": "Restrict exported columns to this set. Repeat the param or pass a comma-separated list.",
        "schema": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "description": "Restrict exported columns to this set. Repeat the param or pass a comma-separated list."
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "success": {
          "type": "boolean",
          "enum": [
            true
          ]
        },
        "data": {
          "$ref": "#/components/schemas/AssetExportJsonPayload"
        },
        "meta": {
          "$ref": "#/components/schemas/ApiResponseMeta"
        }
      },
      "required": [
        "success",
        "data",
        "meta"
      ]
    }
  },
  {
    "id": "put-_api_v1_assets_maintenance_scheduleid",
    "method": "put",
    "path": "/api/v1/assets/maintenance/{scheduleId}",
    "displayName": "Update asset maintenance schedule",
    "summary": "Update asset maintenance schedule",
    "description": "Updates a maintenance schedule by asset_maintenance_schedules.schedule_id for the authenticated tenant. All request fields are optional because updateMaintenanceScheduleSchema is a partial form of the create schema. If frequency, frequency_interval, or start_date are supplied, the service loads the existing schedule for the tenant and recalculates next_maintenance. Missing or cross-tenant schedule IDs result in a 200 response with an undefined nested data value rather than 404.",
    "tags": [
      "Assets"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "scheduleId",
        "in": "path",
        "required": true,
        "description": "Maintenance schedule UUID from asset_maintenance_schedules.schedule_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Maintenance schedule UUID from asset_maintenance_schedules.schedule_id."
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "schedule_type": {
          "type": "string",
          "enum": [
            "preventive",
            "inspection",
            "calibration",
            "replacement"
          ],
          "description": "Type of maintenance schedule."
        },
        "frequency": {
          "type": "string",
          "enum": [
            "daily",
            "weekly",
            "monthly",
            "quarterly",
            "yearly",
            "custom"
          ],
          "description": "Recurrence frequency. Changing this triggers next_maintenance recalculation."
        },
        "frequency_interval": {
          "type": "number",
          "minimum": 1,
          "description": "Frequency multiplier used when calculating the next maintenance date."
        },
        "start_date": {
          "type": "string",
          "format": "date-time",
          "description": "Schedule start date/time. Changing this triggers next_maintenance recalculation."
        },
        "end_date": {
          "type": "string",
          "format": "date-time",
          "description": "Optional schedule end date/time."
        },
        "notes": {
          "type": "string",
          "description": "Free-text schedule notes."
        },
        "assigned_to": {
          "type": "string",
          "format": "uuid",
          "description": "Assigned user UUID from users.user_id."
        },
        "is_active": {
          "type": "boolean",
          "description": "Whether the schedule is active."
        },
        "schedule_config": {
          "type": "object",
          "additionalProperties": {},
          "description": "Custom scheduling configuration."
        }
      }
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "success": {
          "type": "boolean",
          "enum": [
            true
          ]
        },
        "data": {
          "$ref": "#/components/schemas/AssetMaintenanceSchedulePayload"
        },
        "meta": {
          "$ref": "#/components/schemas/ApiResponseMeta"
        }
      },
      "required": [
        "success",
        "data",
        "meta"
      ]
    }
  },
  {
    "id": "delete-_api_v1_assets_maintenance_scheduleid",
    "method": "delete",
    "path": "/api/v1/assets/maintenance/{scheduleId}",
    "displayName": "Delete asset maintenance schedule",
    "summary": "Delete asset maintenance schedule",
    "description": "Deletes a maintenance schedule by asset_maintenance_schedules.schedule_id for the authenticated tenant. The service scopes deletion by schedule_id and context.tenant and performs no existence check, so missing or cross-tenant IDs are silent no-ops. The controller intends to return 204 with no body, but currently constructs a JSON response with status 204, which can throw in NextResponse.",
    "tags": [
      "Assets"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "scheduleId",
        "in": "path",
        "required": true,
        "description": "Maintenance schedule UUID from asset_maintenance_schedules.schedule_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Maintenance schedule UUID from asset_maintenance_schedules.schedule_id."
        }
      }
    ]
  },
  {
    "id": "delete-_api_v1_assets_relationships_relationshipid",
    "method": "delete",
    "path": "/api/v1/assets/relationships/{relationshipId}",
    "displayName": "Delete asset relationship",
    "summary": "Delete asset relationship",
    "description": "Deletes an asset relationship by asset_relationships.relationship_id for the authenticated tenant. The service hard-deletes rows where relationship_id and context.tenant match, publishes no event, and performs no existence check; missing or cross-tenant IDs are silent no-ops. The controller intends to return 204 with no body, but currently constructs a JSON response with status 204, which can throw in NextResponse.",
    "tags": [
      "Assets"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "relationshipId",
        "in": "path",
        "required": true,
        "description": "Asset relationship UUID from asset_relationships.relationship_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Asset relationship UUID from asset_relationships.relationship_id."
        }
      }
    ]
  },
  {
    "id": "get-_api_v1_assets_search",
    "method": "get",
    "path": "/api/v1/assets/search",
    "displayName": "Search assets",
    "summary": "Search assets",
    "description": "Searches tenant assets with a required query term and optional field, asset type, status, client, extension-data, and limit parameters. The service searches assets scoped to context.tenant, joins clients for client_name, and optionally loads asset-type-specific extension data per result. The response is not paginated and includes HATEOAS links for each asset; the top-level search link currently points at /api/v2/assets/search.",
    "tags": [
      "Assets"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "query",
        "in": "query",
        "required": true,
        "description": "Required search term used in ILIKE clauses.",
        "schema": {
          "type": "string",
          "minLength": 1,
          "description": "Required search term used in ILIKE clauses."
        }
      },
      {
        "name": "fields",
        "in": "query",
        "required": false,
        "description": "Search fields. If omitted, the service searches asset_tag, name, serial_number, and location.",
        "schema": {
          "type": "array",
          "items": {
            "type": "string",
            "enum": [
              "asset_tag",
              "name",
              "serial_number",
              "location",
              "client_name"
            ]
          },
          "description": "Search fields. If omitted, the service searches asset_tag, name, serial_number, and location."
        }
      },
      {
        "name": "asset_types",
        "in": "query",
        "required": false,
        "description": "Optional asset type filters.",
        "schema": {
          "type": "array",
          "items": {
            "type": "string",
            "enum": [
              "workstation",
              "network_device",
              "server",
              "mobile_device",
              "printer",
              "unknown"
            ]
          },
          "description": "Optional asset type filters."
        }
      },
      {
        "name": "statuses",
        "in": "query",
        "required": false,
        "description": "Optional status filters.",
        "schema": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "description": "Optional status filters."
        }
      },
      {
        "name": "client_ids",
        "in": "query",
        "required": false,
        "description": "Optional client UUID filters.",
        "schema": {
          "type": "array",
          "items": {
            "type": "string",
            "format": "uuid"
          },
          "description": "Optional client UUID filters."
        }
      },
      {
        "name": "include_extension_data",
        "in": "query",
        "required": false,
        "description": "When true, the service fetches asset-type-specific extension data for every result.",
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ],
          "description": "When true, the service fetches asset-type-specific extension data for every result."
        }
      },
      {
        "name": "limit",
        "in": "query",
        "required": false,
        "description": "Maximum result count as a query string. Must parse to 1 through 100; defaults to 25.",
        "schema": {
          "type": "string",
          "description": "Maximum result count as a query string. Must parse to 1 through 100; defaults to 25."
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "success": {
          "type": "boolean",
          "enum": [
            true
          ]
        },
        "data": {
          "$ref": "#/components/schemas/AssetSearchPayload"
        },
        "meta": {
          "$ref": "#/components/schemas/ApiResponseMeta"
        }
      },
      "required": [
        "success",
        "data",
        "meta"
      ]
    }
  },
  {
    "id": "get-_api_v1_assets_stats",
    "method": "get",
    "path": "/api/v1/assets/stats",
    "displayName": "Get asset statistics",
    "summary": "Get asset statistics",
    "description": "Returns tenant-scoped aggregate asset statistics including total counts, counts by type/status/client, warranty counts, and maintenance due/overdue counts. The service runs multiple aggregate queries filtered by context.tenant; assets_by_client is limited to the top 10 client names. The response links currently point at /api/v2/assets paths.",
    "tags": [
      "Assets"
    ],
    "approvalRequired": false,
    "parameters": [],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "success": {
          "type": "boolean",
          "enum": [
            true
          ]
        },
        "data": {
          "$ref": "#/components/schemas/AssetStatsPayload"
        },
        "meta": {
          "$ref": "#/components/schemas/ApiResponseMeta"
        }
      },
      "required": [
        "success",
        "data",
        "meta"
      ]
    }
  },
  {
    "id": "get-_api_v1_assets_id",
    "method": "get",
    "path": "/api/v1/assets/{id}",
    "displayName": "Get asset details",
    "summary": "Get asset details",
    "description": "Returns detailed asset information for the authenticated tenant, including joined client_name, computed warranty_status, client details, type-specific extension_data, relationships, document associations, maintenance schedules, and HATEOAS links. The service first loads assets by asset_id and context.tenant, then loads related data in parallel. If the asset is not found, the controller returns a 404 error envelope.",
    "tags": [
      "Assets"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Asset UUID from assets.asset_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Asset UUID from assets.asset_id."
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "success": {
          "type": "boolean",
          "enum": [
            true
          ]
        },
        "data": {
          "allOf": [
            {
              "$ref": "#/components/schemas/AssetResourcePayload"
            },
            {
              "description": "Nested payload passed to createApiResponse by ApiAssetController.create."
            }
          ]
        },
        "meta": {
          "$ref": "#/components/schemas/ApiResponseMeta"
        }
      },
      "required": [
        "success",
        "data",
        "meta"
      ]
    }
  },
  {
    "id": "put-_api_v1_assets_id",
    "method": "put",
    "path": "/api/v1/assets/{id}",
    "displayName": "Update asset",
    "summary": "Update asset",
    "description": "Partially updates base asset fields for the authenticated tenant. The request body is validated with updateAssetSchema, where all fields are optional. AssetService.update scopes the update by asset_id and context.tenant, writes updated_at, publishes ASSET_UPDATED, and returns the refreshed base asset with joined client_name and warranty_status. This REST path does not update extension data, create asset history records, or wrap the update in a transaction. Missing assets currently lead to a 500 when the controller tries to add links to a null result rather than a clean 404.",
    "tags": [
      "Assets"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Asset UUID from assets.asset_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Asset UUID from assets.asset_id."
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "client_id": {
          "type": "string",
          "format": "uuid",
          "description": "Client UUID to assign to the asset."
        },
        "asset_type": {
          "type": "string",
          "enum": [
            "workstation",
            "network_device",
            "server",
            "mobile_device",
            "printer",
            "unknown"
          ],
          "description": "Asset type to store in assets.asset_type."
        },
        "asset_tag": {
          "type": "string",
          "minLength": 1,
          "maxLength": 255,
          "description": "Tenant-specific asset tag."
        },
        "name": {
          "type": "string",
          "minLength": 1,
          "maxLength": 255,
          "description": "Asset name."
        },
        "status": {
          "type": "string",
          "minLength": 1,
          "description": "Asset status."
        },
        "location_id": {
          "type": [
            "string",
            "null"
          ],
          "format": "uuid",
          "description": "Client_locations.location_id link. Pass null to clear."
        },
        "location": {
          "type": "string",
          "description": "Free-text asset location."
        },
        "serial_number": {
          "type": "string",
          "description": "Serial number."
        },
        "purchase_date": {
          "type": "string",
          "format": "date-time",
          "description": "Purchase date/time."
        },
        "warranty_end_date": {
          "type": "string",
          "format": "date-time",
          "description": "Warranty end date/time."
        }
      }
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "success": {
          "type": "boolean",
          "enum": [
            true
          ]
        },
        "data": {
          "allOf": [
            {
              "$ref": "#/components/schemas/AssetResourcePayload"
            },
            {
              "description": "Nested payload passed to createApiResponse by ApiAssetController.create."
            }
          ]
        },
        "meta": {
          "$ref": "#/components/schemas/ApiResponseMeta"
        }
      },
      "required": [
        "success",
        "data",
        "meta"
      ]
    }
  },
  {
    "id": "delete-_api_v1_assets_id",
    "method": "delete",
    "path": "/api/v1/assets/{id}",
    "displayName": "Delete asset",
    "summary": "Delete asset",
    "description": "Hard-deletes an asset for the authenticated tenant. AssetService.delete first loads the asset by asset_id and context.tenant, deletes asset-type-specific extension data, deletes tenant_external_entity_mappings for the asset, deletes the assets row, and publishes ASSET_DELETED. The method overrides the BaseService softDelete configuration and does not explicitly clean every related table handled by the server-action delete path. Missing assets throw a generic Error and currently surface as 500 via handleApiError rather than 404. The controller also constructs a JSON response with status 204, which can throw in NextResponse.",
    "tags": [
      "Assets"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Asset UUID from assets.asset_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Asset UUID from assets.asset_id."
        }
      }
    ]
  },
  {
    "id": "get-_api_v1_assets_id_documents",
    "method": "get",
    "path": "/api/v1/assets/{id}/documents",
    "displayName": "List asset document associations",
    "summary": "List asset document associations",
    "description": "Returns document_associations rows for an asset in the authenticated tenant where entity_type is asset and entity_id is the path asset ID. The service joins documents to add original_filename, file_size, mime_type, and uploaded_at. It does not check whether the asset exists first, so nonexistent or cross-tenant asset IDs return 200 with an empty array. Response links currently point at /api/v2/assets paths.",
    "tags": [
      "Assets"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Asset UUID from assets.asset_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Asset UUID from assets.asset_id."
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "success": {
          "type": "boolean",
          "enum": [
            true
          ]
        },
        "data": {
          "$ref": "#/components/schemas/AssetDocumentListPayload"
        },
        "meta": {
          "type": "object",
          "properties": {
            "timestamp": {
              "type": "string",
              "format": "date-time"
            },
            "version": {
              "type": "string"
            }
          },
          "required": [
            "timestamp",
            "version"
          ]
        }
      },
      "required": [
        "success",
        "data",
        "meta"
      ]
    }
  },
  {
    "id": "post-_api_v1_assets_id_documents",
    "method": "post",
    "path": "/api/v1/assets/{id}/documents",
    "displayName": "Associate document with asset",
    "summary": "Associate document with asset",
    "description": "Creates a document_associations row that links the path asset ID to the supplied document_id. The body is validated with createAssetDocumentSchema; document_id is required and notes is optional. The service inserts entity_type=asset, entity_id from the path, document_id, notes, tenant from context, and created_at, then returns the inserted row. It does not verify that the asset or document belongs to the same tenant before insert, does not set created_by, and publishes no event. Foreign-key or unique constraint errors surface through handleApiError.",
    "tags": [
      "Assets"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Asset UUID from assets.asset_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Asset UUID from assets.asset_id."
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "document_id": {
          "type": "string",
          "format": "uuid",
          "description": "Document UUID from documents.document_id to associate with the asset."
        },
        "notes": {
          "type": "string",
          "description": "Optional notes stored on document_associations.notes."
        }
      },
      "required": [
        "document_id"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "success": {
          "type": "boolean",
          "enum": [
            true
          ]
        },
        "data": {
          "$ref": "#/components/schemas/AssetDocumentAssociationPayload"
        },
        "meta": {
          "type": "object",
          "properties": {
            "timestamp": {
              "type": "string",
              "format": "date-time"
            },
            "version": {
              "type": "string"
            }
          },
          "required": [
            "timestamp",
            "version"
          ]
        }
      },
      "required": [
        "success",
        "data",
        "meta"
      ]
    }
  },
  {
    "id": "get-_api_v1_assets_id_history",
    "method": "get",
    "path": "/api/v1/assets/{id}/history",
    "displayName": "List asset maintenance history",
    "summary": "List asset maintenance history",
    "description": "Returns all maintenance history rows for the path asset ID in the authenticated tenant, ordered by performed_at descending. The service joins users to add performed_by_user_name and filters asset_maintenance_history by asset_id and context.tenant. It performs no asset existence check, so nonexistent or cross-tenant asset IDs return 200 with an empty array. Response links currently point at /api/v2/assets paths.",
    "tags": [
      "Assets"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Asset UUID from assets.asset_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Asset UUID from assets.asset_id."
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "success": {
          "type": "boolean",
          "enum": [
            true
          ]
        },
        "data": {
          "$ref": "#/components/schemas/AssetMaintenanceHistoryPayload"
        },
        "meta": {
          "$ref": "#/components/schemas/ApiResponseMeta"
        }
      },
      "required": [
        "success",
        "data",
        "meta"
      ]
    }
  },
  {
    "id": "get-_api_v1_assets_id_maintenance",
    "method": "get",
    "path": "/api/v1/assets/{id}/maintenance",
    "displayName": "List asset maintenance schedules",
    "summary": "List asset maintenance schedules",
    "description": "Returns maintenance schedule rows for the path asset ID in the authenticated tenant. The service filters asset_maintenance_schedules by asset_id and context.tenant and joins users to add assigned_user_name. It performs no asset existence check, so nonexistent or cross-tenant asset IDs return 200 with an empty array. Response links currently point at /api/v2/assets paths.",
    "tags": [
      "Assets"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Asset UUID from assets.asset_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Asset UUID from assets.asset_id."
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "success": {
          "type": "boolean",
          "enum": [
            true
          ]
        },
        "data": {
          "$ref": "#/components/schemas/AssetMaintenanceScheduleListPayload"
        },
        "meta": {
          "$ref": "#/components/schemas/ApiResponseMeta"
        }
      },
      "required": [
        "success",
        "data",
        "meta"
      ]
    }
  },
  {
    "id": "post-_api_v1_assets_id_maintenance",
    "method": "post",
    "path": "/api/v1/assets/{id}/maintenance",
    "displayName": "Create asset maintenance schedule",
    "summary": "Create asset maintenance schedule",
    "description": "Creates a maintenance schedule for the path asset ID in the authenticated tenant. The request body is validated with createMaintenanceScheduleSchema; schedule_type and frequency are required, while start_date is optional in the current shared date schema and the service falls back to now when absent. The service inserts asset_id from the path, tenant from context, timestamps, and a calculated next_maintenance value. It does not verify asset existence, does not set created_by, and publishes no event.",
    "tags": [
      "Assets"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Asset UUID from assets.asset_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Asset UUID from assets.asset_id."
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "schedule_type": {
          "type": "string",
          "enum": [
            "preventive",
            "inspection",
            "calibration",
            "replacement"
          ],
          "description": "Required type of maintenance schedule."
        },
        "frequency": {
          "type": "string",
          "enum": [
            "daily",
            "weekly",
            "monthly",
            "quarterly",
            "yearly",
            "custom"
          ],
          "description": "Required recurrence frequency used to calculate next_maintenance."
        },
        "frequency_interval": {
          "type": "number",
          "minimum": 1,
          "description": "Frequency multiplier. Defaults to service logic when absent."
        },
        "start_date": {
          "type": "string",
          "format": "date-time",
          "description": "Schedule start date/time. The current schema makes this optional; the service falls back to now when absent."
        },
        "end_date": {
          "type": "string",
          "format": "date-time",
          "description": "Optional schedule end date/time."
        },
        "notes": {
          "type": "string",
          "description": "Free-text schedule notes."
        },
        "assigned_to": {
          "type": "string",
          "format": "uuid",
          "description": "Assigned user UUID from users.user_id."
        },
        "is_active": {
          "type": "boolean",
          "description": "Whether the schedule is active. Defaults to true in validation."
        },
        "schedule_config": {
          "type": "object",
          "additionalProperties": {},
          "description": "Custom scheduling configuration."
        }
      },
      "required": [
        "schedule_type",
        "frequency"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "success": {
          "type": "boolean",
          "enum": [
            true
          ]
        },
        "data": {
          "$ref": "#/components/schemas/AssetMaintenanceSchedulePayload"
        },
        "meta": {
          "$ref": "#/components/schemas/ApiResponseMeta"
        }
      },
      "required": [
        "success",
        "data",
        "meta"
      ]
    }
  },
  {
    "id": "post-_api_v1_assets_id_maintenance_record",
    "method": "post",
    "path": "/api/v1/assets/{id}/maintenance/record",
    "displayName": "Record asset maintenance",
    "summary": "Record asset maintenance",
    "description": "Inserts an asset_maintenance_history row for the path asset ID in the authenticated tenant. The request body requires maintenance_type, performed_by, and performed_at; schedule_id, duration, cost, notes, parts, and structured maintenance_data are optional. If schedule_id is supplied and a matching tenant schedule exists, the service updates that schedule last_maintenance and next_maintenance. It does not verify asset existence or performed_by before insert, does not set created_by, and publishes no event.",
    "tags": [
      "Assets"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Asset UUID from assets.asset_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Asset UUID from assets.asset_id."
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "schedule_id": {
          "type": "string",
          "format": "uuid",
          "description": "Optional maintenance schedule UUID. If present and found for the tenant, the schedule last_maintenance and next_maintenance are updated."
        },
        "maintenance_type": {
          "type": "string",
          "enum": [
            "preventive",
            "corrective",
            "inspection",
            "calibration",
            "replacement"
          ],
          "description": "Required type of maintenance performed."
        },
        "performed_by": {
          "type": "string",
          "format": "uuid",
          "description": "Required UUID of the user who performed maintenance. The service does not validate this user before insert."
        },
        "performed_at": {
          "type": "string",
          "format": "date-time",
          "description": "Required timestamp when maintenance was performed."
        },
        "duration_hours": {
          "type": "number",
          "minimum": 0,
          "description": "Optional duration in hours."
        },
        "cost": {
          "type": "number",
          "minimum": 0,
          "description": "Optional cost."
        },
        "notes": {
          "type": "string",
          "description": "Optional notes."
        },
        "parts_used": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "description": "Optional list of parts used."
        },
        "maintenance_data": {
          "type": "object",
          "additionalProperties": {},
          "description": "Optional structured maintenance data."
        }
      },
      "required": [
        "maintenance_type",
        "performed_by",
        "performed_at"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "success": {
          "type": "boolean",
          "enum": [
            true
          ]
        },
        "data": {
          "$ref": "#/components/schemas/AssetRecordMaintenancePayload"
        },
        "meta": {
          "$ref": "#/components/schemas/ApiResponseMeta"
        }
      },
      "required": [
        "success",
        "data",
        "meta"
      ]
    }
  },
  {
    "id": "get-_api_v1_assets_id_relationships",
    "method": "get",
    "path": "/api/v1/assets/{id}/relationships",
    "displayName": "List asset relationships",
    "summary": "List asset relationships",
    "description": "Returns asset_relationships rows for the path asset ID in the authenticated tenant, joined with the related assets table for display fields. The service filters by asset_relationships.asset_id and context.tenant and joins related assets on matching tenant. It performs no parent asset existence check and does not filter soft-deleted related assets. Response links currently point at /api/v2/assets paths.",
    "tags": [
      "Assets"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Asset UUID from assets.asset_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Asset UUID from assets.asset_id."
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "success": {
          "type": "boolean",
          "enum": [
            true
          ]
        },
        "data": {
          "$ref": "#/components/schemas/AssetRelationshipListPayload"
        },
        "meta": {
          "$ref": "#/components/schemas/ApiResponseMeta"
        }
      },
      "required": [
        "success",
        "data",
        "meta"
      ]
    }
  },
  {
    "id": "post-_api_v1_assets_id_relationships",
    "method": "post",
    "path": "/api/v1/assets/{id}/relationships",
    "displayName": "Create asset relationship",
    "summary": "Create asset relationship",
    "description": "Creates a relationship row between the path asset ID and related_asset_id for the authenticated tenant. The request body requires related_asset_id and non-empty relationship_type. The service rejects self relationships and duplicate source/related pairs, but currently throws generic Errors for those cases, which surface as 500 rather than 400 or 409. The inserted row is returned without joined related asset details.",
    "tags": [
      "Assets"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Asset UUID from assets.asset_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Asset UUID from assets.asset_id."
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "related_asset_id": {
          "type": "string",
          "format": "uuid",
          "description": "Related asset UUID from assets.asset_id."
        },
        "relationship_type": {
          "type": "string",
          "minLength": 1,
          "description": "Free-form relationship type. Must be non-empty."
        }
      },
      "required": [
        "related_asset_id",
        "relationship_type"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "success": {
          "type": "boolean",
          "enum": [
            true
          ]
        },
        "data": {
          "$ref": "#/components/schemas/AssetRelationshipPayload"
        },
        "meta": {
          "$ref": "#/components/schemas/ApiResponseMeta"
        }
      },
      "required": [
        "success",
        "data",
        "meta"
      ]
    }
  },
  {
    "id": "listAssetTickets",
    "method": "get",
    "path": "/api/v1/assets/{id}/tickets",
    "displayName": "List tickets linked to an asset",
    "summary": "List tickets linked to an asset",
    "description": "Returns tickets associated with the path asset ID in the authenticated tenant, read from asset_associations where entity_type is ticket, joined to tickets and statuses. Results include the association relationship_type and linked_at and are ordered by ticket updated_at descending. This mirrors the asset detail UI and the assets.find_associated_tickets workflow action. The route is authenticated and tenant-scoped via withApiKeyRouteAuth (req.context is populated and RLS is active) and enforces BOTH asset:read and ticket:read because the response joins ticket data. It performs no asset existence check, so a valid caller hitting a nonexistent or cross-tenant asset ID gets 200 with an empty array (tenant scoping prevents cross-tenant leakage; this is not an authorization bypass).",
    "tags": [
      "Assets"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Asset UUID from assets.asset_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Asset UUID from assets.asset_id."
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "success": {
          "type": "boolean",
          "enum": [
            true
          ]
        },
        "data": {
          "type": "array",
          "items": {
            "$ref": "#/components/schemas/AssetTicketRow"
          },
          "description": "Tickets linked to the asset via asset_associations, ordered by ticket updated_at descending. Empty when no associations exist or the asset is not found."
        },
        "meta": {
          "$ref": "#/components/schemas/ApiResponseMeta"
        }
      },
      "required": [
        "success",
        "data",
        "meta"
      ]
    }
  },
  {
    "id": "linkTicketToAsset",
    "method": "post",
    "path": "/api/v1/assets/{id}/tickets",
    "displayName": "Link a ticket to an asset",
    "summary": "Link a ticket to an asset",
    "description": "Creates an asset_associations row (entity_type=ticket) linking the path asset to the ticket in the request body. This is the same table the asset detail UI, GET /api/v1/assets/{id}/tickets, and GET /api/v1/tickets/{id}/assets read, so the link is immediately visible from both sides. relationship_type defaults to affected. The route is authenticated and tenant-scoped via withApiKeyRouteAuth and enforces asset:update (the asset associations are being mutated) plus ticket:read (the ticket is only referenced). Both the asset and the ticket must exist in the tenant (404 otherwise), and a duplicate link returns 409.",
    "tags": [
      "Assets"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Asset UUID from assets.asset_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Asset UUID from assets.asset_id."
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "ticket_id": {
          "type": "string",
          "format": "uuid",
          "description": "Ticket UUID to link to the asset."
        },
        "relationship_type": {
          "type": "string",
          "minLength": 1,
          "description": "Optional association type; defaults to affected."
        },
        "notes": {
          "type": "string",
          "description": "Optional notes stored on asset_associations.notes."
        }
      },
      "required": [
        "ticket_id"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "success": {
          "type": "boolean",
          "enum": [
            true
          ]
        },
        "data": {
          "allOf": [
            {
              "$ref": "#/components/schemas/AssetAssociationRow"
            },
            {
              "description": "The inserted asset_associations row."
            }
          ]
        },
        "meta": {
          "$ref": "#/components/schemas/ApiResponseMeta"
        }
      },
      "required": [
        "success",
        "data",
        "meta"
      ]
    }
  },
  {
    "id": "listTicketAssets",
    "method": "get",
    "path": "/api/v1/tickets/{id}/assets",
    "displayName": "List assets linked to a ticket",
    "summary": "List assets linked to a ticket",
    "description": "Returns assets associated with the path ticket ID in the authenticated tenant, read from asset_associations where entity_type is ticket, joined to assets and clients. Each row includes the asset fields plus the association relationship_type, association_notes, and linked_at, ordered by link time descending. The route is authenticated and tenant-scoped via ApiBaseController.authenticate + runWithTenant (RLS active); it enforces ticket:read, a per-ticket authorization-kernel check (assertTicketReadAllowed), AND asset:read because the response exposes asset records. The response uses the apiMiddleware envelope ({ data } with no top-level success field). It performs no asset existence check beyond the ticket authorization, so an authorized caller on a ticket with no linked assets gets 200 with an empty array.",
    "tags": [
      "Assets"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Asset UUID from assets.asset_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Asset UUID from assets.asset_id."
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "type": "array",
          "items": {
            "$ref": "#/components/schemas/TicketAssetRow"
          },
          "description": "Assets linked to the ticket via asset_associations, ordered by link time descending. Empty when no associations exist or the ticket is not found."
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "linkAssetToTicket",
    "method": "post",
    "path": "/api/v1/tickets/{id}/assets",
    "displayName": "Link an asset to a ticket",
    "summary": "Link an asset to a ticket",
    "description": "Creates an asset_associations row (entity_type=ticket) linking the asset in the request body to the path ticket. Same table GET /api/v1/tickets/{id}/assets and the asset detail UI read, so the link is visible from both sides. relationship_type defaults to affected. The route is authenticated and tenant-scoped via ApiBaseController.authenticate + runWithTenant; it enforces ticket:update plus a per-ticket authorization-kernel check (assertTicketReadAllowed) AND asset:read (the asset is referenced). The response uses the apiMiddleware envelope ({ data } with no top-level success field). Both the ticket and asset must exist (404 otherwise); a duplicate link returns 409.",
    "tags": [
      "Assets"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Asset UUID from assets.asset_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Asset UUID from assets.asset_id."
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "asset_id": {
          "type": "string",
          "format": "uuid",
          "description": "Asset UUID to link to the ticket."
        },
        "relationship_type": {
          "type": "string",
          "minLength": 1,
          "description": "Optional association type; defaults to affected."
        },
        "notes": {
          "type": "string",
          "description": "Optional notes stored on asset_associations.notes."
        }
      },
      "required": [
        "asset_id"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "allOf": [
            {
              "$ref": "#/components/schemas/AssetAssociationRow"
            },
            {
              "description": "The inserted asset_associations row."
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "unlinkTicketFromAsset",
    "method": "delete",
    "path": "/api/v1/assets/{id}/tickets/{ticketId}",
    "displayName": "Unlink a ticket from an asset",
    "summary": "Unlink a ticket from an asset",
    "description": "Deletes the asset_associations row (entity_type=ticket) linking the path asset and ticket for the authenticated tenant. The route is authenticated and tenant-scoped via withApiKeyRouteAuth and enforces asset:update plus ticket:read. Returns 404 when no such link exists.",
    "tags": [
      "Assets"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Asset UUID from assets.asset_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Asset UUID from assets.asset_id."
        }
      },
      {
        "name": "ticketId",
        "in": "path",
        "required": true,
        "description": "Ticket UUID from tickets.ticket_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Ticket UUID from tickets.ticket_id."
        }
      }
    ]
  },
  {
    "id": "unlinkAssetFromTicket",
    "method": "delete",
    "path": "/api/v1/tickets/{id}/assets/{assetId}",
    "displayName": "Unlink an asset from a ticket",
    "summary": "Unlink an asset from a ticket",
    "description": "Deletes the asset_associations row (entity_type=ticket) linking the path asset and ticket for the authenticated tenant. Authenticated and tenant-scoped via ApiBaseController.authenticate + runWithTenant; enforces ticket:update plus the per-ticket authorization check and asset:read. Returns 404 when no such link exists.",
    "tags": [
      "Assets"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Ticket UUID from tickets.ticket_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Ticket UUID from tickets.ticket_id."
        }
      },
      {
        "name": "assetId",
        "in": "path",
        "required": true,
        "description": "Asset UUID from assets.asset_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Asset UUID from assets.asset_id."
        }
      }
    ]
  },
  {
    "id": "get-_api_v1_assets_id_notes",
    "method": "get",
    "path": "/api/v1/assets/{id}/notes",
    "displayName": "Get asset notes",
    "summary": "Get asset notes",
    "description": "Returns the BlockNote content of the asset notes document, or an empty result when no notes exist.",
    "tags": [
      "Assets"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Asset UUID from assets.asset_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Asset UUID from assets.asset_id."
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "document": {
          "type": [
            "object",
            "null"
          ],
          "additionalProperties": {}
        },
        "blockData": {
          "description": "Parsed BlockNote JSON, or null when no notes exist."
        },
        "lastUpdated": {
          "type": [
            "string",
            "null"
          ]
        }
      }
    }
  },
  {
    "id": "put-_api_v1_assets_id_notes",
    "method": "put",
    "path": "/api/v1/assets/{id}/notes",
    "displayName": "Update asset notes",
    "summary": "Update asset notes",
    "description": "Creates or updates the BlockNote notes document linked to the asset. Returns the document id.",
    "tags": [
      "Assets"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Asset UUID from assets.asset_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Asset UUID from assets.asset_id."
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "blockData": {
          "description": "BlockNote JSON block data to store as the asset notes."
        }
      }
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "document_id": {
          "type": "string",
          "format": "uuid"
        }
      },
      "required": [
        "document_id"
      ]
    }
  },
  {
    "id": "delete-_api_v1_assets_id_notes",
    "method": "delete",
    "path": "/api/v1/assets/{id}/notes",
    "displayName": "Delete asset notes",
    "summary": "Delete asset notes",
    "description": "Unlinks the notes document from the asset. Pass delete_document=true to also hard-delete the document and its block content.",
    "tags": [
      "Assets"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Asset UUID from assets.asset_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Asset UUID from assets.asset_id."
        }
      },
      {
        "name": "delete_document",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ]
        }
      }
    ]
  },
  {
    "id": "get-_api_v1_assets_id_rmm",
    "method": "get",
    "path": "/api/v1/assets/{id}/rmm",
    "displayName": "Get cached RMM data",
    "summary": "Get cached RMM data",
    "description": "Returns the cached RMM device data synced from the RMM provider. Enterprise Edition feature — on Community Edition this returns null.",
    "tags": [
      "Assets"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Asset UUID from assets.asset_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Asset UUID from assets.asset_id."
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "type": [
            "object",
            "null"
          ],
          "additionalProperties": {},
          "description": "Cached RMM device data, or null (always null on Community Edition)."
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "post-_api_v1_assets_id_rmm_reboot",
    "method": "post",
    "path": "/api/v1/assets/{id}/rmm/reboot",
    "displayName": "Reboot device via RMM",
    "summary": "Reboot device via RMM",
    "description": "Sends a reboot command to the RMM-managed device. Enterprise Edition feature — on Community Edition this returns { success:false } with an EE-required message.",
    "tags": [
      "Assets"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Asset UUID from assets.asset_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Asset UUID from assets.asset_id."
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "success": {
          "type": "boolean"
        },
        "message": {
          "type": "string"
        },
        "jobId": {
          "type": "string",
          "description": "Provider job id when the action was queued (EE)."
        }
      },
      "required": [
        "success",
        "message"
      ]
    }
  },
  {
    "id": "post-_api_v1_assets_id_rmm_refresh",
    "method": "post",
    "path": "/api/v1/assets/{id}/rmm/refresh",
    "displayName": "Refresh RMM data for device",
    "summary": "Refresh RMM data for device",
    "description": "Triggers a single-device RMM sync and returns the refreshed data. Enterprise Edition feature — on Community Edition this returns null.",
    "tags": [
      "Assets"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Asset UUID from assets.asset_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Asset UUID from assets.asset_id."
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "type": [
            "object",
            "null"
          ],
          "additionalProperties": {},
          "description": "Cached RMM device data, or null (always null on Community Edition)."
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_assets_id_rmm_remotecontrol",
    "method": "get",
    "path": "/api/v1/assets/{id}/rmm/remote-control",
    "displayName": "Get remote-control session URL",
    "summary": "Get remote-control session URL",
    "description": "Generates a remote-control URL for the device using the protocol given by the type query param. Enterprise Edition feature — on Community Edition this returns null.",
    "tags": [
      "Assets"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Asset UUID from assets.asset_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Asset UUID from assets.asset_id."
        }
      },
      {
        "name": "type",
        "in": "query",
        "required": false,
        "description": "Remote-control protocol (default splashtop).",
        "schema": {
          "type": "string",
          "enum": [
            "splashtop",
            "teamviewer",
            "vnc",
            "rdp",
            "shell"
          ],
          "description": "Remote-control protocol (default splashtop)."
        }
      }
    ],
    "responseBodySchema": {
      "type": [
        "object",
        "null"
      ],
      "properties": {
        "url": {
          "type": "string"
        },
        "type": {
          "type": "string"
        }
      },
      "description": "Remote-control session URL, or null when unavailable (always null on Community Edition)."
    }
  },
  {
    "id": "post-_api_v1_assets_id_rmm_script",
    "method": "post",
    "path": "/api/v1/assets/{id}/rmm/script",
    "displayName": "Run a script via RMM",
    "summary": "Run a script via RMM",
    "description": "Runs the script identified by scriptId on the RMM-managed device. Enterprise Edition feature — on Community Edition this returns { success:false } with an EE-required message.",
    "tags": [
      "Assets"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Asset UUID from assets.asset_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Asset UUID from assets.asset_id."
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "scriptId": {
          "type": "string",
          "description": "Provider script identifier to run on the device."
        }
      },
      "required": [
        "scriptId"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "success": {
          "type": "boolean"
        },
        "message": {
          "type": "string"
        },
        "jobId": {
          "type": "string",
          "description": "Provider job id when the action was queued (EE)."
        }
      },
      "required": [
        "success",
        "message"
      ]
    }
  },
  {
    "id": "get-_api_v1_assets_id_software",
    "method": "get",
    "path": "/api/v1/assets/{id}/software",
    "displayName": "List asset software inventory",
    "summary": "List asset software inventory",
    "description": "Returns the paginated software inventory for the asset (from the normalized software tables), with filters for category, software_type, search, and include_uninstalled, plus a summary of totals.",
    "tags": [
      "Assets"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Asset UUID from assets.asset_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Asset UUID from assets.asset_id."
        }
      },
      {
        "name": "page",
        "in": "query",
        "required": false,
        "schema": {
          "type": "integer",
          "minimum": 1
        }
      },
      {
        "name": "limit",
        "in": "query",
        "required": false,
        "schema": {
          "type": "integer",
          "minimum": 1,
          "maximum": 200
        }
      },
      {
        "name": "category",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "software_type",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "search",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "include_uninstalled",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ]
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "type": "array",
          "items": {
            "type": "object",
            "additionalProperties": {}
          }
        },
        "summary": {
          "type": "object",
          "additionalProperties": {}
        },
        "pagination": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_assets_id_summary",
    "method": "get",
    "path": "/api/v1/assets/{id}/summary",
    "displayName": "Get asset summary metrics",
    "summary": "Get asset summary metrics",
    "description": "Returns computed asset metrics: health status/reason, security status/issues, warranty status and days remaining, and open ticket count.",
    "tags": [
      "Assets"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Asset UUID from assets.asset_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Asset UUID from assets.asset_id."
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "health_status": {
          "type": "string",
          "enum": [
            "healthy",
            "warning",
            "critical",
            "unknown"
          ]
        },
        "health_reason": {
          "type": "string"
        },
        "security_status": {
          "type": "string",
          "enum": [
            "secure",
            "at_risk",
            "critical"
          ]
        },
        "security_issues": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "warranty_status": {
          "type": "string",
          "enum": [
            "no_warranty",
            "expired",
            "expiring_soon",
            "active"
          ]
        },
        "warranty_days_remaining": {
          "type": [
            "number",
            "null"
          ]
        },
        "open_tickets_count": {
          "type": "number"
        }
      }
    }
  },
  {
    "id": "get-_api_v1_automation_executions",
    "method": "get",
    "path": "/api/v1/automation/executions",
    "displayName": "List automation executions",
    "summary": "List automation executions",
    "description": "Returns a paginated list of automation executions for the authenticated tenant. Authentication uses x-api-key with optional x-tenant-id; the controller validates the API key, resolves the user and tenant, runs under tenant context, and requires automation:read permission. The service forces tenant into the execution query conditions. Current service code appears to wrap the execution array in another array before createPaginatedResponse, which may produce nested data in practice.",
    "tags": [
      "Automation"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "page",
        "in": "query",
        "required": false,
        "description": "Page number as a query string. Defaults to 1.",
        "schema": {
          "type": "string",
          "description": "Page number as a query string. Defaults to 1."
        }
      },
      {
        "name": "limit",
        "in": "query",
        "required": false,
        "description": "Page size as a query string. Must parse to 1 through 100; defaults to 25.",
        "schema": {
          "type": "string",
          "description": "Page size as a query string. Must parse to 1 through 100; defaults to 25."
        }
      },
      {
        "name": "sort",
        "in": "query",
        "required": false,
        "description": "Accepted by shared list query validation; the service currently orders executions by started_at desc.",
        "schema": {
          "type": "string",
          "description": "Accepted by shared list query validation; the service currently orders executions by started_at desc."
        }
      },
      {
        "name": "order",
        "in": "query",
        "required": false,
        "description": "Accepted by shared list query validation.",
        "schema": {
          "type": "string",
          "enum": [
            "asc",
            "desc"
          ],
          "description": "Accepted by shared list query validation."
        }
      },
      {
        "name": "search",
        "in": "query",
        "required": false,
        "description": "Accepted by shared filter validation.",
        "schema": {
          "type": "string",
          "description": "Accepted by shared filter validation."
        }
      },
      {
        "name": "created_from",
        "in": "query",
        "required": false,
        "description": "Accepted by shared filter validation.",
        "schema": {
          "type": "string",
          "format": "date-time",
          "description": "Accepted by shared filter validation."
        }
      },
      {
        "name": "created_to",
        "in": "query",
        "required": false,
        "description": "Accepted by shared filter validation.",
        "schema": {
          "type": "string",
          "format": "date-time",
          "description": "Accepted by shared filter validation."
        }
      },
      {
        "name": "updated_from",
        "in": "query",
        "required": false,
        "description": "Accepted by shared filter validation.",
        "schema": {
          "type": "string",
          "format": "date-time",
          "description": "Accepted by shared filter validation."
        }
      },
      {
        "name": "updated_to",
        "in": "query",
        "required": false,
        "description": "Accepted by shared filter validation.",
        "schema": {
          "type": "string",
          "format": "date-time",
          "description": "Accepted by shared filter validation."
        }
      },
      {
        "name": "is_active",
        "in": "query",
        "required": false,
        "description": "Accepted by shared filter validation and transformed to boolean.",
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ],
          "description": "Accepted by shared filter validation and transformed to boolean."
        }
      },
      {
        "name": "automation_rule_id",
        "in": "query",
        "required": false,
        "description": "Filter executions by parent automation rule UUID.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Filter executions by parent automation rule UUID."
        }
      },
      {
        "name": "status",
        "in": "query",
        "required": false,
        "description": "Filter by execution status.",
        "schema": {
          "type": "string",
          "enum": [
            "pending",
            "running",
            "completed",
            "failed",
            "cancelled",
            "timeout",
            "skipped"
          ],
          "description": "Filter by execution status."
        }
      },
      {
        "name": "started_from",
        "in": "query",
        "required": false,
        "description": "Filter executions started at or after this timestamp.",
        "schema": {
          "type": "string",
          "format": "date-time",
          "description": "Filter executions started at or after this timestamp."
        }
      },
      {
        "name": "started_to",
        "in": "query",
        "required": false,
        "description": "Filter executions started at or before this timestamp.",
        "schema": {
          "type": "string",
          "format": "date-time",
          "description": "Filter executions started at or before this timestamp."
        }
      },
      {
        "name": "duration_min_ms",
        "in": "query",
        "required": false,
        "description": "Minimum execution duration in milliseconds.",
        "schema": {
          "type": "number",
          "minimum": 0,
          "description": "Minimum execution duration in milliseconds."
        }
      },
      {
        "name": "duration_max_ms",
        "in": "query",
        "required": false,
        "description": "Maximum execution duration in milliseconds.",
        "schema": {
          "type": "number",
          "minimum": 0,
          "description": "Maximum execution duration in milliseconds."
        }
      },
      {
        "name": "has_errors",
        "in": "query",
        "required": false,
        "description": "Filter by whether the execution has errors; transformed to boolean by validation.",
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ],
          "description": "Filter by whether the execution has errors; transformed to boolean by validation."
        }
      },
      {
        "name": "trigger_type",
        "in": "query",
        "required": false,
        "description": "Filter by automation trigger type.",
        "schema": {
          "type": "string",
          "enum": [
            "time_based",
            "event_based",
            "condition_based",
            "manual",
            "recurring",
            "webhook"
          ],
          "description": "Filter by automation trigger type."
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "type": "array",
          "items": {
            "$ref": "#/components/schemas/AutomationExecution"
          },
          "description": "Automation execution rows. Current service code wraps the DB result array in another array; this schema documents the intended flat shape returned by createPaginatedResponse."
        },
        "pagination": {
          "$ref": "#/components/schemas/AutomationPagination"
        },
        "meta": {
          "type": "object",
          "properties": {
            "filters": {
              "type": "object",
              "additionalProperties": {},
              "description": "Validated filters echoed by the controller."
            },
            "resource": {
              "type": "string",
              "enum": [
                "automation_execution"
              ],
              "description": "Resource name supplied by the controller."
            }
          }
        }
      },
      "required": [
        "data",
        "pagination"
      ]
    }
  },
  {
    "id": "get-_api_v1_automation_executions_id",
    "method": "get",
    "path": "/api/v1/automation/executions/{id}",
    "displayName": "Get automation execution",
    "summary": "Get automation execution",
    "description": "Returns one automation execution by execution_id for the authenticated tenant, with HATEOAS links to the parent rule and retry endpoint when the status is failed. Authentication uses x-api-key with optional x-tenant-id; the controller validates the API key, resolves tenant context, validates the UUID path parameter, and requires automation:read permission. The service scopes lookup by execution_id and tenant. Missing executions currently throw a generic Error and may surface as 500 rather than 404.",
    "tags": [
      "Automation"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Automation execution UUID from automation_executions.execution_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Automation execution UUID from automation_executions.execution_id."
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "$ref": "#/components/schemas/AutomationExecution"
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "post-_api_v1_automation_executions_id_retry",
    "method": "post",
    "path": "/api/v1/automation/executions/{id}/retry",
    "displayName": "Retry automation execution",
    "summary": "Retry automation execution",
    "description": "Retries a failed automation execution. The controller authenticates with x-api-key, requires automation:execute permission, validates the execution UUID, resets a failed execution to pending, clears completion/error counters, queues the execution, publishes automation.execution.retried, and returns the updated execution with links. The service only allows status=failed; missing executions and non-failed executions currently throw generic Errors and may surface as 500 rather than 404 or 400. The queueExecution helper is currently a stub.",
    "tags": [
      "Automation"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Automation execution UUID from automation_executions.execution_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Automation execution UUID from automation_executions.execution_id."
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "$ref": "#/components/schemas/AutomationExecution"
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_automation_rules",
    "method": "get",
    "path": "/api/v1/automation/rules",
    "displayName": "List automation rules",
    "summary": "List automation rules",
    "description": "Returns a paginated list of automation rules scoped to the authenticated tenant. Authentication uses x-api-key with optional x-tenant-id, then RBAC requires automation:read. The controller validates query params with automationRulesListSchema, parses page/limit from the URL, and the service enforces tenant filtering on automation_rules.",
    "tags": [
      "Automation"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "page",
        "in": "query",
        "required": false,
        "description": "Page number as a query string. Defaults to 1.",
        "schema": {
          "type": "string",
          "description": "Page number as a query string. Defaults to 1."
        }
      },
      {
        "name": "limit",
        "in": "query",
        "required": false,
        "description": "Page size as a query string. Must parse to 1 through 100; defaults to 25.",
        "schema": {
          "type": "string",
          "description": "Page size as a query string. Must parse to 1 through 100; defaults to 25."
        }
      },
      {
        "name": "sort",
        "in": "query",
        "required": false,
        "description": "Accepted by shared list query validation; service currently orders rules by created_at desc.",
        "schema": {
          "type": "string",
          "description": "Accepted by shared list query validation; service currently orders rules by created_at desc."
        }
      },
      {
        "name": "order",
        "in": "query",
        "required": false,
        "description": "Accepted by shared list query validation.",
        "schema": {
          "type": "string",
          "enum": [
            "asc",
            "desc"
          ],
          "description": "Accepted by shared list query validation."
        }
      },
      {
        "name": "search",
        "in": "query",
        "required": false,
        "description": "Accepted by shared filter validation.",
        "schema": {
          "type": "string",
          "description": "Accepted by shared filter validation."
        }
      },
      {
        "name": "created_from",
        "in": "query",
        "required": false,
        "description": "Accepted by shared filter validation.",
        "schema": {
          "type": "string",
          "format": "date-time",
          "description": "Accepted by shared filter validation."
        }
      },
      {
        "name": "created_to",
        "in": "query",
        "required": false,
        "description": "Accepted by shared filter validation.",
        "schema": {
          "type": "string",
          "format": "date-time",
          "description": "Accepted by shared filter validation."
        }
      },
      {
        "name": "updated_from",
        "in": "query",
        "required": false,
        "description": "Accepted by shared filter validation.",
        "schema": {
          "type": "string",
          "format": "date-time",
          "description": "Accepted by shared filter validation."
        }
      },
      {
        "name": "updated_to",
        "in": "query",
        "required": false,
        "description": "Accepted by shared filter validation.",
        "schema": {
          "type": "string",
          "format": "date-time",
          "description": "Accepted by shared filter validation."
        }
      },
      {
        "name": "is_active",
        "in": "query",
        "required": false,
        "description": "Accepted by shared filter validation and transformed to boolean.",
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ],
          "description": "Accepted by shared filter validation and transformed to boolean."
        }
      },
      {
        "name": "name",
        "in": "query",
        "required": false,
        "description": "Optional rule name filter.",
        "schema": {
          "type": "string",
          "description": "Optional rule name filter."
        }
      },
      {
        "name": "status",
        "in": "query",
        "required": false,
        "description": "Filter by automation rule status.",
        "schema": {
          "type": "string",
          "enum": [
            "active",
            "inactive",
            "draft",
            "error"
          ],
          "description": "Filter by automation rule status."
        }
      },
      {
        "name": "trigger_type",
        "in": "query",
        "required": false,
        "description": "Filter by trigger type.",
        "schema": {
          "type": "string",
          "enum": [
            "time_based",
            "event_based",
            "condition_based",
            "manual",
            "recurring",
            "webhook"
          ],
          "description": "Filter by trigger type."
        }
      },
      {
        "name": "priority",
        "in": "query",
        "required": false,
        "description": "Filter by priority level.",
        "schema": {
          "type": "string",
          "enum": [
            "low",
            "normal",
            "high",
            "critical"
          ],
          "description": "Filter by priority level."
        }
      },
      {
        "name": "template_category",
        "in": "query",
        "required": false,
        "description": "Filter template category.",
        "schema": {
          "type": "string",
          "description": "Filter template category."
        }
      },
      {
        "name": "created_by",
        "in": "query",
        "required": false,
        "description": "Filter by creator user UUID from automation_rules.created_by.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Filter by creator user UUID from automation_rules.created_by."
        }
      },
      {
        "name": "last_executed_from",
        "in": "query",
        "required": false,
        "description": "Filter for rules last executed at or after timestamp.",
        "schema": {
          "type": "string",
          "format": "date-time",
          "description": "Filter for rules last executed at or after timestamp."
        }
      },
      {
        "name": "last_executed_to",
        "in": "query",
        "required": false,
        "description": "Filter for rules last executed at or before timestamp.",
        "schema": {
          "type": "string",
          "format": "date-time",
          "description": "Filter for rules last executed at or before timestamp."
        }
      },
      {
        "name": "execution_count_min",
        "in": "query",
        "required": false,
        "description": "Minimum execution count filter.",
        "schema": {
          "type": "integer",
          "minimum": 0,
          "description": "Minimum execution count filter."
        }
      },
      {
        "name": "execution_count_max",
        "in": "query",
        "required": false,
        "description": "Maximum execution count filter.",
        "schema": {
          "type": "integer",
          "minimum": 0,
          "description": "Maximum execution count filter."
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "type": "array",
          "items": {
            "$ref": "#/components/schemas/AutomationRule"
          }
        },
        "pagination": {
          "$ref": "#/components/schemas/AutomationPagination"
        },
        "meta": {
          "type": "object",
          "properties": {
            "filters": {
              "type": "object",
              "additionalProperties": {}
            },
            "resource": {
              "type": "string",
              "enum": [
                "automation_rule"
              ]
            }
          }
        }
      },
      "required": [
        "data",
        "pagination"
      ]
    }
  },
  {
    "id": "post-_api_v1_automation_rules",
    "method": "post",
    "path": "/api/v1/automation/rules",
    "displayName": "Create automation rule",
    "summary": "Create automation rule",
    "description": "Creates a tenant-scoped automation rule in automation_rules. Authentication uses x-api-key with optional x-tenant-id; RBAC requires automation:create. The controller validates request body via createAutomationRuleSchema, and the service validates trigger/action config, inserts the rule with crypto.randomUUID generated rule_id, and emits automation.rule.created + audit log events.",
    "tags": [
      "Automation"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "name": {
          "type": "string",
          "minLength": 1,
          "maxLength": 255
        },
        "description": {
          "type": "string"
        },
        "status": {
          "type": "string",
          "enum": [
            "active",
            "inactive",
            "draft",
            "error"
          ],
          "description": "Defaults to draft when omitted."
        },
        "priority": {
          "type": "string",
          "enum": [
            "low",
            "normal",
            "high",
            "critical"
          ],
          "description": "Defaults to normal when omitted."
        },
        "trigger_type": {
          "type": "string",
          "enum": [
            "time_based",
            "event_based",
            "condition_based",
            "manual",
            "recurring",
            "webhook"
          ]
        },
        "trigger_config": {
          "type": "object",
          "additionalProperties": {},
          "description": "Trigger-type-specific configuration object."
        },
        "conditions": {
          "type": "array",
          "items": {
            "$ref": "#/components/schemas/AutomationRuleCondition"
          }
        },
        "condition_logic": {
          "type": "string",
          "enum": [
            "and",
            "or"
          ]
        },
        "actions": {
          "type": "array",
          "items": {
            "$ref": "#/components/schemas/AutomationRuleAction"
          },
          "minItems": 1
        },
        "max_concurrent_executions": {
          "type": "integer",
          "minimum": 1
        },
        "execution_timeout_minutes": {
          "type": "integer",
          "minimum": 1
        },
        "retry_failed_executions": {
          "type": "boolean"
        },
        "is_template": {
          "type": "boolean"
        },
        "template_category": {
          "type": "string"
        },
        "tags": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "metadata": {
          "type": "object",
          "additionalProperties": {}
        },
        "notification_settings": {
          "$ref": "#/components/schemas/AutomationNotificationSettings"
        }
      },
      "required": [
        "name",
        "trigger_type",
        "trigger_config",
        "actions"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "$ref": "#/components/schemas/AutomationRule"
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_automation_rules_id",
    "method": "get",
    "path": "/api/v1/automation/rules/{id}",
    "displayName": "Get automation rule",
    "summary": "Get automation rule",
    "description": "Returns one automation rule by rule_id for the authenticated tenant with generated links and execution statistics. Authentication uses x-api-key with optional x-tenant-id; RBAC requires automation:read. The service scopes by {rule_id, tenant}. Missing rules currently throw generic Error and surface as 500 rather than 404.",
    "tags": [
      "Automation"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Automation rule UUID from automation_rules.rule_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Automation rule UUID from automation_rules.rule_id."
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "$ref": "#/components/schemas/AutomationRule"
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "put-_api_v1_automation_rules_id",
    "method": "put",
    "path": "/api/v1/automation/rules/{id}",
    "displayName": "Update automation rule",
    "summary": "Update automation rule",
    "description": "Updates an automation rule by rule_id for the authenticated tenant. Authentication uses x-api-key with optional x-tenant-id; RBAC requires automation:update. The controller validates partial updates with updateAutomationRuleSchema and the service revalidates trigger/action config when changed, updates automation_rules, and emits automation.rule.updated + audit log events. Missing rules currently surface as 500.",
    "tags": [
      "Automation"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Automation rule UUID from automation_rules.rule_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Automation rule UUID from automation_rules.rule_id."
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "name": {
          "type": "string",
          "minLength": 1,
          "maxLength": 255
        },
        "description": {
          "type": "string"
        },
        "status": {
          "type": "string",
          "enum": [
            "active",
            "inactive",
            "draft",
            "error"
          ],
          "description": "Defaults to draft when omitted."
        },
        "priority": {
          "type": "string",
          "enum": [
            "low",
            "normal",
            "high",
            "critical"
          ],
          "description": "Defaults to normal when omitted."
        },
        "trigger_type": {
          "type": "string",
          "enum": [
            "time_based",
            "event_based",
            "condition_based",
            "manual",
            "recurring",
            "webhook"
          ]
        },
        "trigger_config": {
          "type": "object",
          "additionalProperties": {},
          "description": "Trigger-type-specific configuration object."
        },
        "conditions": {
          "type": "array",
          "items": {
            "$ref": "#/components/schemas/AutomationRuleCondition"
          }
        },
        "condition_logic": {
          "type": "string",
          "enum": [
            "and",
            "or"
          ]
        },
        "actions": {
          "type": "array",
          "items": {
            "$ref": "#/components/schemas/AutomationRuleAction"
          },
          "minItems": 1
        },
        "max_concurrent_executions": {
          "type": "integer",
          "minimum": 1
        },
        "execution_timeout_minutes": {
          "type": "integer",
          "minimum": 1
        },
        "retry_failed_executions": {
          "type": "boolean"
        },
        "is_template": {
          "type": "boolean"
        },
        "template_category": {
          "type": "string"
        },
        "tags": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "metadata": {
          "type": "object",
          "additionalProperties": {}
        },
        "notification_settings": {
          "$ref": "#/components/schemas/AutomationNotificationSettings"
        }
      }
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "$ref": "#/components/schemas/AutomationRule"
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "delete-_api_v1_automation_rules_id",
    "method": "delete",
    "path": "/api/v1/automation/rules/{id}",
    "displayName": "Delete automation rule",
    "summary": "Delete automation rule",
    "description": "Deletes one automation rule by rule_id for the authenticated tenant. Authentication uses x-api-key with optional x-tenant-id; RBAC requires automation:delete. The service blocks deletion when pending/running executions exist, unschedules active rules, deletes automation_rules row, and emits automation.rule.deleted + audit log events. Missing rules and delete constraints currently bubble as 500 errors.",
    "tags": [
      "Automation"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Automation rule UUID from automation_rules.rule_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Automation rule UUID from automation_rules.rule_id."
        }
      }
    ]
  },
  {
    "id": "post-_api_v1_automation_rules_id_execute",
    "method": "post",
    "path": "/api/v1/automation/rules/{id}/execute",
    "displayName": "Execute automation rule manually",
    "summary": "Execute automation rule manually",
    "description": "Starts a manual execution for one automation rule identified by path rule_id. Authentication uses x-api-key with optional x-tenant-id; RBAC requires automation:execute. The current request schema requires automation_rule_id in the body, but controller/service execute the path rule ID and do not cross-check the body ID. For dry_run=false the service creates automation_executions row and queues execution via a currently stubbed queue helper.",
    "tags": [
      "Automation"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Automation rule UUID from automation_rules.rule_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Automation rule UUID from automation_rules.rule_id."
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "automation_rule_id": {
          "type": "string",
          "format": "uuid",
          "description": "Required by current validation schema but ignored by controller/service, which execute the path rule ID."
        },
        "execution_data": {
          "type": "object",
          "additionalProperties": {}
        },
        "override_conditions": {
          "type": "boolean",
          "description": "Set true to allow execution of inactive rules."
        },
        "dry_run": {
          "type": "boolean",
          "description": "When true, returns a completed execution without queueing actions."
        }
      },
      "required": [
        "automation_rule_id"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "$ref": "#/components/schemas/AutomationExecution"
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "post-_api_v1_automation_rules_bulkstatus",
    "method": "post",
    "path": "/api/v1/automation/rules/bulk-status",
    "displayName": "Bulk update automation rule status",
    "summary": "Bulk update automation rule status",
    "description": "Updates status for up to 100 automation rules under the authenticated tenant. Authentication uses x-api-key with optional x-tenant-id; RBAC requires automation:update. The controller validates ids/status with bulkStatusUpdateSchema and calls updateAutomationRule per id. Failures are collected into an errors array and still return HTTP 200 with partial-success details.",
    "tags": [
      "Automation"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "ids": {
          "type": "array",
          "items": {
            "type": "string",
            "format": "uuid"
          },
          "minItems": 1,
          "maxItems": 100,
          "description": "Rule UUIDs from automation_rules.rule_id."
        },
        "status": {
          "type": "string",
          "enum": [
            "active",
            "inactive",
            "draft",
            "error"
          ],
          "description": "Status to apply to each provided rule id."
        }
      },
      "required": [
        "ids",
        "status"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "type": "object",
          "properties": {
            "action": {
              "type": "string",
              "enum": [
                "bulk_status_update"
              ]
            },
            "status": {
              "type": "string",
              "enum": [
                "active",
                "inactive",
                "draft",
                "error"
              ]
            },
            "rule_ids": {
              "type": "array",
              "items": {
                "type": "string",
                "format": "uuid"
              }
            },
            "updated": {
              "type": "integer",
              "minimum": 0
            },
            "errors": {
              "type": "array",
              "items": {
                "type": "string"
              },
              "description": "Per-rule failures emitted as `<ruleId>: <error message>` entries."
            },
            "message": {
              "type": "string"
            }
          },
          "required": [
            "action",
            "status",
            "rule_ids",
            "updated",
            "errors",
            "message"
          ]
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "post-_api_v1_automation_rules_bulkexecute",
    "method": "post",
    "path": "/api/v1/automation/rules/bulk-execute",
    "displayName": "Bulk execute automation rules",
    "summary": "Bulk execute automation rules",
    "description": "Starts execution attempts for up to 20 automation rules for the authenticated tenant. Authentication uses x-api-key with optional x-tenant-id; RBAC requires automation:execute. The controller validates bulkExecutionSchema and calls executeAutomationRule per id. sequential_execution=true runs serially; otherwise Promise.all is used. Per-rule errors are returned in a 200 response.",
    "tags": [
      "Automation"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "automation_rule_ids": {
          "type": "array",
          "items": {
            "type": "string",
            "format": "uuid"
          },
          "minItems": 1,
          "maxItems": 20,
          "description": "Rule UUIDs to execute."
        },
        "execution_data": {
          "type": "object",
          "additionalProperties": {},
          "description": "Optional shared execution payload for each run."
        },
        "override_conditions": {
          "type": "boolean",
          "description": "Allow execution of inactive rules when true."
        },
        "sequential_execution": {
          "type": "boolean",
          "description": "When true, executes rules sequentially; otherwise Promise.all is used."
        }
      },
      "required": [
        "automation_rule_ids"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "type": "object",
          "properties": {
            "action": {
              "type": "string",
              "enum": [
                "bulk_execute"
              ]
            },
            "rule_ids": {
              "type": "array",
              "items": {
                "type": "string",
                "format": "uuid"
              }
            },
            "started": {
              "type": "integer",
              "minimum": 0
            },
            "errors": {
              "type": "array",
              "items": {
                "type": "string"
              },
              "description": "Per-rule failures emitted as `<ruleId>: <error message>` entries."
            },
            "sequential": {
              "type": "boolean"
            },
            "message": {
              "type": "string"
            }
          },
          "required": [
            "action",
            "rule_ids",
            "started",
            "errors",
            "message"
          ]
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_automation_templates",
    "method": "get",
    "path": "/api/v1/automation/templates",
    "displayName": "List automation templates",
    "summary": "List automation templates",
    "description": "Returns a paginated list of automation templates for the authenticated tenant. Authentication uses x-api-key with optional x-tenant-id; RBAC requires automation:read. The controller validates query params with templatesListSchema and the service filters automation_templates by tenant. Current service code wraps template array before createPaginatedResponse, which can produce nested data in practice.",
    "tags": [
      "Automation"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "page",
        "in": "query",
        "required": false,
        "description": "Page number as a query string. Defaults to 1.",
        "schema": {
          "type": "string",
          "description": "Page number as a query string. Defaults to 1."
        }
      },
      {
        "name": "limit",
        "in": "query",
        "required": false,
        "description": "Page size as a query string. Must parse to 1 through 100; defaults to 25.",
        "schema": {
          "type": "string",
          "description": "Page size as a query string. Must parse to 1 through 100; defaults to 25."
        }
      },
      {
        "name": "sort",
        "in": "query",
        "required": false,
        "description": "Accepted by shared list query validation; service currently orders templates by created_at desc.",
        "schema": {
          "type": "string",
          "description": "Accepted by shared list query validation; service currently orders templates by created_at desc."
        }
      },
      {
        "name": "order",
        "in": "query",
        "required": false,
        "description": "Accepted by shared list query validation.",
        "schema": {
          "type": "string",
          "enum": [
            "asc",
            "desc"
          ],
          "description": "Accepted by shared list query validation."
        }
      },
      {
        "name": "search",
        "in": "query",
        "required": false,
        "description": "Accepted by shared filter validation.",
        "schema": {
          "type": "string",
          "description": "Accepted by shared filter validation."
        }
      },
      {
        "name": "created_from",
        "in": "query",
        "required": false,
        "description": "Accepted by shared filter validation.",
        "schema": {
          "type": "string",
          "format": "date-time",
          "description": "Accepted by shared filter validation."
        }
      },
      {
        "name": "created_to",
        "in": "query",
        "required": false,
        "description": "Accepted by shared filter validation.",
        "schema": {
          "type": "string",
          "format": "date-time",
          "description": "Accepted by shared filter validation."
        }
      },
      {
        "name": "updated_from",
        "in": "query",
        "required": false,
        "description": "Accepted by shared filter validation.",
        "schema": {
          "type": "string",
          "format": "date-time",
          "description": "Accepted by shared filter validation."
        }
      },
      {
        "name": "updated_to",
        "in": "query",
        "required": false,
        "description": "Accepted by shared filter validation.",
        "schema": {
          "type": "string",
          "format": "date-time",
          "description": "Accepted by shared filter validation."
        }
      },
      {
        "name": "is_active",
        "in": "query",
        "required": false,
        "description": "Accepted by shared filter validation and transformed to boolean.",
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ],
          "description": "Accepted by shared filter validation and transformed to boolean."
        }
      },
      {
        "name": "category",
        "in": "query",
        "required": false,
        "description": "Filter templates by category.",
        "schema": {
          "type": "string",
          "description": "Filter templates by category."
        }
      },
      {
        "name": "compatible_version",
        "in": "query",
        "required": false,
        "description": "Filter templates by compatibility version tag.",
        "schema": {
          "type": "string",
          "description": "Filter templates by compatibility version tag."
        }
      },
      {
        "name": "author",
        "in": "query",
        "required": false,
        "description": "Filter templates by author/user id value saved on the template.",
        "schema": {
          "type": "string",
          "description": "Filter templates by author/user id value saved on the template."
        }
      },
      {
        "name": "usage_count_min",
        "in": "query",
        "required": false,
        "description": "Minimum usage_count filter.",
        "schema": {
          "type": "integer",
          "minimum": 0,
          "description": "Minimum usage_count filter."
        }
      },
      {
        "name": "usage_count_max",
        "in": "query",
        "required": false,
        "description": "Maximum usage_count filter.",
        "schema": {
          "type": "integer",
          "minimum": 0,
          "description": "Maximum usage_count filter."
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "type": "array",
          "items": {
            "$ref": "#/components/schemas/AutomationTemplate"
          },
          "description": "Template rows. Current service code wraps the DB result array in another array before createPaginatedResponse, which can produce nested data in practice."
        },
        "pagination": {
          "$ref": "#/components/schemas/AutomationPagination"
        },
        "meta": {
          "type": "object",
          "properties": {
            "filters": {
              "type": "object",
              "additionalProperties": {}
            },
            "resource": {
              "type": "string",
              "enum": [
                "automation_template"
              ]
            }
          }
        }
      },
      "required": [
        "data",
        "pagination"
      ]
    }
  },
  {
    "id": "post-_api_v1_automation_templates",
    "method": "post",
    "path": "/api/v1/automation/templates",
    "displayName": "Create automation template from rule",
    "summary": "Create automation template from rule",
    "description": "Creates a template row by copying one source automation rule into automation_templates.template_config. Authentication uses x-api-key with optional x-tenant-id; RBAC requires automation:create. The controller validates createTemplateFromRuleSchema and service emits automation.template.created + audit log events. Missing source rules currently throw generic Error and surface as 500.",
    "tags": [
      "Automation"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "automation_rule_id": {
          "type": "string",
          "format": "uuid",
          "description": "Source automation_rules.rule_id copied into template_config."
        },
        "template_name": {
          "type": "string",
          "minLength": 1,
          "maxLength": 255
        },
        "template_description": {
          "type": "string"
        },
        "category": {
          "type": "string",
          "minLength": 1
        },
        "template_variables": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "rule_field_path": {
                "type": "string",
                "minLength": 1
              },
              "variable_name": {
                "type": "string",
                "minLength": 1
              },
              "display_name": {
                "type": "string",
                "minLength": 1
              },
              "description": {
                "type": "string"
              },
              "type": {
                "type": "string",
                "enum": [
                  "string",
                  "number",
                  "boolean",
                  "date",
                  "select",
                  "multiselect"
                ]
              },
              "required": {
                "type": "boolean"
              }
            },
            "required": [
              "rule_field_path",
              "variable_name",
              "display_name",
              "type"
            ]
          }
        }
      },
      "required": [
        "automation_rule_id",
        "template_name",
        "category"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "$ref": "#/components/schemas/AutomationTemplate"
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_automation_templates_id",
    "method": "get",
    "path": "/api/v1/automation/templates/{id}",
    "displayName": "Get automation template",
    "summary": "Get automation template",
    "description": "Returns one automation template by template_id for the authenticated tenant. Authentication uses x-api-key with optional x-tenant-id; RBAC requires automation:read. Service lookup is scoped by {template_id, tenant}. Missing templates currently throw generic Error and surface as 500 rather than 404.",
    "tags": [
      "Automation"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Automation template UUID from automation_templates.template_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Automation template UUID from automation_templates.template_id."
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "$ref": "#/components/schemas/AutomationTemplate"
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "post-_api_v1_automation_templates_id_use",
    "method": "post",
    "path": "/api/v1/automation/templates/{id}/use",
    "displayName": "Create automation rule from template",
    "summary": "Create automation rule from template",
    "description": "Uses one template_id to create a new automation rule under the authenticated tenant. Authentication uses x-api-key with optional x-tenant-id; RBAC requires automation:create. The controller validates `{ variables }`, then service loads template, applies substitutions into template_config, creates rule via createAutomationRule, and increments automation_templates.usage_count/last_used. Missing templates surface as 500.",
    "tags": [
      "Automation"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Automation template UUID from automation_templates.template_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Automation template UUID from automation_templates.template_id."
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "variables": {
          "type": "object",
          "additionalProperties": {},
          "description": "Optional variable substitutions applied to template_config before creating a new automation rule."
        }
      }
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "$ref": "#/components/schemas/AutomationRule"
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_automation_statistics",
    "method": "get",
    "path": "/api/v1/automation/statistics",
    "displayName": "Get automation statistics",
    "summary": "Get automation statistics",
    "description": "Returns tenant-scoped automation aggregate counts (rules and executions) plus HATEOAS links. Authentication uses x-api-key with optional x-tenant-id; RBAC requires automation:read. The service computes counts from automation_rules and automation_executions plus period-based execution totals and success rate.",
    "tags": [
      "Automation"
    ],
    "approvalRequired": false,
    "parameters": [],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "type": "object",
          "properties": {
            "total_rules": {
              "type": "integer",
              "minimum": 0
            },
            "active_rules": {
              "type": "integer",
              "minimum": 0
            },
            "inactive_rules": {
              "type": "integer",
              "minimum": 0
            },
            "draft_rules": {
              "type": "integer",
              "minimum": 0
            },
            "error_rules": {
              "type": "integer",
              "minimum": 0
            },
            "total_executions": {
              "type": "integer",
              "minimum": 0
            },
            "successful_executions": {
              "type": "integer",
              "minimum": 0
            },
            "failed_executions": {
              "type": "integer",
              "minimum": 0
            },
            "executions_today": {
              "type": "integer",
              "minimum": 0
            },
            "executions_this_week": {
              "type": "integer",
              "minimum": 0
            },
            "executions_this_month": {
              "type": "integer",
              "minimum": 0
            },
            "avg_execution_time_ms": {
              "type": "number",
              "minimum": 0
            },
            "success_rate_percent": {
              "type": "number",
              "minimum": 0,
              "maximum": 100
            },
            "_links": {
              "type": "object",
              "properties": {
                "self": {
                  "type": "string",
                  "enum": [
                    "/api/v1/automation/statistics"
                  ]
                },
                "rules": {
                  "type": "string",
                  "enum": [
                    "/api/v1/automation/rules"
                  ]
                },
                "executions": {
                  "type": "string",
                  "enum": [
                    "/api/v1/automation/executions"
                  ]
                },
                "templates": {
                  "type": "string",
                  "enum": [
                    "/api/v1/automation/templates"
                  ]
                },
                "performance": {
                  "type": "string",
                  "enum": [
                    "/api/v1/automation/performance"
                  ]
                }
              },
              "required": [
                "self",
                "rules",
                "executions",
                "templates",
                "performance"
              ]
            }
          },
          "required": [
            "total_rules",
            "active_rules",
            "inactive_rules",
            "draft_rules",
            "error_rules",
            "total_executions",
            "successful_executions",
            "failed_executions",
            "executions_today",
            "executions_this_week",
            "executions_this_month"
          ]
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_automation_performance",
    "method": "get",
    "path": "/api/v1/automation/performance",
    "displayName": "Get automation performance metrics",
    "summary": "Get automation performance metrics",
    "description": "Returns performance metrics calculated by AutomationService.calculatePerformanceMetrics for the authenticated tenant. Authentication uses x-api-key with optional x-tenant-id; RBAC requires automation:read. Query is validated with performanceMetricsRequestSchema; because validateQueryParams maps URL values to strings, array filters (rule_ids, metrics) currently have parsing limitations and may fail validation unless encoded specially.",
    "tags": [
      "Automation"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "date_from",
        "in": "query",
        "required": false,
        "description": "Optional lower bound for performance window.",
        "schema": {
          "type": "string",
          "format": "date-time",
          "description": "Optional lower bound for performance window."
        }
      },
      {
        "name": "date_to",
        "in": "query",
        "required": false,
        "description": "Optional upper bound for performance window.",
        "schema": {
          "type": "string",
          "format": "date-time",
          "description": "Optional upper bound for performance window."
        }
      },
      {
        "name": "group_by",
        "in": "query",
        "required": false,
        "description": "Aggregation bucket size; defaults to day.",
        "schema": {
          "type": "string",
          "enum": [
            "hour",
            "day",
            "week",
            "month"
          ],
          "description": "Aggregation bucket size; defaults to day."
        }
      },
      {
        "name": "rule_ids",
        "in": "query",
        "required": false,
        "description": "Raw query value copied from URL. The controller expects an array UUID schema but validateQueryParams passes string values, so array filters currently require custom caller-side encoding or fail validation.",
        "schema": {
          "type": "string",
          "description": "Raw query value copied from URL. The controller expects an array UUID schema but validateQueryParams passes string values, so array filters currently require custom caller-side encoding or fail validation."
        }
      },
      {
        "name": "metrics",
        "in": "query",
        "required": false,
        "description": "Raw query value copied from URL. The controller expects an array enum schema but validateQueryParams passes string values, so array filters currently require custom caller-side encoding or fail validation.",
        "schema": {
          "type": "string",
          "description": "Raw query value copied from URL. The controller expects an array enum schema but validateQueryParams passes string values, so array filters currently require custom caller-side encoding or fail validation."
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "allOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "object",
              "properties": {
                "_links": {
                  "type": "object",
                  "properties": {
                    "self": {
                      "type": "string",
                      "enum": [
                        "/api/v1/automation/performance"
                      ]
                    },
                    "statistics": {
                      "type": "string",
                      "enum": [
                        "/api/v1/automation/statistics"
                      ]
                    }
                  },
                  "required": [
                    "self",
                    "statistics"
                  ]
                }
              }
            }
          ],
          "description": "Performance payload from AutomationService.calculatePerformanceMetrics plus links."
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_automation_meta",
    "method": "get",
    "path": "/api/v1/automation/meta",
    "displayName": "Get automation metadata",
    "summary": "Get automation metadata",
    "description": "Returns a static reference catalog of automation enum values: trigger types, action types, rule statuses, execution statuses, priority levels, and condition operators. Authentication uses x-api-key with optional x-tenant-id; the controller validates the API key, resolves tenant context, and requires automation:read permission. The response is hardcoded and performs no service or database lookup beyond authentication/RBAC.",
    "tags": [
      "Automation"
    ],
    "approvalRequired": false,
    "parameters": [],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "type": "object",
          "properties": {
            "trigger_types": {
              "type": "array",
              "items": {
                "type": "string",
                "enum": [
                  "time_based",
                  "event_based",
                  "condition_based",
                  "manual",
                  "recurring",
                  "webhook"
                ]
              },
              "description": "Valid automation trigger types."
            },
            "action_types": {
              "type": "array",
              "items": {
                "type": "string",
                "enum": [
                  "email_notification",
                  "sms_notification",
                  "webhook_call",
                  "database_update",
                  "ticket_creation",
                  "ticket_update",
                  "project_update",
                  "time_entry_creation",
                  "invoice_generation",
                  "custom_script",
                  "workflow_execution",
                  "system_command"
                ]
              },
              "description": "Valid automation action types."
            },
            "rule_statuses": {
              "type": "array",
              "items": {
                "type": "string",
                "enum": [
                  "active",
                  "inactive",
                  "draft",
                  "error"
                ]
              },
              "description": "Valid automation rule statuses."
            },
            "execution_statuses": {
              "type": "array",
              "items": {
                "type": "string",
                "enum": [
                  "pending",
                  "running",
                  "completed",
                  "failed",
                  "cancelled",
                  "timeout",
                  "skipped"
                ]
              },
              "description": "Valid automation execution statuses."
            },
            "priority_levels": {
              "type": "array",
              "items": {
                "type": "string",
                "enum": [
                  "low",
                  "normal",
                  "high",
                  "critical"
                ]
              },
              "description": "Valid automation priority levels."
            },
            "condition_operators": {
              "type": "array",
              "items": {
                "type": "string",
                "enum": [
                  "equals",
                  "not_equals",
                  "greater_than",
                  "less_than",
                  "greater_than_or_equal",
                  "less_than_or_equal",
                  "contains",
                  "not_contains",
                  "starts_with",
                  "ends_with",
                  "in",
                  "not_in",
                  "exists",
                  "not_exists",
                  "regex_match"
                ]
              },
              "description": "Valid condition operators."
            }
          },
          "required": [
            "trigger_types",
            "action_types",
            "rule_statuses",
            "execution_statuses",
            "priority_levels",
            "condition_operators"
          ]
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_billing_licencecount",
    "method": "get",
    "path": "/api/billing/licence-count",
    "displayName": "Get tenant licence usage",
    "summary": "Get tenant licence usage",
    "description": "Server-to-server webhook endpoint used by the billing service to query current licence usage for a tenant. The caller supplies tenant_id and an x-webhook-signature header containing HMAC-SHA256(\"GET:<tenant_id>\", ALGA_WEBHOOK_SECRET). The response reports the configured licensed internal-user limit, active internal-user count, calculated remaining seats, and last licence update timestamp.",
    "tags": [
      "Billing"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "tenant_id",
        "in": "query",
        "required": true,
        "description": "Tenant identifier to query. This must match a tenants.tenant record.",
        "schema": {
          "type": "string",
          "description": "Tenant identifier to query. This must match a tenants.tenant record."
        }
      },
      {
        "name": "x-webhook-signature",
        "in": "header",
        "required": true,
        "description": "HMAC-SHA256 hex digest proving the caller knows ALGA_WEBHOOK_SECRET.",
        "schema": {
          "type": "string",
          "description": "HMAC-SHA256 hex digest proving the caller knows ALGA_WEBHOOK_SECRET."
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "tenant_id": {
          "type": "string",
          "description": "Echoed tenant identifier from the request."
        },
        "limit": {
          "type": [
            "integer",
            "null"
          ],
          "description": "Licensed internal-user count from tenants.licensed_user_count. Null means unlimited."
        },
        "used": {
          "type": "integer",
          "description": "Count of active internal users where users.user_type is internal and is_inactive is false."
        },
        "remaining": {
          "type": [
            "integer",
            "null"
          ],
          "description": "Calculated remaining seats as max(0, limit - used), or null when limit is unlimited."
        },
        "last_updated": {
          "type": [
            "string",
            "null"
          ],
          "description": "ISO timestamp from tenants.last_license_update, or null if no license update has been recorded."
        }
      },
      "required": [
        "tenant_id",
        "limit",
        "used",
        "remaining",
        "last_updated"
      ]
    }
  },
  {
    "id": "post-_api_billing_licencecount",
    "method": "post",
    "path": "/api/billing/licence-count",
    "displayName": "Update tenant licensed user count",
    "summary": "Update tenant licensed user count",
    "description": "Server-to-server webhook endpoint used by the billing service to synchronize a tenant's licensed internal-user count from a Stripe subscription quantity. The x-webhook-signature header must be the HMAC-SHA256 hex digest of the raw JSON request body using ALGA_WEBHOOK_SECRET. When event_id is provided, the handler treats tenants.stripe_event_id as an idempotency marker and skips duplicate Stripe events.",
    "tags": [
      "Billing"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "x-webhook-signature",
        "in": "header",
        "required": true,
        "description": "HMAC-SHA256 hex digest proving the caller knows ALGA_WEBHOOK_SECRET.",
        "schema": {
          "type": "string",
          "description": "HMAC-SHA256 hex digest proving the caller knows ALGA_WEBHOOK_SECRET."
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "tenant_id": {
          "type": "string",
          "description": "Tenant identifier from tenants.tenant whose licensed user count should be updated."
        },
        "license_count": {
          "type": "integer",
          "minimum": 0,
          "description": "Licensed internal-user count from the Stripe subscription quantity."
        },
        "event_id": {
          "type": "string",
          "description": "Stripe webhook event ID. When supplied, the handler uses tenants.stripe_event_id for idempotency."
        }
      },
      "required": [
        "tenant_id",
        "license_count"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "success": {
          "type": "boolean",
          "enum": [
            true
          ],
          "description": "Indicates the license count update was accepted."
        },
        "tenant_id": {
          "type": "string",
          "description": "Echoed tenant identifier that was updated."
        },
        "license_count": {
          "type": "integer",
          "description": "Echoed licensed user count that was written."
        },
        "updated_at": {
          "type": "string",
          "format": "date-time",
          "description": "ISO timestamp generated by the handler for this response."
        }
      },
      "required": [
        "success",
        "tenant_id",
        "license_count",
        "updated_at"
      ]
    }
  },
  {
    "id": "post-_api_chat_stream_title",
    "method": "post",
    "path": "/api/chat/stream/title",
    "displayName": "Generate chat title stream",
    "summary": "Generate chat title stream",
    "description": "Enterprise-only AI endpoint that generates a short title from conversation messages. Requires a valid Auth.js session and the aiAssistant experimental feature enabled for the tenant. The handler sends the messages to OpenRouter and returns Server-Sent Events; the implementation emits a generated title event and a completion event rather than a conventional JSON response.",
    "tags": [
      "Chat"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "inputs": {
          "type": "array",
          "items": {
            "$ref": "#/components/schemas/ChatMessage"
          },
          "minItems": 1,
          "description": "Conversation messages used as context for generating a short chat title."
        }
      },
      "required": [
        "inputs"
      ]
    }
  },
  {
    "id": "get-_api_chat_stream_slug",
    "method": "get",
    "path": "/api/chat/stream/{slug}",
    "displayName": "Get chat stream placeholder",
    "summary": "Get chat stream placeholder",
    "description": "Placeholder GET handler for the chat stream catch-all route. The slug path segment is accepted by the Next.js route but is not inspected. The handler currently returns the plain text string \"Hello World\" and does not require authentication.",
    "tags": [
      "Chat"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "slug",
        "in": "path",
        "required": true,
        "description": "Catch-all chat stream path segment. The current handler accepts the value but does not use it.",
        "schema": {
          "type": "string",
          "description": "Catch-all chat stream path segment. The current handler accepts the value but does not use it."
        }
      }
    ]
  },
  {
    "id": "post-_api_chat_stream_slug",
    "method": "post",
    "path": "/api/chat/stream/{slug}",
    "displayName": "Stream AI chat response",
    "summary": "Stream AI chat response",
    "description": "Enterprise-only AI chat endpoint that accepts conversation messages and returns an assistant response via Server-Sent Events. Requires a valid Auth.js session and the aiAssistant experimental feature enabled for the tenant. The slug path segment is accepted by the catch-all route but is not used by the implementation. API-key authentication is skipped for /api/chat; tenant context comes from the session.",
    "tags": [
      "Chat"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "slug",
        "in": "path",
        "required": true,
        "description": "Catch-all chat stream path segment. The current handler accepts the value but does not use it.",
        "schema": {
          "type": "string",
          "description": "Catch-all chat stream path segment. The current handler accepts the value but does not use it."
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "inputs": {
          "type": "array",
          "items": {
            "$ref": "#/components/schemas/ChatMessage"
          },
          "minItems": 1,
          "description": "Conversation messages in order. These are passed to the OpenRouter chat model."
        },
        "options": {
          "type": "object",
          "additionalProperties": {},
          "description": "Optional model options. Currently declared by the internal interface but not consumed by the handler."
        },
        "model": {
          "type": "string",
          "description": "Optional model override. Currently ignored; the server uses OPENROUTER_CHAT_MODEL or minimax/minimax-m2."
        },
        "meta": {
          "type": "object",
          "properties": {
            "authorization": {
              "type": "string",
              "description": "Optional downstream authorization token. Currently declared but not consumed by the handler."
            }
          },
          "description": "Optional metadata for legacy chat clients."
        }
      },
      "required": [
        "inputs"
      ]
    }
  },
  {
    "id": "get-_api_v1_clients",
    "method": "get",
    "path": "/api/v1/clients",
    "displayName": "List Clients",
    "summary": "Fetch clients for the current tenant",
    "description": "Returns paginated client records. Use this before creating tickets to map human-readable client names to client_id values.",
    "tags": [
      "Clients"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "client_name",
        "in": "query",
        "required": false,
        "description": "Optional case-insensitive filter on the client name.",
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "is_inactive",
        "in": "query",
        "required": false,
        "description": "When true, include inactive clients as well as active ones.",
        "schema": {
          "type": "boolean"
        }
      },
      {
        "name": "limit",
        "in": "query",
        "required": false,
        "description": "Number of records per page (default 25, max 100).",
        "schema": {
          "type": "integer",
          "minimum": 1,
          "maximum": 100
        }
      },
      {
        "name": "page",
        "in": "query",
        "required": false,
        "description": "Pagination page number starting at 1.",
        "schema": {
          "type": "integer",
          "minimum": 1
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "client_id": {
                "type": "string",
                "format": "uuid"
              },
              "client_name": {
                "type": "string"
              },
              "phone_no": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "credit_balance": {
                "type": "number"
              },
              "email": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "url": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "address": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "created_at": {
                "type": "string",
                "format": "date-time"
              },
              "updated_at": {
                "type": "string",
                "format": "date-time"
              },
              "is_inactive": {
                "type": "boolean"
              },
              "client_type": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "tax_id_number": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "notes": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "properties": {
                "type": "object",
                "properties": {
                  "industry": {
                    "type": "string"
                  },
                  "company_size": {
                    "type": "string"
                  },
                  "annual_revenue": {
                    "type": "string"
                  },
                  "primary_contact_id": {
                    "type": "string",
                    "format": "uuid"
                  },
                  "primary_contact_name": {
                    "type": "string"
                  },
                  "status": {
                    "type": "string"
                  },
                  "type": {
                    "type": "string"
                  },
                  "billing_address": {
                    "type": "string"
                  },
                  "tax_id": {
                    "type": "string"
                  },
                  "notes": {
                    "type": "string"
                  },
                  "payment_terms": {
                    "type": "string"
                  },
                  "website": {
                    "type": "string",
                    "format": "uri"
                  },
                  "parent_client_id": {
                    "type": "string",
                    "format": "uuid"
                  },
                  "parent_client_name": {
                    "type": "string"
                  },
                  "last_contact_date": {
                    "type": "string",
                    "format": "date-time"
                  },
                  "logo": {
                    "type": "string"
                  }
                }
              },
              "payment_terms": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "billing_cycle": {
                "type": "string",
                "enum": [
                  "weekly",
                  "bi-weekly",
                  "monthly",
                  "quarterly",
                  "semi-annually",
                  "annually"
                ]
              },
              "credit_limit": {
                "type": [
                  "number",
                  "null"
                ]
              },
              "preferred_payment_method": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "auto_invoice": {
                "type": "boolean"
              },
              "invoice_delivery_method": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "region_code": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "is_tax_exempt": {
                "type": "boolean"
              },
              "tax_exemption_certificate": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "timezone": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "invoice_template_id": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "uuid"
              },
              "billing_contact_id": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "uuid"
              },
              "billing_email": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "account_manager_id": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "uuid"
              },
              "account_manager_full_name": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "logoUrl": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "tenant": {
                "type": "string",
                "format": "uuid"
              },
              "tags": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            },
            "required": [
              "client_id",
              "client_name",
              "phone_no",
              "credit_balance",
              "email",
              "url",
              "address",
              "created_at",
              "updated_at",
              "is_inactive",
              "client_type",
              "tax_id_number",
              "notes",
              "payment_terms",
              "billing_cycle",
              "credit_limit",
              "preferred_payment_method",
              "auto_invoice",
              "invoice_delivery_method",
              "region_code",
              "is_tax_exempt",
              "tax_exemption_certificate",
              "timezone",
              "invoice_template_id",
              "billing_contact_id",
              "billing_email",
              "account_manager_id",
              "tenant"
            ]
          }
        },
        "pagination": {
          "type": "object",
          "properties": {
            "page": {
              "type": "integer"
            },
            "limit": {
              "type": "integer"
            },
            "total": {
              "type": "integer"
            },
            "totalPages": {
              "type": "integer"
            },
            "hasNext": {
              "type": "boolean"
            },
            "hasPrev": {
              "type": "boolean"
            }
          },
          "required": [
            "page",
            "limit",
            "total",
            "totalPages",
            "hasNext",
            "hasPrev"
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data",
        "pagination"
      ]
    },
    "examples": [
      {
        "name": "Find a specific client",
        "request": {
          "query": {
            "client_name": "Acme",
            "limit": 5
          }
        },
        "notes": "Use a small limit when searching for a client name mentioned by the user so you can quickly grab the matching client_id. If the user did not name a specific client, reuse the first client_id returned."
      }
    ]
  },
  {
    "id": "post-_api_v1_clients",
    "method": "post",
    "path": "/api/v1/clients",
    "displayName": "Create client",
    "summary": "Create client",
    "description": "Inherited ApiBaseController create route for clients. Requires API-key auth and client:create permission.",
    "tags": [
      "Clients"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "client_name": {
          "type": "string",
          "minLength": 1,
          "maxLength": 255
        },
        "phone_no": {
          "type": "string"
        },
        "email": {
          "type": "string",
          "format": "email"
        },
        "url": {
          "type": "string",
          "format": "uri"
        },
        "address": {
          "type": "string"
        },
        "client_type": {
          "type": "string"
        },
        "tax_id_number": {
          "type": "string"
        },
        "notes": {
          "type": "string"
        },
        "properties": {
          "type": "object",
          "additionalProperties": {}
        },
        "payment_terms": {
          "type": "string"
        },
        "billing_cycle": {
          "type": "string",
          "enum": [
            "weekly",
            "bi-weekly",
            "monthly",
            "quarterly",
            "semi-annually",
            "annually"
          ]
        },
        "credit_limit": {
          "type": "number",
          "minimum": 0
        },
        "preferred_payment_method": {
          "type": "string"
        },
        "auto_invoice": {
          "type": "boolean"
        },
        "invoice_delivery_method": {
          "type": "string",
          "enum": [
            "email",
            "mail",
            "portal"
          ]
        },
        "region_code": {
          "type": "string"
        },
        "is_tax_exempt": {
          "type": "boolean"
        },
        "tax_exemption_certificate": {
          "type": "string"
        },
        "timezone": {
          "type": "string"
        },
        "invoice_template_id": {
          "type": "string",
          "format": "uuid"
        },
        "billing_contact_id": {
          "type": "string",
          "format": "uuid"
        },
        "billing_email": {
          "type": "string",
          "format": "email"
        },
        "account_manager_id": {
          "type": "string",
          "format": "uuid"
        },
        "is_inactive": {
          "type": "boolean"
        },
        "tags": {
          "type": "array",
          "items": {
            "type": "string"
          }
        }
      },
      "required": [
        "client_name",
        "billing_cycle"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "type": "object",
          "properties": {
            "client_id": {
              "type": "string",
              "format": "uuid"
            },
            "client_name": {
              "type": "string"
            },
            "phone_no": {
              "type": [
                "string",
                "null"
              ]
            },
            "credit_balance": {
              "type": "number"
            },
            "email": {
              "type": [
                "string",
                "null"
              ]
            },
            "url": {
              "type": [
                "string",
                "null"
              ]
            },
            "address": {
              "type": [
                "string",
                "null"
              ]
            },
            "created_at": {
              "type": "string",
              "format": "date-time"
            },
            "updated_at": {
              "type": "string",
              "format": "date-time"
            },
            "is_inactive": {
              "type": "boolean"
            },
            "client_type": {
              "type": [
                "string",
                "null"
              ]
            },
            "tax_id_number": {
              "type": [
                "string",
                "null"
              ]
            },
            "notes": {
              "type": [
                "string",
                "null"
              ]
            },
            "properties": {
              "type": "object",
              "properties": {
                "industry": {
                  "type": "string"
                },
                "company_size": {
                  "type": "string"
                },
                "annual_revenue": {
                  "type": "string"
                },
                "primary_contact_id": {
                  "type": "string",
                  "format": "uuid"
                },
                "primary_contact_name": {
                  "type": "string"
                },
                "status": {
                  "type": "string"
                },
                "type": {
                  "type": "string"
                },
                "billing_address": {
                  "type": "string"
                },
                "tax_id": {
                  "type": "string"
                },
                "notes": {
                  "type": "string"
                },
                "payment_terms": {
                  "type": "string"
                },
                "website": {
                  "type": "string",
                  "format": "uri"
                },
                "parent_client_id": {
                  "type": "string",
                  "format": "uuid"
                },
                "parent_client_name": {
                  "type": "string"
                },
                "last_contact_date": {
                  "type": "string",
                  "format": "date-time"
                },
                "logo": {
                  "type": "string"
                }
              }
            },
            "payment_terms": {
              "type": [
                "string",
                "null"
              ]
            },
            "billing_cycle": {
              "type": "string",
              "enum": [
                "weekly",
                "bi-weekly",
                "monthly",
                "quarterly",
                "semi-annually",
                "annually"
              ]
            },
            "credit_limit": {
              "type": [
                "number",
                "null"
              ]
            },
            "preferred_payment_method": {
              "type": [
                "string",
                "null"
              ]
            },
            "auto_invoice": {
              "type": "boolean"
            },
            "invoice_delivery_method": {
              "type": [
                "string",
                "null"
              ]
            },
            "region_code": {
              "type": [
                "string",
                "null"
              ]
            },
            "is_tax_exempt": {
              "type": "boolean"
            },
            "tax_exemption_certificate": {
              "type": [
                "string",
                "null"
              ]
            },
            "timezone": {
              "type": [
                "string",
                "null"
              ]
            },
            "invoice_template_id": {
              "type": [
                "string",
                "null"
              ],
              "format": "uuid"
            },
            "billing_contact_id": {
              "type": [
                "string",
                "null"
              ],
              "format": "uuid"
            },
            "billing_email": {
              "type": [
                "string",
                "null"
              ]
            },
            "account_manager_id": {
              "type": [
                "string",
                "null"
              ],
              "format": "uuid"
            },
            "account_manager_full_name": {
              "type": [
                "string",
                "null"
              ]
            },
            "logoUrl": {
              "type": [
                "string",
                "null"
              ]
            },
            "tenant": {
              "type": "string",
              "format": "uuid"
            },
            "tags": {
              "type": "array",
              "items": {
                "type": "string"
              }
            }
          },
          "required": [
            "client_id",
            "client_name",
            "phone_no",
            "credit_balance",
            "email",
            "url",
            "address",
            "created_at",
            "updated_at",
            "is_inactive",
            "client_type",
            "tax_id_number",
            "notes",
            "payment_terms",
            "billing_cycle",
            "credit_limit",
            "preferred_payment_method",
            "auto_invoice",
            "invoice_delivery_method",
            "region_code",
            "is_tax_exempt",
            "tax_exemption_certificate",
            "timezone",
            "invoice_template_id",
            "billing_contact_id",
            "billing_email",
            "account_manager_id",
            "tenant"
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_clients_id",
    "method": "get",
    "path": "/api/v1/clients/{id}",
    "displayName": "Get client",
    "summary": "Get client",
    "description": "Inherited ApiBaseController get route for one client_id.",
    "tags": [
      "Clients"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "type": "object",
          "properties": {
            "client_id": {
              "type": "string",
              "format": "uuid"
            },
            "client_name": {
              "type": "string"
            },
            "phone_no": {
              "type": [
                "string",
                "null"
              ]
            },
            "credit_balance": {
              "type": "number"
            },
            "email": {
              "type": [
                "string",
                "null"
              ]
            },
            "url": {
              "type": [
                "string",
                "null"
              ]
            },
            "address": {
              "type": [
                "string",
                "null"
              ]
            },
            "created_at": {
              "type": "string",
              "format": "date-time"
            },
            "updated_at": {
              "type": "string",
              "format": "date-time"
            },
            "is_inactive": {
              "type": "boolean"
            },
            "client_type": {
              "type": [
                "string",
                "null"
              ]
            },
            "tax_id_number": {
              "type": [
                "string",
                "null"
              ]
            },
            "notes": {
              "type": [
                "string",
                "null"
              ]
            },
            "properties": {
              "type": "object",
              "properties": {
                "industry": {
                  "type": "string"
                },
                "company_size": {
                  "type": "string"
                },
                "annual_revenue": {
                  "type": "string"
                },
                "primary_contact_id": {
                  "type": "string",
                  "format": "uuid"
                },
                "primary_contact_name": {
                  "type": "string"
                },
                "status": {
                  "type": "string"
                },
                "type": {
                  "type": "string"
                },
                "billing_address": {
                  "type": "string"
                },
                "tax_id": {
                  "type": "string"
                },
                "notes": {
                  "type": "string"
                },
                "payment_terms": {
                  "type": "string"
                },
                "website": {
                  "type": "string",
                  "format": "uri"
                },
                "parent_client_id": {
                  "type": "string",
                  "format": "uuid"
                },
                "parent_client_name": {
                  "type": "string"
                },
                "last_contact_date": {
                  "type": "string",
                  "format": "date-time"
                },
                "logo": {
                  "type": "string"
                }
              }
            },
            "payment_terms": {
              "type": [
                "string",
                "null"
              ]
            },
            "billing_cycle": {
              "type": "string",
              "enum": [
                "weekly",
                "bi-weekly",
                "monthly",
                "quarterly",
                "semi-annually",
                "annually"
              ]
            },
            "credit_limit": {
              "type": [
                "number",
                "null"
              ]
            },
            "preferred_payment_method": {
              "type": [
                "string",
                "null"
              ]
            },
            "auto_invoice": {
              "type": "boolean"
            },
            "invoice_delivery_method": {
              "type": [
                "string",
                "null"
              ]
            },
            "region_code": {
              "type": [
                "string",
                "null"
              ]
            },
            "is_tax_exempt": {
              "type": "boolean"
            },
            "tax_exemption_certificate": {
              "type": [
                "string",
                "null"
              ]
            },
            "timezone": {
              "type": [
                "string",
                "null"
              ]
            },
            "invoice_template_id": {
              "type": [
                "string",
                "null"
              ],
              "format": "uuid"
            },
            "billing_contact_id": {
              "type": [
                "string",
                "null"
              ],
              "format": "uuid"
            },
            "billing_email": {
              "type": [
                "string",
                "null"
              ]
            },
            "account_manager_id": {
              "type": [
                "string",
                "null"
              ],
              "format": "uuid"
            },
            "account_manager_full_name": {
              "type": [
                "string",
                "null"
              ]
            },
            "logoUrl": {
              "type": [
                "string",
                "null"
              ]
            },
            "tenant": {
              "type": "string",
              "format": "uuid"
            },
            "tags": {
              "type": "array",
              "items": {
                "type": "string"
              }
            }
          },
          "required": [
            "client_id",
            "client_name",
            "phone_no",
            "credit_balance",
            "email",
            "url",
            "address",
            "created_at",
            "updated_at",
            "is_inactive",
            "client_type",
            "tax_id_number",
            "notes",
            "payment_terms",
            "billing_cycle",
            "credit_limit",
            "preferred_payment_method",
            "auto_invoice",
            "invoice_delivery_method",
            "region_code",
            "is_tax_exempt",
            "tax_exemption_certificate",
            "timezone",
            "invoice_template_id",
            "billing_contact_id",
            "billing_email",
            "account_manager_id",
            "tenant"
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "put-_api_v1_clients_id",
    "method": "put",
    "path": "/api/v1/clients/{id}",
    "displayName": "Update client",
    "summary": "Update client",
    "description": "Inherited ApiBaseController update route for one client_id.",
    "tags": [
      "Clients"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "client_name": {
          "type": "string",
          "minLength": 1,
          "maxLength": 255
        },
        "phone_no": {
          "type": "string"
        },
        "email": {
          "type": "string",
          "format": "email"
        },
        "url": {
          "type": "string",
          "format": "uri"
        },
        "address": {
          "type": "string"
        },
        "client_type": {
          "type": "string"
        },
        "tax_id_number": {
          "type": "string"
        },
        "notes": {
          "type": "string"
        },
        "properties": {
          "type": "object",
          "additionalProperties": {}
        },
        "payment_terms": {
          "type": "string"
        },
        "billing_cycle": {
          "type": "string",
          "enum": [
            "weekly",
            "bi-weekly",
            "monthly",
            "quarterly",
            "semi-annually",
            "annually"
          ]
        },
        "credit_limit": {
          "type": "number",
          "minimum": 0
        },
        "preferred_payment_method": {
          "type": "string"
        },
        "auto_invoice": {
          "type": "boolean"
        },
        "invoice_delivery_method": {
          "type": "string",
          "enum": [
            "email",
            "mail",
            "portal"
          ]
        },
        "region_code": {
          "type": "string"
        },
        "is_tax_exempt": {
          "type": "boolean"
        },
        "tax_exemption_certificate": {
          "type": "string"
        },
        "timezone": {
          "type": "string"
        },
        "invoice_template_id": {
          "type": "string",
          "format": "uuid"
        },
        "billing_contact_id": {
          "type": "string",
          "format": "uuid"
        },
        "billing_email": {
          "type": "string",
          "format": "email"
        },
        "account_manager_id": {
          "type": "string",
          "format": "uuid"
        },
        "is_inactive": {
          "type": "boolean"
        },
        "tags": {
          "type": "array",
          "items": {
            "type": "string"
          }
        }
      },
      "required": [
        "client_name",
        "billing_cycle"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "type": "object",
          "properties": {
            "client_id": {
              "type": "string",
              "format": "uuid"
            },
            "client_name": {
              "type": "string"
            },
            "phone_no": {
              "type": [
                "string",
                "null"
              ]
            },
            "credit_balance": {
              "type": "number"
            },
            "email": {
              "type": [
                "string",
                "null"
              ]
            },
            "url": {
              "type": [
                "string",
                "null"
              ]
            },
            "address": {
              "type": [
                "string",
                "null"
              ]
            },
            "created_at": {
              "type": "string",
              "format": "date-time"
            },
            "updated_at": {
              "type": "string",
              "format": "date-time"
            },
            "is_inactive": {
              "type": "boolean"
            },
            "client_type": {
              "type": [
                "string",
                "null"
              ]
            },
            "tax_id_number": {
              "type": [
                "string",
                "null"
              ]
            },
            "notes": {
              "type": [
                "string",
                "null"
              ]
            },
            "properties": {
              "type": "object",
              "properties": {
                "industry": {
                  "type": "string"
                },
                "company_size": {
                  "type": "string"
                },
                "annual_revenue": {
                  "type": "string"
                },
                "primary_contact_id": {
                  "type": "string",
                  "format": "uuid"
                },
                "primary_contact_name": {
                  "type": "string"
                },
                "status": {
                  "type": "string"
                },
                "type": {
                  "type": "string"
                },
                "billing_address": {
                  "type": "string"
                },
                "tax_id": {
                  "type": "string"
                },
                "notes": {
                  "type": "string"
                },
                "payment_terms": {
                  "type": "string"
                },
                "website": {
                  "type": "string",
                  "format": "uri"
                },
                "parent_client_id": {
                  "type": "string",
                  "format": "uuid"
                },
                "parent_client_name": {
                  "type": "string"
                },
                "last_contact_date": {
                  "type": "string",
                  "format": "date-time"
                },
                "logo": {
                  "type": "string"
                }
              }
            },
            "payment_terms": {
              "type": [
                "string",
                "null"
              ]
            },
            "billing_cycle": {
              "type": "string",
              "enum": [
                "weekly",
                "bi-weekly",
                "monthly",
                "quarterly",
                "semi-annually",
                "annually"
              ]
            },
            "credit_limit": {
              "type": [
                "number",
                "null"
              ]
            },
            "preferred_payment_method": {
              "type": [
                "string",
                "null"
              ]
            },
            "auto_invoice": {
              "type": "boolean"
            },
            "invoice_delivery_method": {
              "type": [
                "string",
                "null"
              ]
            },
            "region_code": {
              "type": [
                "string",
                "null"
              ]
            },
            "is_tax_exempt": {
              "type": "boolean"
            },
            "tax_exemption_certificate": {
              "type": [
                "string",
                "null"
              ]
            },
            "timezone": {
              "type": [
                "string",
                "null"
              ]
            },
            "invoice_template_id": {
              "type": [
                "string",
                "null"
              ],
              "format": "uuid"
            },
            "billing_contact_id": {
              "type": [
                "string",
                "null"
              ],
              "format": "uuid"
            },
            "billing_email": {
              "type": [
                "string",
                "null"
              ]
            },
            "account_manager_id": {
              "type": [
                "string",
                "null"
              ],
              "format": "uuid"
            },
            "account_manager_full_name": {
              "type": [
                "string",
                "null"
              ]
            },
            "logoUrl": {
              "type": [
                "string",
                "null"
              ]
            },
            "tenant": {
              "type": "string",
              "format": "uuid"
            },
            "tags": {
              "type": "array",
              "items": {
                "type": "string"
              }
            }
          },
          "required": [
            "client_id",
            "client_name",
            "phone_no",
            "credit_balance",
            "email",
            "url",
            "address",
            "created_at",
            "updated_at",
            "is_inactive",
            "client_type",
            "tax_id_number",
            "notes",
            "payment_terms",
            "billing_cycle",
            "credit_limit",
            "preferred_payment_method",
            "auto_invoice",
            "invoice_delivery_method",
            "region_code",
            "is_tax_exempt",
            "tax_exemption_certificate",
            "timezone",
            "invoice_template_id",
            "billing_contact_id",
            "billing_email",
            "account_manager_id",
            "tenant"
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "delete-_api_v1_clients_id",
    "method": "delete",
    "path": "/api/v1/clients/{id}",
    "displayName": "Delete client",
    "summary": "Delete client",
    "description": "Inherited ApiBaseController delete route for one client_id.",
    "tags": [
      "Clients"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      }
    ]
  },
  {
    "id": "get-_api_v1_clients_stats",
    "method": "get",
    "path": "/api/v1/clients/stats",
    "displayName": "Get client stats",
    "summary": "Get client stats",
    "description": "Client statistics route with explicit API-key validation and client:read permission check.",
    "tags": [
      "Clients"
    ],
    "approvalRequired": false,
    "parameters": [],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "type": "object",
          "properties": {
            "total_clients": {
              "type": "number"
            },
            "active_clients": {
              "type": "number"
            },
            "inactive_clients": {
              "type": "number"
            },
            "clients_by_billing_cycle": {
              "type": "object",
              "additionalProperties": {
                "type": "number"
              }
            },
            "clients_by_client_type": {
              "type": "object",
              "additionalProperties": {
                "type": "number"
              }
            },
            "total_credit_balance": {
              "type": "number"
            },
            "average_credit_balance": {
              "type": "number"
            }
          },
          "required": [
            "total_clients",
            "active_clients",
            "inactive_clients",
            "clients_by_billing_cycle",
            "clients_by_client_type",
            "total_credit_balance",
            "average_credit_balance"
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_clients_id_contacts",
    "method": "get",
    "path": "/api/v1/clients/{id}/contacts",
    "displayName": "List contacts for client",
    "summary": "List contacts for client",
    "description": "Returns paginated contacts filtered by client_id after client existence check.",
    "tags": [
      "Clients"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "type": "array",
          "items": {
            "$ref": "#/components/schemas/ContactResource"
          }
        },
        "pagination": {
          "type": "object",
          "properties": {
            "page": {
              "type": "integer"
            },
            "limit": {
              "type": "integer"
            },
            "total": {
              "type": "integer"
            },
            "totalPages": {
              "type": "integer"
            },
            "hasNext": {
              "type": "boolean"
            },
            "hasPrev": {
              "type": "boolean"
            }
          },
          "required": [
            "page",
            "limit",
            "total",
            "totalPages",
            "hasNext",
            "hasPrev"
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data",
        "pagination"
      ]
    }
  },
  {
    "id": "get-_api_v1_clients_id_locations",
    "method": "get",
    "path": "/api/v1/clients/{id}/locations",
    "displayName": "List Client Locations",
    "summary": "Fetch locations for a client",
    "description": "Returns the saved locations for the specified client. Call this when a ticket needs a location_id.",
    "tags": [
      "Clients"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Client identifier whose locations should be listed.",
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      },
      {
        "name": "limit",
        "in": "query",
        "required": false,
        "description": "Number of locations to return (default 25, max 100).",
        "schema": {
          "type": "integer",
          "minimum": 1,
          "maximum": 100
        }
      },
      {
        "name": "page",
        "in": "query",
        "required": false,
        "description": "Pagination page number.",
        "schema": {
          "type": "integer",
          "minimum": 1
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "location_id": {
                "type": "string",
                "format": "uuid"
              },
              "client_id": {
                "type": "string",
                "format": "uuid"
              },
              "location_name": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "address_line1": {
                "type": "string"
              },
              "address_line2": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "address_line3": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "city": {
                "type": "string"
              },
              "state_province": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "postal_code": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "country_code": {
                "type": "string"
              },
              "country_name": {
                "type": "string"
              },
              "region_code": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "is_billing_address": {
                "type": "boolean"
              },
              "is_shipping_address": {
                "type": "boolean"
              },
              "is_default": {
                "type": "boolean"
              },
              "phone": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "fax": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "email": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "notes": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "is_active": {
                "type": "boolean"
              },
              "created_at": {
                "type": "string",
                "format": "date-time"
              },
              "updated_at": {
                "type": "string",
                "format": "date-time"
              },
              "tenant": {
                "type": "string",
                "format": "uuid"
              }
            },
            "required": [
              "location_id",
              "client_id",
              "location_name",
              "address_line1",
              "address_line2",
              "address_line3",
              "city",
              "state_province",
              "postal_code",
              "country_code",
              "country_name",
              "region_code",
              "is_billing_address",
              "is_shipping_address",
              "is_default",
              "phone",
              "fax",
              "email",
              "notes",
              "is_active",
              "created_at",
              "updated_at",
              "tenant"
            ]
          }
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    },
    "examples": [
      {
        "name": "List locations for client",
        "request": {
          "params": {
            "id": "22222222-2222-2222-2222-222222222222"
          },
          "query": {
            "limit": 5
          }
        },
        "notes": "Use the same client_id supplied to the ticket create payload."
      }
    ]
  },
  {
    "id": "post-_api_v1_clients_id_locations",
    "method": "post",
    "path": "/api/v1/clients/{id}/locations",
    "displayName": "Create client location",
    "summary": "Create client location",
    "description": "Creates a location row for client_id after validation and client existence check.",
    "tags": [
      "Clients"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "location_name": {
          "type": "string"
        },
        "address_line1": {
          "type": "string",
          "minLength": 1
        },
        "address_line2": {
          "type": "string"
        },
        "address_line3": {
          "type": "string"
        },
        "city": {
          "type": "string",
          "minLength": 1
        },
        "state_province": {
          "type": "string"
        },
        "postal_code": {
          "type": "string"
        },
        "country_code": {
          "type": "string",
          "minLength": 2,
          "maxLength": 3
        },
        "country_name": {
          "type": "string",
          "minLength": 1
        },
        "region_code": {
          "type": "string"
        },
        "is_billing_address": {
          "type": "boolean"
        },
        "is_shipping_address": {
          "type": "boolean"
        },
        "is_default": {
          "type": "boolean"
        },
        "phone": {
          "type": "string"
        },
        "fax": {
          "type": "string"
        },
        "email": {
          "type": "string",
          "format": "email"
        },
        "notes": {
          "type": "string"
        },
        "is_active": {
          "type": "boolean"
        }
      },
      "required": [
        "address_line1",
        "city",
        "country_code",
        "country_name"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "type": "object",
          "properties": {
            "location_id": {
              "type": "string",
              "format": "uuid"
            },
            "client_id": {
              "type": "string",
              "format": "uuid"
            },
            "location_name": {
              "type": [
                "string",
                "null"
              ]
            },
            "address_line1": {
              "type": "string"
            },
            "address_line2": {
              "type": [
                "string",
                "null"
              ]
            },
            "address_line3": {
              "type": [
                "string",
                "null"
              ]
            },
            "city": {
              "type": "string"
            },
            "state_province": {
              "type": [
                "string",
                "null"
              ]
            },
            "postal_code": {
              "type": [
                "string",
                "null"
              ]
            },
            "country_code": {
              "type": "string"
            },
            "country_name": {
              "type": "string"
            },
            "region_code": {
              "type": [
                "string",
                "null"
              ]
            },
            "is_billing_address": {
              "type": "boolean"
            },
            "is_shipping_address": {
              "type": "boolean"
            },
            "is_default": {
              "type": "boolean"
            },
            "phone": {
              "type": [
                "string",
                "null"
              ]
            },
            "fax": {
              "type": [
                "string",
                "null"
              ]
            },
            "email": {
              "type": [
                "string",
                "null"
              ]
            },
            "notes": {
              "type": [
                "string",
                "null"
              ]
            },
            "is_active": {
              "type": "boolean"
            },
            "created_at": {
              "type": "string",
              "format": "date-time"
            },
            "updated_at": {
              "type": "string",
              "format": "date-time"
            },
            "tenant": {
              "type": "string",
              "format": "uuid"
            }
          },
          "required": [
            "location_id",
            "client_id",
            "location_name",
            "address_line1",
            "address_line2",
            "address_line3",
            "city",
            "state_province",
            "postal_code",
            "country_code",
            "country_name",
            "region_code",
            "is_billing_address",
            "is_shipping_address",
            "is_default",
            "phone",
            "fax",
            "email",
            "notes",
            "is_active",
            "created_at",
            "updated_at",
            "tenant"
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_contacts",
    "method": "get",
    "path": "/api/v1/contacts",
    "displayName": "List Contacts",
    "summary": "Fetch contacts",
    "description": "Paginated list of contacts. Filter by client_id to retrieve contacts for a specific client when preparing a ticket.",
    "tags": [
      "Contacts"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "client_id",
        "in": "query",
        "required": false,
        "description": "Restrict contacts to a specific client.",
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      },
      {
        "name": "search_term",
        "in": "query",
        "required": false,
        "description": "Search text to match against contact names or emails.",
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "limit",
        "in": "query",
        "required": false,
        "description": "Number of records per page (default 25, max 100).",
        "schema": {
          "type": "integer",
          "minimum": 1,
          "maximum": 100
        }
      },
      {
        "name": "page",
        "in": "query",
        "required": false,
        "description": "Pagination page number.",
        "schema": {
          "type": "integer",
          "minimum": 1
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "type": "array",
          "items": {
            "$ref": "#/components/schemas/ContactResource"
          }
        },
        "pagination": {
          "type": "object",
          "properties": {
            "page": {
              "type": "integer"
            },
            "limit": {
              "type": "integer"
            },
            "total": {
              "type": "integer"
            },
            "totalPages": {
              "type": "integer"
            },
            "hasNext": {
              "type": "boolean"
            },
            "hasPrev": {
              "type": "boolean"
            }
          },
          "required": [
            "page",
            "limit",
            "total",
            "totalPages",
            "hasNext",
            "hasPrev"
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data",
        "pagination"
      ]
    },
    "examples": [
      {
        "name": "Find client contacts",
        "request": {
          "query": {
            "client_id": "22222222-2222-2222-2222-222222222222",
            "limit": 5
          }
        },
        "notes": "Use the client_id discovered from the clients endpoint to retrieve matching contacts and resolve contact_name_id."
      }
    ]
  },
  {
    "id": "post-_api_v1_contacts",
    "method": "post",
    "path": "/api/v1/contacts",
    "displayName": "Create contact",
    "summary": "Create contact",
    "description": "Inherited ApiBaseController create route for contacts.",
    "tags": [
      "Contacts"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "full_name": {
          "type": "string",
          "minLength": 1,
          "maxLength": 255
        },
        "client_id": {
          "type": "string",
          "format": "uuid"
        },
        "phone_numbers": {
          "type": "array",
          "items": {
            "type": "object",
            "additionalProperties": {}
          }
        },
        "email": {
          "type": "string",
          "format": "email"
        },
        "primary_email_canonical_type": {
          "type": [
            "string",
            "null"
          ]
        },
        "primary_email_custom_type": {
          "type": [
            "string",
            "null"
          ]
        },
        "primary_email_custom_type_id": {
          "type": [
            "string",
            "null"
          ],
          "format": "uuid"
        },
        "additional_email_addresses": {
          "type": "array",
          "items": {
            "type": "object",
            "additionalProperties": {}
          }
        },
        "role": {
          "type": "string"
        },
        "notes": {
          "type": "string"
        },
        "is_inactive": {
          "type": "boolean"
        },
        "tags": {
          "type": "array",
          "items": {
            "type": "string"
          }
        }
      },
      "required": [
        "full_name",
        "email"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "$ref": "#/components/schemas/ContactResource"
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_contacts_id",
    "method": "get",
    "path": "/api/v1/contacts/{id}",
    "displayName": "Get contact",
    "summary": "Get contact",
    "description": "Inherited ApiBaseController get route for one contact_name_id.",
    "tags": [
      "Contacts"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "$ref": "#/components/schemas/ContactResource"
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "put-_api_v1_contacts_id",
    "method": "put",
    "path": "/api/v1/contacts/{id}",
    "displayName": "Update contact",
    "summary": "Update contact",
    "description": "Inherited ApiBaseController update route for one contact_name_id.",
    "tags": [
      "Contacts"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "full_name": {
          "type": "string",
          "minLength": 1,
          "maxLength": 255
        },
        "client_id": {
          "type": "string",
          "format": "uuid"
        },
        "phone_numbers": {
          "type": "array",
          "items": {
            "type": "object",
            "additionalProperties": {}
          }
        },
        "email": {
          "type": "string",
          "format": "email"
        },
        "primary_email_canonical_type": {
          "type": [
            "string",
            "null"
          ]
        },
        "primary_email_custom_type": {
          "type": [
            "string",
            "null"
          ]
        },
        "primary_email_custom_type_id": {
          "type": [
            "string",
            "null"
          ],
          "format": "uuid"
        },
        "additional_email_addresses": {
          "type": "array",
          "items": {
            "type": "object",
            "additionalProperties": {}
          }
        },
        "role": {
          "type": "string"
        },
        "notes": {
          "type": "string"
        },
        "is_inactive": {
          "type": "boolean"
        },
        "tags": {
          "type": "array",
          "items": {
            "type": "string"
          }
        }
      },
      "required": [
        "full_name",
        "email"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "$ref": "#/components/schemas/ContactResource"
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "delete-_api_v1_contacts_id",
    "method": "delete",
    "path": "/api/v1/contacts/{id}",
    "displayName": "Delete contact",
    "summary": "Delete contact",
    "description": "Inherited ApiBaseController delete route for one contact_name_id.",
    "tags": [
      "Contacts"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      }
    ]
  },
  {
    "id": "get-_api_v1_contacts_search",
    "method": "get",
    "path": "/api/v1/contacts/search",
    "displayName": "Search contacts",
    "summary": "Search contacts",
    "description": "Runs advanced contact search with explicit API-key auth and contact:read permission check.",
    "tags": [
      "Contacts"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "query",
        "in": "query",
        "required": true,
        "schema": {
          "type": "string",
          "minLength": 1
        }
      },
      {
        "name": "fields",
        "in": "query",
        "required": false,
        "description": "Comma-separated field list; parsed by contactSearchSchema transform.",
        "schema": {
          "type": "string",
          "description": "Comma-separated field list; parsed by contactSearchSchema transform."
        }
      },
      {
        "name": "client_id",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      },
      {
        "name": "include_inactive",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ]
        }
      },
      {
        "name": "limit",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "type": "array",
          "items": {
            "$ref": "#/components/schemas/ContactResource"
          }
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_contacts_export",
    "method": "get",
    "path": "/api/v1/contacts/export",
    "displayName": "Export contacts",
    "summary": "Export contacts",
    "description": "Exports contacts as CSV or JSON using explicit API-key auth and contact:read permission.",
    "tags": [
      "Contacts"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "format",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "csv",
            "json"
          ]
        }
      },
      {
        "name": "include_inactive",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ]
        }
      },
      {
        "name": "client_id",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      },
      {
        "name": "fields",
        "in": "query",
        "required": false,
        "description": "Array schema expects parsed list, but URL values arrive as string.",
        "schema": {
          "type": "string",
          "description": "Array schema expects parsed list, but URL values arrive as string."
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "type": "array",
          "items": {
            "$ref": "#/components/schemas/ContactExportRow"
          }
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_contacts_stats",
    "method": "get",
    "path": "/api/v1/contacts/stats",
    "displayName": "Get contact stats",
    "summary": "Get contact stats",
    "description": "Returns contact statistics using explicit API-key auth and contact:read permission.",
    "tags": [
      "Contacts"
    ],
    "approvalRequired": false,
    "parameters": [],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "$ref": "#/components/schemas/ContactStatsResource"
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_clientcontractlines",
    "method": "get",
    "path": "/api/v1/client-contract-lines",
    "displayName": "List client contract lines",
    "summary": "List client contract lines",
    "description": "Lists client contract lines — contract_lines rows that belong to client contracts (joined via contract_id), with the owning client_id and client_contract_id surfaced. Supports client_id, contract_line_id, service_category, is_active, has_custom_rate, and start/end-date-range filters plus page/limit pagination. Authenticated and tenant-scoped via withApiKeyRouteAuth.",
    "tags": [
      "Client Contract Lines"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "page",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "limit",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "sort",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "order",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "asc",
            "desc"
          ]
        }
      },
      {
        "name": "search",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "created_from",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "format": "date-time"
        }
      },
      {
        "name": "created_to",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "format": "date-time"
        }
      },
      {
        "name": "updated_from",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "format": "date-time"
        }
      },
      {
        "name": "updated_to",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "format": "date-time"
        }
      },
      {
        "name": "client_id",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      },
      {
        "name": "contract_line_id",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      },
      {
        "name": "service_category",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "is_active",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ]
        }
      },
      {
        "name": "has_custom_rate",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ]
        }
      },
      {
        "name": "is_contractd",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ]
        }
      },
      {
        "name": "start_date_from",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "format": "date-time"
        }
      },
      {
        "name": "start_date_to",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "format": "date-time"
        }
      },
      {
        "name": "end_date_from",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "format": "date-time"
        }
      },
      {
        "name": "end_date_to",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "format": "date-time"
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "$ref": "#/components/schemas/ClientContractLineListItem"
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "post-_api_v1_clientcontractlines",
    "method": "post",
    "path": "/api/v1/client-contract-lines",
    "displayName": "Assign contract line to client",
    "summary": "Assign contract line to client",
    "description": "Assigns one contract line to a client by cloning a template line into the client contract, using createClientContractLineSchema validation. Authenticated and tenant-scoped via withApiKeyRouteAuth.",
    "tags": [
      "Client Contract Lines"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "client_id": {
          "type": "string",
          "format": "uuid"
        },
        "contract_line_id": {
          "type": "string",
          "format": "uuid"
        },
        "service_category": {
          "type": "string"
        },
        "start_date": {
          "type": "string",
          "format": "date-time"
        },
        "end_date": {
          "type": "string",
          "format": "date-time"
        },
        "is_active": {
          "type": "boolean"
        },
        "custom_rate": {
          "type": "number",
          "minimum": 0
        },
        "client_contract_id": {
          "type": "string",
          "format": "uuid"
        }
      },
      "required": [
        "client_id",
        "contract_line_id",
        "start_date"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "$ref": "#/components/schemas/ClientContractLineResource"
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "delete-_api_v1_clientcontractlines_id",
    "method": "delete",
    "path": "/api/v1/client-contract-lines/{id}",
    "displayName": "Unassign contract line from client",
    "summary": "Unassign contract line from client",
    "description": "Deactivates the client-owned contract line for the provided id. Authenticated and tenant-scoped via withApiKeyRouteAuth.",
    "tags": [
      "Client Contract Lines"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      }
    ]
  },
  {
    "id": "get-_api_v1_contractlines",
    "method": "get",
    "path": "/api/v1/contract-lines",
    "displayName": "List contract lines",
    "summary": "List contract lines",
    "description": "Lists contract lines with pagination/filtering and optional include flags. Authenticated and tenant-scoped via withApiKeyRouteAuth. Query parsing/validation uses contractLineListQuerySchema, then listWithOptions reads from contract_lines for the tenant context.",
    "tags": [
      "Contract Lines"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "page",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "limit",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "sort",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "order",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "asc",
            "desc"
          ]
        }
      },
      {
        "name": "search",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "created_from",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "format": "date-time"
        }
      },
      {
        "name": "created_to",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "format": "date-time"
        }
      },
      {
        "name": "updated_from",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "format": "date-time"
        }
      },
      {
        "name": "updated_to",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "format": "date-time"
        }
      },
      {
        "name": "contract_line_name",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "contract_line_type",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "Fixed",
            "Hourly",
            "Usage"
          ]
        }
      },
      {
        "name": "billing_frequency",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "weekly",
            "bi-weekly",
            "monthly",
            "quarterly",
            "semi-annually",
            "annually"
          ]
        }
      },
      {
        "name": "is_custom",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ]
        }
      },
      {
        "name": "is_active",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ]
        }
      },
      {
        "name": "service_category",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "has_services",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ]
        }
      },
      {
        "name": "clients_count_min",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "clients_count_max",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "revenue_min",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "revenue_max",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "include_services",
        "in": "query",
        "required": false,
        "description": "Controller-level include flag parsed directly from query string.",
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ],
          "description": "Controller-level include flag parsed directly from query string."
        }
      },
      {
        "name": "include_usage",
        "in": "query",
        "required": false,
        "description": "Controller-level include flag parsed directly from query string.",
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ],
          "description": "Controller-level include flag parsed directly from query string."
        }
      },
      {
        "name": "include_clients",
        "in": "query",
        "required": false,
        "description": "Controller-level include flag parsed directly from query string.",
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ],
          "description": "Controller-level include flag parsed directly from query string."
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "success": {
          "type": "boolean",
          "enum": [
            true
          ]
        },
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "properties": {
            "timestamp": {
              "type": "string",
              "format": "date-time"
            },
            "version": {
              "type": "string"
            }
          },
          "required": [
            "timestamp",
            "version"
          ]
        }
      },
      "required": [
        "success",
        "data"
      ]
    }
  },
  {
    "id": "post-_api_v1_contractlines",
    "method": "post",
    "path": "/api/v1/contract-lines",
    "displayName": "Create contract line",
    "summary": "Create contract line",
    "description": "Creates a contract line row in contract_lines. Validation uses createContractLineSchema (including overtime/after-hours constraints). ID is generated by service with uuidv4. Route currently relies on request context presence and can fail when context is unavailable.",
    "tags": [
      "Contract Lines"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "contract_line_name": {
          "type": "string",
          "minLength": 1,
          "maxLength": 255
        },
        "billing_frequency": {
          "type": "string",
          "enum": [
            "weekly",
            "bi-weekly",
            "monthly",
            "quarterly",
            "semi-annually",
            "annually"
          ]
        },
        "is_custom": {
          "type": "boolean"
        },
        "service_category": {
          "type": "string"
        },
        "contract_line_type": {
          "type": "string",
          "enum": [
            "Fixed",
            "Hourly",
            "Usage"
          ]
        },
        "cadence_owner": {
          "type": "string",
          "enum": [
            "client",
            "contract"
          ]
        },
        "hourly_rate": {
          "type": "number",
          "minimum": 0
        },
        "minimum_billable_time": {
          "type": "number",
          "minimum": 0
        },
        "round_up_to_nearest": {
          "type": "number",
          "minimum": 1
        },
        "enable_overtime": {
          "type": "boolean"
        },
        "overtime_rate": {
          "type": "number",
          "minimum": 0
        },
        "overtime_threshold": {
          "type": "number",
          "minimum": 0
        },
        "enable_after_hours_rate": {
          "type": "boolean"
        },
        "after_hours_multiplier": {
          "type": "number",
          "minimum": 0
        },
        "is_active": {
          "type": "boolean"
        },
        "features": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "location_id": {
          "type": [
            "string",
            "null"
          ],
          "format": "uuid"
        }
      },
      "required": [
        "contract_line_name",
        "billing_frequency",
        "contract_line_type"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "success": {
          "type": "boolean",
          "enum": [
            true
          ]
        },
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "properties": {
            "timestamp": {
              "type": "string",
              "format": "date-time"
            },
            "version": {
              "type": "string"
            }
          },
          "required": [
            "timestamp",
            "version"
          ]
        }
      },
      "required": [
        "success",
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_contractlines_id",
    "method": "get",
    "path": "/api/v1/contract-lines/{id}",
    "displayName": "Get contract line",
    "summary": "Get contract line",
    "description": "Returns one contract line by contract_line_id, including optional related data through include query flags.",
    "tags": [
      "Contract Lines"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Contract line UUID from contract_lines.contract_line_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Contract line UUID from contract_lines.contract_line_id."
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "success": {
          "type": "boolean",
          "enum": [
            true
          ]
        },
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "properties": {
            "timestamp": {
              "type": "string",
              "format": "date-time"
            },
            "version": {
              "type": "string"
            }
          },
          "required": [
            "timestamp",
            "version"
          ]
        }
      },
      "required": [
        "success",
        "data"
      ]
    }
  },
  {
    "id": "put-_api_v1_contractlines_id",
    "method": "put",
    "path": "/api/v1/contract-lines/{id}",
    "displayName": "Update contract line",
    "summary": "Update contract line",
    "description": "Updates a contract line by contract_line_id using updateContractLineSchema validation.",
    "tags": [
      "Contract Lines"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Contract line UUID from contract_lines.contract_line_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Contract line UUID from contract_lines.contract_line_id."
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "contract_line_name": {
          "type": "string",
          "minLength": 1,
          "maxLength": 255
        },
        "billing_frequency": {
          "type": "string",
          "enum": [
            "weekly",
            "bi-weekly",
            "monthly",
            "quarterly",
            "semi-annually",
            "annually"
          ]
        },
        "is_custom": {
          "type": "boolean"
        },
        "service_category": {
          "type": "string"
        },
        "contract_line_type": {
          "type": "string",
          "enum": [
            "Fixed",
            "Hourly",
            "Usage"
          ]
        },
        "cadence_owner": {
          "type": "string",
          "enum": [
            "client",
            "contract"
          ]
        },
        "hourly_rate": {
          "type": "number",
          "minimum": 0
        },
        "minimum_billable_time": {
          "type": "number",
          "minimum": 0
        },
        "round_up_to_nearest": {
          "type": "number",
          "minimum": 1
        },
        "enable_overtime": {
          "type": "boolean"
        },
        "overtime_rate": {
          "type": "number",
          "minimum": 0
        },
        "overtime_threshold": {
          "type": "number",
          "minimum": 0
        },
        "enable_after_hours_rate": {
          "type": "boolean"
        },
        "after_hours_multiplier": {
          "type": "number",
          "minimum": 0
        },
        "is_active": {
          "type": "boolean"
        },
        "features": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "location_id": {
          "type": [
            "string",
            "null"
          ],
          "format": "uuid"
        }
      }
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "success": {
          "type": "boolean",
          "enum": [
            true
          ]
        },
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "properties": {
            "timestamp": {
              "type": "string",
              "format": "date-time"
            },
            "version": {
              "type": "string"
            }
          },
          "required": [
            "timestamp",
            "version"
          ]
        }
      },
      "required": [
        "success",
        "data"
      ]
    }
  },
  {
    "id": "delete-_api_v1_contractlines_id",
    "method": "delete",
    "path": "/api/v1/contract-lines/{id}",
    "displayName": "Delete contract line",
    "summary": "Delete contract line",
    "description": "Deletes a contract line after dependency checks (in-use checks, service cleanup, contract detach).",
    "tags": [
      "Contract Lines"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Contract line UUID from contract_lines.contract_line_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Contract line UUID from contract_lines.contract_line_id."
        }
      }
    ]
  },
  {
    "id": "post-_api_v1_contractlines_bulk",
    "method": "post",
    "path": "/api/v1/contract-lines/bulk",
    "displayName": "Bulk create contract lines",
    "summary": "Bulk create contract lines",
    "description": "Alias route to bulkCreateContractLines; creates multiple contract lines from `plans` array.",
    "tags": [
      "Contract Lines"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "plans": {
          "type": "array",
          "items": {
            "$ref": "#/components/schemas/ContractLineBody"
          },
          "minItems": 1,
          "maxItems": 50
        }
      },
      "required": [
        "plans"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "success": {
          "type": "boolean",
          "enum": [
            true
          ]
        },
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "properties": {
            "timestamp": {
              "type": "string",
              "format": "date-time"
            },
            "version": {
              "type": "string"
            }
          },
          "required": [
            "timestamp",
            "version"
          ]
        }
      },
      "required": [
        "success",
        "data"
      ]
    }
  },
  {
    "id": "put-_api_v1_contractlines_bulk",
    "method": "put",
    "path": "/api/v1/contract-lines/bulk",
    "displayName": "Bulk update contract lines",
    "summary": "Bulk update contract lines",
    "description": "Alias route to bulkUpdateContractLines; updates multiple rows by contract_line_id.",
    "tags": [
      "Contract Lines"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "plans": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "contract_line_id": {
                "type": "string",
                "format": "uuid"
              },
              "data": {
                "$ref": "#/components/schemas/UpdateContractLineBody"
              }
            },
            "required": [
              "contract_line_id",
              "data"
            ]
          },
          "minItems": 1,
          "maxItems": 50
        }
      },
      "required": [
        "plans"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "success": {
          "type": "boolean",
          "enum": [
            true
          ]
        },
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "properties": {
            "timestamp": {
              "type": "string",
              "format": "date-time"
            },
            "version": {
              "type": "string"
            }
          },
          "required": [
            "timestamp",
            "version"
          ]
        }
      },
      "required": [
        "success",
        "data"
      ]
    }
  },
  {
    "id": "delete-_api_v1_contractlines_bulk",
    "method": "delete",
    "path": "/api/v1/contract-lines/bulk",
    "displayName": "Bulk delete contract lines",
    "summary": "Bulk delete contract lines",
    "description": "Alias route to bulkDeleteContractLines; deletes multiple contract lines by ID list.",
    "tags": [
      "Contract Lines"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "contract_line_ids": {
          "type": "array",
          "items": {
            "type": "string",
            "format": "uuid"
          },
          "minItems": 1,
          "maxItems": 50
        }
      },
      "required": [
        "contract_line_ids"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "success": {
          "type": "boolean",
          "enum": [
            true
          ]
        },
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "properties": {
            "timestamp": {
              "type": "string",
              "format": "date-time"
            },
            "version": {
              "type": "string"
            }
          },
          "required": [
            "timestamp",
            "version"
          ]
        }
      },
      "required": [
        "success",
        "data"
      ]
    }
  },
  {
    "id": "post-_api_v1_contractlines_bulk_create",
    "method": "post",
    "path": "/api/v1/contract-lines/bulk/create",
    "displayName": "Bulk create contract lines (explicit route)",
    "summary": "Bulk create contract lines (explicit route)",
    "description": "Same controller behavior as POST /api/v1/contract-lines/bulk.",
    "tags": [
      "Contract Lines"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "plans": {
          "type": "array",
          "items": {
            "$ref": "#/components/schemas/ContractLineBody"
          },
          "minItems": 1,
          "maxItems": 50
        }
      },
      "required": [
        "plans"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "success": {
          "type": "boolean",
          "enum": [
            true
          ]
        },
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "properties": {
            "timestamp": {
              "type": "string",
              "format": "date-time"
            },
            "version": {
              "type": "string"
            }
          },
          "required": [
            "timestamp",
            "version"
          ]
        }
      },
      "required": [
        "success",
        "data"
      ]
    }
  },
  {
    "id": "put-_api_v1_contractlines_bulk_update",
    "method": "put",
    "path": "/api/v1/contract-lines/bulk/update",
    "displayName": "Bulk update contract lines (explicit route)",
    "summary": "Bulk update contract lines (explicit route)",
    "description": "Same controller behavior as PUT /api/v1/contract-lines/bulk.",
    "tags": [
      "Contract Lines"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "plans": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "contract_line_id": {
                "type": "string",
                "format": "uuid"
              },
              "data": {
                "$ref": "#/components/schemas/UpdateContractLineBody"
              }
            },
            "required": [
              "contract_line_id",
              "data"
            ]
          },
          "minItems": 1,
          "maxItems": 50
        }
      },
      "required": [
        "plans"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "success": {
          "type": "boolean",
          "enum": [
            true
          ]
        },
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "properties": {
            "timestamp": {
              "type": "string",
              "format": "date-time"
            },
            "version": {
              "type": "string"
            }
          },
          "required": [
            "timestamp",
            "version"
          ]
        }
      },
      "required": [
        "success",
        "data"
      ]
    }
  },
  {
    "id": "delete-_api_v1_contractlines_bulk_delete",
    "method": "delete",
    "path": "/api/v1/contract-lines/bulk/delete",
    "displayName": "Bulk delete contract lines (explicit route)",
    "summary": "Bulk delete contract lines (explicit route)",
    "description": "Same controller behavior as DELETE /api/v1/contract-lines/bulk.",
    "tags": [
      "Contract Lines"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "contract_line_ids": {
          "type": "array",
          "items": {
            "type": "string",
            "format": "uuid"
          },
          "minItems": 1,
          "maxItems": 50
        }
      },
      "required": [
        "contract_line_ids"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "success": {
          "type": "boolean",
          "enum": [
            true
          ]
        },
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "properties": {
            "timestamp": {
              "type": "string",
              "format": "date-time"
            },
            "version": {
              "type": "string"
            }
          },
          "required": [
            "timestamp",
            "version"
          ]
        }
      },
      "required": [
        "success",
        "data"
      ]
    }
  },
  {
    "id": "post-_api_v1_contractlines_bulk_addservices",
    "method": "post",
    "path": "/api/v1/contract-lines/bulk/add-services",
    "displayName": "Bulk add services to contract line",
    "summary": "Bulk add services to contract line",
    "description": "Adds multiple services to one contract_line_id and returns per-service success/failure results.",
    "tags": [
      "Contract Lines"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "contract_line_id": {
          "type": "string",
          "format": "uuid"
        },
        "services": {
          "type": "array",
          "items": {
            "$ref": "#/components/schemas/ContractLineAddServiceBody"
          },
          "minItems": 1,
          "maxItems": 20
        }
      },
      "required": [
        "contract_line_id",
        "services"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "success": {
          "type": "boolean",
          "enum": [
            true
          ]
        },
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "properties": {
            "timestamp": {
              "type": "string",
              "format": "date-time"
            },
            "version": {
              "type": "string"
            }
          },
          "required": [
            "timestamp",
            "version"
          ]
        }
      },
      "required": [
        "success",
        "data"
      ]
    }
  },
  {
    "id": "delete-_api_v1_contractlines_bulk_removeservices",
    "method": "delete",
    "path": "/api/v1/contract-lines/bulk/remove-services",
    "displayName": "Bulk remove services from contract line",
    "summary": "Bulk remove services from contract line",
    "description": "Removes multiple services from one contract_line_id and returns per-service success/failure results.",
    "tags": [
      "Contract Lines"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "contract_line_id": {
          "type": "string",
          "format": "uuid"
        },
        "service_ids": {
          "type": "array",
          "items": {
            "type": "string",
            "format": "uuid"
          },
          "minItems": 1,
          "maxItems": 20
        }
      },
      "required": [
        "contract_line_id",
        "service_ids"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "success": {
          "type": "boolean",
          "enum": [
            true
          ]
        },
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "properties": {
            "timestamp": {
              "type": "string",
              "format": "date-time"
            },
            "version": {
              "type": "string"
            }
          },
          "required": [
            "timestamp",
            "version"
          ]
        }
      },
      "required": [
        "success",
        "data"
      ]
    }
  },
  {
    "id": "put-_api_v1_contractlines_id_activation",
    "method": "put",
    "path": "/api/v1/contract-lines/{id}/activation",
    "displayName": "Set contract line activation",
    "summary": "Set contract line activation",
    "description": "Activates or deactivates a contract line. Deactivation can require a reason when plan is in use.",
    "tags": [
      "Contract Lines"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Contract line UUID from contract_lines.contract_line_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Contract line UUID from contract_lines.contract_line_id."
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "is_active": {
          "type": "boolean"
        },
        "effective_date": {
          "type": "string",
          "format": "date-time"
        },
        "reason": {
          "type": "string"
        },
        "notify_clients": {
          "type": "boolean"
        }
      },
      "required": [
        "is_active"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "success": {
          "type": "boolean",
          "enum": [
            true
          ]
        },
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "properties": {
            "timestamp": {
              "type": "string",
              "format": "date-time"
            },
            "version": {
              "type": "string"
            }
          },
          "required": [
            "timestamp",
            "version"
          ]
        }
      },
      "required": [
        "success",
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_contractlines_id_analytics",
    "method": "get",
    "path": "/api/v1/contract-lines/{id}/analytics",
    "displayName": "Get contract line analytics",
    "summary": "Get contract line analytics",
    "description": "Returns analytics aggregates for one contract line.",
    "tags": [
      "Contract Lines"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Contract line UUID from contract_lines.contract_line_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Contract line UUID from contract_lines.contract_line_id."
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "success": {
          "type": "boolean",
          "enum": [
            true
          ]
        },
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "properties": {
            "timestamp": {
              "type": "string",
              "format": "date-time"
            },
            "version": {
              "type": "string"
            }
          },
          "required": [
            "timestamp",
            "version"
          ]
        }
      },
      "required": [
        "success",
        "data"
      ]
    }
  },
  {
    "id": "post-_api_v1_contractlines_id_copy",
    "method": "post",
    "path": "/api/v1/contract-lines/{id}/copy",
    "displayName": "Copy contract line",
    "summary": "Copy contract line",
    "description": "Copies an existing contract line. Current implementation validates and uses `source_contract_line_id` from body, while path `{id}` is not consumed by service logic.",
    "tags": [
      "Contract Lines"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Contract line UUID from contract_lines.contract_line_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Contract line UUID from contract_lines.contract_line_id."
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "source_contract_line_id": {
          "type": "string",
          "format": "uuid",
          "description": "Used by service; path id is currently ignored."
        },
        "new_contract_line_name": {
          "type": "string",
          "minLength": 1,
          "maxLength": 255
        },
        "copy_services": {
          "type": "boolean"
        },
        "copy_configurations": {
          "type": "boolean"
        },
        "modify_rates": {
          "type": "object",
          "properties": {
            "percentage_change": {
              "type": "number"
            },
            "fixed_adjustment": {
              "type": "number"
            }
          }
        }
      },
      "required": [
        "source_contract_line_id",
        "new_contract_line_name"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "success": {
          "type": "boolean",
          "enum": [
            true
          ]
        },
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "properties": {
            "timestamp": {
              "type": "string",
              "format": "date-time"
            },
            "version": {
              "type": "string"
            }
          },
          "required": [
            "timestamp",
            "version"
          ]
        }
      },
      "required": [
        "success",
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_contractlines_id_fixedconfig",
    "method": "get",
    "path": "/api/v1/contract-lines/{id}/fixed-config",
    "displayName": "Get fixed contract line config",
    "summary": "Get fixed contract line config",
    "description": "Returns fixed-plan configuration for a contract line; returns 404 when not found.",
    "tags": [
      "Contract Lines"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Contract line UUID from contract_lines.contract_line_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Contract line UUID from contract_lines.contract_line_id."
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "success": {
          "type": "boolean",
          "enum": [
            true
          ]
        },
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "properties": {
            "timestamp": {
              "type": "string",
              "format": "date-time"
            },
            "version": {
              "type": "string"
            }
          },
          "required": [
            "timestamp",
            "version"
          ]
        }
      },
      "required": [
        "success",
        "data"
      ]
    }
  },
  {
    "id": "put-_api_v1_contractlines_id_fixedconfig",
    "method": "put",
    "path": "/api/v1/contract-lines/{id}/fixed-config",
    "displayName": "Upsert fixed contract line config",
    "summary": "Upsert fixed contract line config",
    "description": "Creates or updates fixed-plan configuration for a contract line.",
    "tags": [
      "Contract Lines"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Contract line UUID from contract_lines.contract_line_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Contract line UUID from contract_lines.contract_line_id."
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "base_rate": {
          "type": "number",
          "minimum": 0
        },
        "enable_proration": {
          "type": "boolean"
        },
        "billing_cycle_alignment": {
          "type": "string",
          "enum": [
            "start",
            "end",
            "prorated"
          ]
        }
      }
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "success": {
          "type": "boolean",
          "enum": [
            true
          ]
        },
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "properties": {
            "timestamp": {
              "type": "string",
              "format": "date-time"
            },
            "version": {
              "type": "string"
            }
          },
          "required": [
            "timestamp",
            "version"
          ]
        }
      },
      "required": [
        "success",
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_contractlines_id_services",
    "method": "get",
    "path": "/api/v1/contract-lines/{id}/services",
    "displayName": "List contract line services",
    "summary": "List contract line services",
    "description": "Returns all service configurations linked to a contract line.",
    "tags": [
      "Contract Lines"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Contract line UUID from contract_lines.contract_line_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Contract line UUID from contract_lines.contract_line_id."
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "success": {
          "type": "boolean",
          "enum": [
            true
          ]
        },
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "properties": {
            "timestamp": {
              "type": "string",
              "format": "date-time"
            },
            "version": {
              "type": "string"
            }
          },
          "required": [
            "timestamp",
            "version"
          ]
        }
      },
      "required": [
        "success",
        "data"
      ]
    }
  },
  {
    "id": "post-_api_v1_contractlines_id_services",
    "method": "post",
    "path": "/api/v1/contract-lines/{id}/services",
    "displayName": "Add service to contract line",
    "summary": "Add service to contract line",
    "description": "Adds one service configuration to a contract line; rejects duplicates.",
    "tags": [
      "Contract Lines"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Contract line UUID from contract_lines.contract_line_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Contract line UUID from contract_lines.contract_line_id."
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "service_id": {
          "type": "string",
          "format": "uuid"
        },
        "quantity": {
          "type": "number",
          "minimum": 1
        },
        "custom_rate": {
          "type": "number",
          "minimum": 0
        },
        "configuration_type": {
          "type": "string",
          "enum": [
            "Fixed",
            "Hourly",
            "Usage",
            "Bucket"
          ]
        },
        "type_config": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "service_id"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "success": {
          "type": "boolean",
          "enum": [
            true
          ]
        },
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "properties": {
            "timestamp": {
              "type": "string",
              "format": "date-time"
            },
            "version": {
              "type": "string"
            }
          },
          "required": [
            "timestamp",
            "version"
          ]
        }
      },
      "required": [
        "success",
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_contractlines_id_services_serviceid",
    "method": "get",
    "path": "/api/v1/contract-lines/{id}/services/{serviceId}",
    "displayName": "Get contract line service details",
    "summary": "Get contract line service details",
    "description": "Route inventory advertises item lookup, but current route handler delegates to getContractLineServices and returns the full service list for `{id}`; `{serviceId}` is effectively ignored in the GET path.",
    "tags": [
      "Contract Lines"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Contract line UUID from contract_lines.contract_line_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Contract line UUID from contract_lines.contract_line_id."
        }
      },
      {
        "name": "serviceId",
        "in": "path",
        "required": true,
        "description": "Service UUID from service_catalog.service_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Service UUID from service_catalog.service_id."
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "success": {
          "type": "boolean",
          "enum": [
            true
          ]
        },
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "properties": {
            "timestamp": {
              "type": "string",
              "format": "date-time"
            },
            "version": {
              "type": "string"
            }
          },
          "required": [
            "timestamp",
            "version"
          ]
        }
      },
      "required": [
        "success",
        "data"
      ]
    }
  },
  {
    "id": "put-_api_v1_contractlines_id_services_serviceid",
    "method": "put",
    "path": "/api/v1/contract-lines/{id}/services/{serviceId}",
    "displayName": "Update contract line service",
    "summary": "Update contract line service",
    "description": "Updates service configuration for one `{id}` + `{serviceId}` pair.",
    "tags": [
      "Contract Lines"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Contract line UUID from contract_lines.contract_line_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Contract line UUID from contract_lines.contract_line_id."
        }
      },
      {
        "name": "serviceId",
        "in": "path",
        "required": true,
        "description": "Service UUID from service_catalog.service_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Service UUID from service_catalog.service_id."
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "quantity": {
          "type": "number",
          "minimum": 1
        },
        "custom_rate": {
          "type": "number",
          "minimum": 0
        },
        "type_config": {
          "type": "object",
          "additionalProperties": {}
        },
        "rate_tiers": {
          "type": "array",
          "items": {
            "type": "object",
            "additionalProperties": {}
          }
        },
        "user_type_rates": {
          "type": "array",
          "items": {
            "type": "object",
            "additionalProperties": {}
          }
        }
      }
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "success": {
          "type": "boolean",
          "enum": [
            true
          ]
        },
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "properties": {
            "timestamp": {
              "type": "string",
              "format": "date-time"
            },
            "version": {
              "type": "string"
            }
          },
          "required": [
            "timestamp",
            "version"
          ]
        }
      },
      "required": [
        "success",
        "data"
      ]
    }
  },
  {
    "id": "delete-_api_v1_contractlines_id_services_serviceid",
    "method": "delete",
    "path": "/api/v1/contract-lines/{id}/services/{serviceId}",
    "displayName": "Remove service from contract line",
    "summary": "Remove service from contract line",
    "description": "Removes one service configuration from a contract line.",
    "tags": [
      "Contract Lines"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Contract line UUID from contract_lines.contract_line_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Contract line UUID from contract_lines.contract_line_id."
        }
      },
      {
        "name": "serviceId",
        "in": "path",
        "required": true,
        "description": "Service UUID from service_catalog.service_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Service UUID from service_catalog.service_id."
        }
      }
    ]
  },
  {
    "id": "get-_api_v1_contractlines_id_usagemetrics",
    "method": "get",
    "path": "/api/v1/contract-lines/{id}/usage-metrics",
    "displayName": "Get contract line usage metrics",
    "summary": "Get contract line usage metrics",
    "description": "Returns usage and cost metrics for a contract line over a time window.",
    "tags": [
      "Contract Lines"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Contract line UUID from contract_lines.contract_line_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Contract line UUID from contract_lines.contract_line_id."
        }
      },
      {
        "name": "period_start",
        "in": "query",
        "required": false,
        "description": "Defaults to now minus 30 days when omitted.",
        "schema": {
          "type": "string",
          "format": "date-time",
          "description": "Defaults to now minus 30 days when omitted."
        }
      },
      {
        "name": "period_end",
        "in": "query",
        "required": false,
        "description": "Defaults to now when omitted.",
        "schema": {
          "type": "string",
          "format": "date-time",
          "description": "Defaults to now when omitted."
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "success": {
          "type": "boolean",
          "enum": [
            true
          ]
        },
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "properties": {
            "timestamp": {
              "type": "string",
              "format": "date-time"
            },
            "version": {
              "type": "string"
            }
          },
          "required": [
            "timestamp",
            "version"
          ]
        }
      },
      "required": [
        "success",
        "data"
      ]
    }
  },
  {
    "id": "post-_api_v1_contractlinetemplates",
    "method": "post",
    "path": "/api/v1/contract-line-templates",
    "displayName": "Create contract line template",
    "summary": "Create contract line template",
    "description": "Creates a plan template record under plan_templates with optional default services.",
    "tags": [
      "Contract Lines"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "template_name": {
          "type": "string",
          "minLength": 1,
          "maxLength": 255
        },
        "template_description": {
          "type": "string"
        },
        "contract_line_type": {
          "type": "string",
          "enum": [
            "Fixed",
            "Hourly",
            "Usage"
          ]
        },
        "billing_frequency": {
          "type": "string",
          "enum": [
            "weekly",
            "bi-weekly",
            "monthly",
            "quarterly",
            "semi-annually",
            "annually"
          ]
        },
        "default_services": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "service_id": {
                "type": "string",
                "format": "uuid"
              },
              "configuration_type": {
                "type": "string",
                "enum": [
                  "Fixed",
                  "Hourly",
                  "Usage",
                  "Bucket"
                ]
              },
              "default_rate": {
                "type": "number",
                "minimum": 0
              },
              "quantity": {
                "type": "number",
                "minimum": 1
              }
            },
            "required": [
              "service_id",
              "configuration_type"
            ]
          }
        },
        "is_public": {
          "type": "boolean"
        }
      },
      "required": [
        "template_name",
        "contract_line_type",
        "billing_frequency"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "success": {
          "type": "boolean",
          "enum": [
            true
          ]
        },
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "properties": {
            "timestamp": {
              "type": "string",
              "format": "date-time"
            },
            "version": {
              "type": "string"
            }
          },
          "required": [
            "timestamp",
            "version"
          ]
        }
      },
      "required": [
        "success",
        "data"
      ]
    }
  },
  {
    "id": "post-_api_v1_contractlinetemplates_id_createcontractline",
    "method": "post",
    "path": "/api/v1/contract-line-templates/{id}/create-contract-line",
    "displayName": "Create contract line from template",
    "summary": "Create contract line from template",
    "description": "Creates a contract line from a template. The template id is taken from the path `{id}` (it takes precedence over any template_id in the body), and the rest of the body is validated with createPlanFromTemplateSchema. Authenticated and tenant-scoped via withApiKeyRouteAuth.",
    "tags": [
      "Contract Lines"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Template UUID from plan_templates.template_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Template UUID from plan_templates.template_id."
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "template_id": {
          "type": "string",
          "format": "uuid",
          "description": "Optional; the template id is taken from the path {id} and overrides this field when both are present."
        },
        "contract_line_name": {
          "type": "string",
          "minLength": 1,
          "maxLength": 255
        },
        "modify_rates": {
          "type": "object",
          "properties": {
            "percentage_change": {
              "type": "number"
            },
            "fixed_adjustment": {
              "type": "number"
            }
          }
        },
        "override_services": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "service_id": {
                "type": "string",
                "format": "uuid"
              },
              "custom_rate": {
                "type": "number",
                "minimum": 0
              },
              "quantity": {
                "type": "number",
                "minimum": 1
              }
            },
            "required": [
              "service_id"
            ]
          }
        }
      },
      "required": [
        "contract_line_name"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "success": {
          "type": "boolean",
          "enum": [
            true
          ]
        },
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "properties": {
            "timestamp": {
              "type": "string",
              "format": "date-time"
            },
            "version": {
              "type": "string"
            }
          },
          "required": [
            "timestamp",
            "version"
          ]
        }
      },
      "required": [
        "success",
        "data"
      ]
    }
  },
  {
    "id": "get-_api_documents_download_fileid",
    "method": "get",
    "path": "/api/documents/download/{fileId}",
    "displayName": "Download or export document file",
    "summary": "Download or export document file",
    "description": "Downloads a stored document file, or exports the document as PDF or Markdown based on the optional format query parameter. The fileId path value may be either a documents.document_id or an external_files.file_id. The route requires an Auth.js session cookie and runs within the session tenant. The normal download path uses document read permission and document authorization rules; PDF and Markdown export paths perform tenant-scoped document lookup and generation.",
    "tags": [
      "Documents"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "fileId",
        "in": "path",
        "required": true,
        "description": "Document UUID or file UUID. The download handler resolves document_id first, then file_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Document UUID or file UUID. The download handler resolves document_id first, then file_id."
        }
      },
      {
        "name": "format",
        "in": "query",
        "required": false,
        "description": "Optional export format. pdf generates a PDF; markdown or md exports markdown; omitted downloads the original stored file.",
        "schema": {
          "type": "string",
          "enum": [
            "pdf",
            "markdown",
            "md"
          ],
          "description": "Optional export format. pdf generates a PDF; markdown or md exports markdown; omitted downloads the original stored file."
        }
      }
    ]
  },
  {
    "id": "get-_api_documents_documentid_download",
    "method": "get",
    "path": "/api/documents/{documentId}/download",
    "displayName": "Download document attachment",
    "summary": "Download document attachment",
    "description": "Downloads the original stored file for a document as an attachment. The documentId path value is resolved against documents.document_id first, then documents.file_id. The route supports Auth.js session-cookie authentication and x-api-key fallback for machine clients, derives the tenant from the authenticated principal, requires document:read permission, and runs document authorization rules before reading the file from storage.",
    "tags": [
      "Documents"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "documentId",
        "in": "path",
        "required": true,
        "description": "Document UUID from documents.document_id, or file UUID from documents.file_id. The handler resolves document_id first and falls back to file_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Document UUID from documents.document_id, or file UUID from documents.file_id. The handler resolves document_id first and falls back to file_id."
        }
      },
      {
        "name": "x-api-key",
        "in": "header",
        "required": false,
        "description": "Optional API key for machine-to-machine download requests. Used only when no valid Auth.js session cookie is present.",
        "schema": {
          "type": "string",
          "description": "Optional API key for machine-to-machine download requests. Used only when no valid Auth.js session cookie is present."
        }
      }
    ]
  },
  {
    "id": "get-_api_documents_view_fileid",
    "method": "get",
    "path": "/api/documents/view/{fileId}",
    "displayName": "View document file inline",
    "summary": "View document file inline",
    "description": "Streams a stored file for inline browser viewing, such as images, videos, PDFs, and SVGs. Tenant logo files are public. Other files require either a valid Auth.js session cookie or an x-api-key header, then document-level authorization is checked using RBAC, relationship rules, bundle narrowing, and client visibility rules. Video files support HTTP Range requests and may return 206 Partial Content.",
    "tags": [
      "Documents"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "fileId",
        "in": "path",
        "required": true,
        "description": "File UUID from external_files.file_id identifying the stored file to serve.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "File UUID from external_files.file_id identifying the stored file to serve."
        }
      },
      {
        "name": "range",
        "in": "header",
        "required": false,
        "description": "HTTP Range header for partial video responses, for example bytes=0-1048575. Only honored for video/* files.",
        "schema": {
          "type": "string",
          "description": "HTTP Range header for partial video responses, for example bytes=0-1048575. Only honored for video/* files."
        }
      },
      {
        "name": "x-api-key",
        "in": "header",
        "required": false,
        "description": "Optional API key fallback for non-browser clients. Used only when no valid session cookie is present.",
        "schema": {
          "type": "string",
          "description": "Optional API key fallback for non-browser clients. Used only when no valid session cookie is present."
        }
      }
    ]
  },
  {
    "id": "post-_api_email_oauth_initiate",
    "method": "post",
    "path": "/api/email/oauth/initiate",
    "displayName": "Initiate email OAuth flow",
    "summary": "Initiate email OAuth flow",
    "description": "Starts the OAuth 2.0 authorization flow for a Google or Microsoft email provider. Requires a valid Auth.js session cookie. The handler builds secure OAuth state containing tenant, user, providerId, redirect URI, timestamp, and nonce, resolves the provider client ID from configured secrets, and returns the authorization URL for the browser to visit.",
    "tags": [
      "Email"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "provider": {
          "type": "string",
          "enum": [
            "microsoft",
            "google"
          ],
          "description": "Email OAuth provider to authorize."
        },
        "redirectUri": {
          "type": "string",
          "format": "uri",
          "description": "Optional OAuth callback URI. If omitted, the server builds /api/auth/{provider}/callback from the configured base URL."
        },
        "providerId": {
          "type": "string",
          "format": "uuid",
          "description": "Email provider configuration ID to carry through OAuth state and use during callback token persistence."
        }
      },
      "required": [
        "provider"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "success": {
          "type": "boolean",
          "enum": [
            true
          ],
          "description": "OAuth initiation succeeded."
        },
        "authUrl": {
          "type": "string",
          "format": "uri",
          "description": "Provider authorization URL for the browser to visit."
        },
        "provider": {
          "type": "string",
          "enum": [
            "microsoft",
            "google"
          ],
          "description": "Email OAuth provider being authorized."
        },
        "state": {
          "type": "string",
          "description": "Base64-encoded OAuth state containing tenant, userId, providerId, redirectUri, timestamp, nonce, and hosted flag."
        }
      },
      "required": [
        "success",
        "authUrl",
        "provider",
        "state"
      ]
    }
  },
  {
    "id": "post-_api_email_refreshwatch",
    "method": "post",
    "path": "/api/email/refresh-watch",
    "displayName": "Refresh Gmail watch registration",
    "summary": "Refresh Gmail watch registration",
    "description": "Forces Pub/Sub setup and Gmail watch registration refresh for an active Google email provider. Requires a valid Auth.js session. The providerId must reference email_providers.id for a provider_type=google record with a google_email_provider_config row and project_id. Internally this calls configureGmailProvider with force=true.",
    "tags": [
      "Email"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "providerId": {
          "type": "string",
          "format": "uuid",
          "description": "Active Gmail email provider ID from email_providers.id to refresh."
        }
      },
      "required": [
        "providerId"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "success": {
          "type": "boolean",
          "enum": [
            true
          ],
          "description": "Refresh completed successfully."
        },
        "message": {
          "type": "string",
          "description": "Human-readable success message."
        },
        "providerId": {
          "type": "string",
          "format": "uuid",
          "description": "Email provider ID that was refreshed."
        },
        "mailbox": {
          "type": "string",
          "format": "email",
          "description": "Mailbox address for the Gmail provider."
        }
      },
      "required": [
        "success",
        "message",
        "providerId",
        "mailbox"
      ]
    }
  },
  {
    "id": "post-_api_email_webhooks_google",
    "method": "post",
    "path": "/api/email/webhooks/google",
    "displayName": "Receive Google Gmail Pub/Sub webhook",
    "summary": "Receive Google Gmail Pub/Sub webhook",
    "description": "Receives Google Pub/Sub push notifications for Gmail watches. Standard session and API-key middleware are bypassed; the handler requires an Authorization: Bearer Google-signed JWT, decodes the Pub/Sub message data into a Gmail notification with emailAddress and historyId, resolves the tenant and email provider by subscription name or mailbox, validates Google configuration, and enqueues a pointer-only job into the unified inbound email queue. It does not fetch or return email content.",
    "tags": [
      "Email"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "message": {
          "$ref": "#/components/schemas/GooglePubSubMessage"
        },
        "subscription": {
          "type": "string",
          "description": "Full Pub/Sub subscription path, such as projects/{project}/subscriptions/{subscriptionName}."
        }
      },
      "required": [
        "message",
        "subscription"
      ]
    },
    "responseBodySchema": {
      "anyOf": [
        {
          "$ref": "#/components/schemas/GoogleWebhookEnqueueResponse"
        },
        {
          "$ref": "#/components/schemas/GoogleWebhookSkippedResponse"
        }
      ]
    }
  },
  {
    "id": "get-_api_email_webhooks_microsoft",
    "method": "get",
    "path": "/api/email/webhooks/microsoft",
    "displayName": "Validate Microsoft email webhook subscription",
    "summary": "Validate Microsoft email webhook subscription",
    "description": "Microsoft Graph subscription validation endpoint. During subscription creation or renewal, Microsoft calls this endpoint with validationtoken or validationToken. The handler echoes the token verbatim as text/plain. If no token is provided, it returns OK. No session, API key, tenant header, or request body is required.",
    "tags": [
      "Email"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "validationtoken",
        "in": "query",
        "required": false,
        "description": "Microsoft Graph subscription validation token. The handler also accepts validationToken with camel-case spelling.",
        "schema": {
          "type": "string",
          "description": "Microsoft Graph subscription validation token. The handler also accepts validationToken with camel-case spelling."
        }
      },
      {
        "name": "validationToken",
        "in": "query",
        "required": false,
        "description": "Camel-case variant of the Microsoft Graph validation token.",
        "schema": {
          "type": "string",
          "description": "Camel-case variant of the Microsoft Graph validation token."
        }
      }
    ]
  },
  {
    "id": "post-_api_email_webhooks_microsoft",
    "method": "post",
    "path": "/api/email/webhooks/microsoft",
    "displayName": "Receive Microsoft Graph email webhook",
    "summary": "Receive Microsoft Graph email webhook",
    "description": "Receives Microsoft Graph change notifications for monitored mailboxes. Standard session and API-key middleware are bypassed. The handler supports validation token echo, parses Microsoft notification batches, resolves provider and tenant by matching notification subscriptionId to microsoft_email_provider_config.webhook_subscription_id, validates clientState against the stored webhook_verification_token when configured, extracts message IDs, and enqueues pointer-only jobs into the unified inbound email queue. The tenantId in the Microsoft payload is informational and is not trusted for tenant resolution.",
    "tags": [
      "Email"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "validationtoken",
        "in": "query",
        "required": false,
        "description": "Microsoft Graph subscription validation token. The handler also accepts validationToken with camel-case spelling.",
        "schema": {
          "type": "string",
          "description": "Microsoft Graph subscription validation token. The handler also accepts validationToken with camel-case spelling."
        }
      },
      {
        "name": "validationToken",
        "in": "query",
        "required": false,
        "description": "Camel-case variant of the Microsoft Graph validation token.",
        "schema": {
          "type": "string",
          "description": "Camel-case variant of the Microsoft Graph validation token."
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "value": {
          "type": "array",
          "items": {
            "$ref": "#/components/schemas/MicrosoftGraphNotification"
          },
          "description": "Batch of Microsoft Graph change notifications."
        }
      },
      "required": [
        "value"
      ]
    },
    "responseBodySchema": {
      "anyOf": [
        {
          "$ref": "#/components/schemas/MicrosoftWebhookSuccessResponse"
        },
        {
          "$ref": "#/components/schemas/MicrosoftWebhookEmptyResponse"
        },
        {
          "$ref": "#/components/schemas/MicrosoftWebhookTextResponse"
        }
      ]
    }
  },
  {
    "id": "post-_api_email_webhooks_test",
    "method": "post",
    "path": "/api/email/webhooks/test",
    "displayName": "Publish test inbound email event",
    "summary": "Publish test inbound email event",
    "description": "Publishes a synthetic INBOUND_EMAIL_RECEIVED event to the workflow event stream so operators can test webhook and workflow delivery without a real provider notification. Requires a valid Auth.js session; tenant is taken from the authenticated user session. The route performs no RBAC check and does not require an API key.",
    "tags": [
      "Email"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "provider": {
          "type": "string",
          "enum": [
            "microsoft",
            "google"
          ],
          "description": "Email provider type to simulate in the synthetic inbound email event. Defaults to microsoft."
        },
        "messageId": {
          "type": "string",
          "description": "Synthetic message identifier to include in the test event. Defaults to test-message-123."
        }
      }
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "success": {
          "type": "boolean",
          "enum": [
            true
          ],
          "description": "Test event was published successfully."
        },
        "message": {
          "type": "string",
          "description": "Human-readable success message."
        },
        "eventId": {
          "type": "string",
          "description": "Redis Streams event ID returned by publishEvent."
        },
        "tenant": {
          "type": "string",
          "description": "Tenant identifier from the authenticated user session."
        }
      },
      "required": [
        "success",
        "message",
        "eventId",
        "tenant"
      ]
    }
  },
  {
    "id": "get-_api_ext_extensionid_path",
    "method": "get",
    "path": "/api/ext/{extensionId}/{path}",
    "displayName": "Forward GET request to extension runner",
    "summary": "Forward GET request to extension runner",
    "description": "Tenant-scoped extension gateway endpoint that forwards GET requests to an installed extension runner. The gateway resolves the tenant from x-alga-tenant, x-tenant-id, session cookie, or DEV_TENANT_ID in development; verifies the extension is installed and enabled for that tenant; forwards selected headers and all query parameters to RUNNER_BASE_URL /v1/execute; and relays the runner response. GET requests do not read a body and do not generate an idempotency key. The gateway currently has a placeholder access check and does not enforce per-extension RBAC beyond tenant install resolution.",
    "tags": [
      "Extension Gateway"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "extensionId",
        "in": "path",
        "required": true,
        "description": "Extension identifier from the URL. This may be a registry/install UUID or a publisher.name slug, resolved case-insensitively.",
        "schema": {
          "type": "string",
          "minLength": 1,
          "description": "Extension identifier from the URL. This may be a registry/install UUID or a publisher.name slug, resolved case-insensitively."
        }
      },
      {
        "name": "path",
        "in": "path",
        "required": false,
        "description": "Remaining extension endpoint path after extensionId. The gateway forwards this path to the runner unchanged.",
        "schema": {
          "type": "string",
          "description": "Remaining extension endpoint path after extensionId. The gateway forwards this path to the runner unchanged."
        }
      },
      {
        "name": "x-request-id",
        "in": "header",
        "required": false,
        "description": "Optional request ID. The gateway generates a UUID when absent and forwards it to the runner.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Optional request ID. The gateway generates a UUID when absent and forwards it to the runner."
        }
      },
      {
        "name": "x-idempotency-key",
        "in": "header",
        "required": false,
        "description": "Optional idempotency key for non-GET methods. The gateway falls back to x-request-id when absent and forwards the key to the runner.",
        "schema": {
          "type": "string",
          "description": "Optional idempotency key for non-GET methods. The gateway falls back to x-request-id when absent and forwards the key to the runner."
        }
      },
      {
        "name": "x-alga-tenant",
        "in": "header",
        "required": false,
        "description": "Internal tenant header used for tenant resolution before session fallback.",
        "schema": {
          "type": "string",
          "description": "Internal tenant header used for tenant resolution before session fallback."
        }
      },
      {
        "name": "x-tenant-id",
        "in": "header",
        "required": false,
        "description": "Legacy tenant header accepted for tenant resolution before session fallback.",
        "schema": {
          "type": "string",
          "description": "Legacy tenant header accepted for tenant resolution before session fallback."
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {},
      "description": "Extension-specific response relayed from the runner. Status code, content type, and body are controlled by the extension."
    }
  },
  {
    "id": "post-_api_ext_extensionid_path",
    "method": "post",
    "path": "/api/ext/{extensionId}/{path}",
    "displayName": "Forward POST request to extension runner",
    "summary": "Forward POST request to extension runner",
    "description": "Tenant-scoped extension gateway endpoint that forwards POST requests to an installed extension runner. The gateway resolves the tenant from x-alga-tenant, x-tenant-id, session cookie, or DEV_TENANT_ID in development; verifies the extension is installed and enabled for that tenant; forwards selected headers, query parameters, and an optional opaque body to RUNNER_BASE_URL /v1/execute; and relays the runner response. For POST requests the body is limited to 10 MB, base64-encoded, and forwarded as http.body_b64. An x-idempotency-key header is forwarded when supplied, otherwise the generated x-request-id is used as the non-GET idempotency fallback. The gateway currently has a placeholder access check and does not enforce per-extension RBAC beyond tenant install resolution.",
    "tags": [
      "Extension Gateway"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "extensionId",
        "in": "path",
        "required": true,
        "description": "Extension identifier from the URL. This may be a registry/install UUID or a publisher.name slug, resolved case-insensitively.",
        "schema": {
          "type": "string",
          "minLength": 1,
          "description": "Extension identifier from the URL. This may be a registry/install UUID or a publisher.name slug, resolved case-insensitively."
        }
      },
      {
        "name": "path",
        "in": "path",
        "required": false,
        "description": "Remaining extension endpoint path after extensionId. The gateway forwards this path to the runner unchanged.",
        "schema": {
          "type": "string",
          "description": "Remaining extension endpoint path after extensionId. The gateway forwards this path to the runner unchanged."
        }
      },
      {
        "name": "x-request-id",
        "in": "header",
        "required": false,
        "description": "Optional request ID. The gateway generates a UUID when absent and forwards it to the runner.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Optional request ID. The gateway generates a UUID when absent and forwards it to the runner."
        }
      },
      {
        "name": "x-idempotency-key",
        "in": "header",
        "required": false,
        "description": "Optional idempotency key for non-GET methods. The gateway falls back to x-request-id when absent and forwards the key to the runner.",
        "schema": {
          "type": "string",
          "description": "Optional idempotency key for non-GET methods. The gateway falls back to x-request-id when absent and forwards the key to the runner."
        }
      },
      {
        "name": "x-alga-tenant",
        "in": "header",
        "required": false,
        "description": "Internal tenant header used for tenant resolution before session fallback.",
        "schema": {
          "type": "string",
          "description": "Internal tenant header used for tenant resolution before session fallback."
        }
      },
      {
        "name": "x-tenant-id",
        "in": "header",
        "required": false,
        "description": "Legacy tenant header accepted for tenant resolution before session fallback.",
        "schema": {
          "type": "string",
          "description": "Legacy tenant header accepted for tenant resolution before session fallback."
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "properties": {},
      "description": "Extension-specific request body. The gateway treats this as opaque, enforces a 10 MB limit for non-GET methods, base64-encodes it, and forwards it to the extension runner."
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {},
      "description": "Extension-specific response relayed from the runner. Status code, content type, and body are controlled by the extension."
    }
  },
  {
    "id": "put-_api_ext_extensionid_path",
    "method": "put",
    "path": "/api/ext/{extensionId}/{path}",
    "displayName": "Forward PUT request to extension runner",
    "summary": "Forward PUT request to extension runner",
    "description": "Tenant-scoped extension gateway endpoint that forwards PUT requests to an installed extension runner. The gateway resolves the tenant from x-alga-tenant, x-tenant-id, session cookie, or DEV_TENANT_ID in development; verifies the extension is installed and enabled for that tenant; forwards selected headers, query parameters, and an optional opaque body to RUNNER_BASE_URL /v1/execute; and relays the runner response. For PUT requests the body is limited to 10 MB, base64-encoded, and forwarded as http.body_b64. Clients should provide x-idempotency-key for safe retries; otherwise the gateway falls back to a generated request ID. The gateway currently has a placeholder access check and does not enforce per-extension RBAC beyond tenant install resolution.",
    "tags": [
      "Extension Gateway"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "extensionId",
        "in": "path",
        "required": true,
        "description": "Extension identifier from the URL. This may be a registry/install UUID or a publisher.name slug, resolved case-insensitively.",
        "schema": {
          "type": "string",
          "minLength": 1,
          "description": "Extension identifier from the URL. This may be a registry/install UUID or a publisher.name slug, resolved case-insensitively."
        }
      },
      {
        "name": "path",
        "in": "path",
        "required": false,
        "description": "Remaining extension endpoint path after extensionId. The gateway forwards this path to the runner unchanged.",
        "schema": {
          "type": "string",
          "description": "Remaining extension endpoint path after extensionId. The gateway forwards this path to the runner unchanged."
        }
      },
      {
        "name": "x-request-id",
        "in": "header",
        "required": false,
        "description": "Optional request ID. The gateway generates a UUID when absent and forwards it to the runner.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Optional request ID. The gateway generates a UUID when absent and forwards it to the runner."
        }
      },
      {
        "name": "x-idempotency-key",
        "in": "header",
        "required": false,
        "description": "Optional idempotency key for non-GET methods. The gateway falls back to x-request-id when absent and forwards the key to the runner.",
        "schema": {
          "type": "string",
          "description": "Optional idempotency key for non-GET methods. The gateway falls back to x-request-id when absent and forwards the key to the runner."
        }
      },
      {
        "name": "x-alga-tenant",
        "in": "header",
        "required": false,
        "description": "Internal tenant header used for tenant resolution before session fallback.",
        "schema": {
          "type": "string",
          "description": "Internal tenant header used for tenant resolution before session fallback."
        }
      },
      {
        "name": "x-tenant-id",
        "in": "header",
        "required": false,
        "description": "Legacy tenant header accepted for tenant resolution before session fallback.",
        "schema": {
          "type": "string",
          "description": "Legacy tenant header accepted for tenant resolution before session fallback."
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "properties": {},
      "description": "Extension-specific request body. The gateway treats this as opaque, enforces a 10 MB limit for non-GET methods, base64-encodes it, and forwards it to the extension runner."
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {},
      "description": "Extension-specific response relayed from the runner. Status code, content type, and body are controlled by the extension."
    }
  },
  {
    "id": "patch-_api_ext_extensionid_path",
    "method": "patch",
    "path": "/api/ext/{extensionId}/{path}",
    "displayName": "Forward PATCH request to extension runner",
    "summary": "Forward PATCH request to extension runner",
    "description": "Tenant-scoped extension gateway endpoint that forwards PATCH requests to an installed extension runner. The gateway resolves the tenant from x-alga-tenant, x-tenant-id, session cookie, or DEV_TENANT_ID in development; verifies the extension is installed and enabled for that tenant; forwards selected headers, query parameters, and an optional opaque body to RUNNER_BASE_URL /v1/execute; and relays the runner response. For PATCH requests the body is limited to 10 MB, base64-encoded, and forwarded as http.body_b64. Clients should provide x-idempotency-key for safe retries; otherwise the gateway falls back to a generated request ID. The gateway does not interpret PATCH semantics; partial-update behavior is extension-defined.",
    "tags": [
      "Extension Gateway"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "extensionId",
        "in": "path",
        "required": true,
        "description": "Extension identifier from the URL. This may be a registry/install UUID or a publisher.name slug, resolved case-insensitively.",
        "schema": {
          "type": "string",
          "minLength": 1,
          "description": "Extension identifier from the URL. This may be a registry/install UUID or a publisher.name slug, resolved case-insensitively."
        }
      },
      {
        "name": "path",
        "in": "path",
        "required": false,
        "description": "Remaining extension endpoint path after extensionId. The gateway forwards this path to the runner unchanged.",
        "schema": {
          "type": "string",
          "description": "Remaining extension endpoint path after extensionId. The gateway forwards this path to the runner unchanged."
        }
      },
      {
        "name": "x-request-id",
        "in": "header",
        "required": false,
        "description": "Optional request ID. The gateway generates a UUID when absent and forwards it to the runner.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Optional request ID. The gateway generates a UUID when absent and forwards it to the runner."
        }
      },
      {
        "name": "x-idempotency-key",
        "in": "header",
        "required": false,
        "description": "Optional idempotency key for non-GET methods. The gateway falls back to x-request-id when absent and forwards the key to the runner.",
        "schema": {
          "type": "string",
          "description": "Optional idempotency key for non-GET methods. The gateway falls back to x-request-id when absent and forwards the key to the runner."
        }
      },
      {
        "name": "x-alga-tenant",
        "in": "header",
        "required": false,
        "description": "Internal tenant header used for tenant resolution before session fallback.",
        "schema": {
          "type": "string",
          "description": "Internal tenant header used for tenant resolution before session fallback."
        }
      },
      {
        "name": "x-tenant-id",
        "in": "header",
        "required": false,
        "description": "Legacy tenant header accepted for tenant resolution before session fallback.",
        "schema": {
          "type": "string",
          "description": "Legacy tenant header accepted for tenant resolution before session fallback."
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "properties": {},
      "description": "Extension-specific request body. The gateway treats this as opaque, enforces a 10 MB limit for non-GET methods, base64-encodes it, and forwards it to the extension runner."
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {},
      "description": "Extension-specific response relayed from the runner. Status code, content type, and body are controlled by the extension."
    }
  },
  {
    "id": "delete-_api_ext_extensionid_path",
    "method": "delete",
    "path": "/api/ext/{extensionId}/{path}",
    "displayName": "Forward DELETE request to extension runner",
    "summary": "Forward DELETE request to extension runner",
    "description": "Tenant-scoped extension gateway endpoint that forwards DELETE requests to an installed extension runner. The gateway resolves the tenant from x-alga-tenant, x-tenant-id, session cookie, or DEV_TENANT_ID in development; verifies the extension is installed and enabled for that tenant; forwards selected headers, query parameters, and an optional opaque body to RUNNER_BASE_URL /v1/execute; and relays the runner response. For DELETE requests the body, if present, is limited to 10 MB, base64-encoded, and forwarded as http.body_b64. The gateway currently has a placeholder access check and does not enforce per-extension RBAC beyond tenant install resolution.",
    "tags": [
      "Extension Gateway"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "extensionId",
        "in": "path",
        "required": true,
        "description": "Extension identifier from the URL. This may be a registry/install UUID or a publisher.name slug, resolved case-insensitively.",
        "schema": {
          "type": "string",
          "minLength": 1,
          "description": "Extension identifier from the URL. This may be a registry/install UUID or a publisher.name slug, resolved case-insensitively."
        }
      },
      {
        "name": "path",
        "in": "path",
        "required": false,
        "description": "Remaining extension endpoint path after extensionId. The gateway forwards this path to the runner unchanged.",
        "schema": {
          "type": "string",
          "description": "Remaining extension endpoint path after extensionId. The gateway forwards this path to the runner unchanged."
        }
      },
      {
        "name": "x-request-id",
        "in": "header",
        "required": false,
        "description": "Optional request ID. The gateway generates a UUID when absent and forwards it to the runner.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Optional request ID. The gateway generates a UUID when absent and forwards it to the runner."
        }
      },
      {
        "name": "x-idempotency-key",
        "in": "header",
        "required": false,
        "description": "Optional idempotency key for non-GET methods. The gateway falls back to x-request-id when absent and forwards the key to the runner.",
        "schema": {
          "type": "string",
          "description": "Optional idempotency key for non-GET methods. The gateway falls back to x-request-id when absent and forwards the key to the runner."
        }
      },
      {
        "name": "x-alga-tenant",
        "in": "header",
        "required": false,
        "description": "Internal tenant header used for tenant resolution before session fallback.",
        "schema": {
          "type": "string",
          "description": "Internal tenant header used for tenant resolution before session fallback."
        }
      },
      {
        "name": "x-tenant-id",
        "in": "header",
        "required": false,
        "description": "Legacy tenant header accepted for tenant resolution before session fallback.",
        "schema": {
          "type": "string",
          "description": "Legacy tenant header accepted for tenant resolution before session fallback."
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "properties": {},
      "description": "Extension-specific request body. The gateway treats this as opaque, enforces a 10 MB limit for non-GET methods, base64-encodes it, and forwards it to the extension runner."
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {},
      "description": "Extension-specific response relayed from the runner. Status code, content type, and body are controlled by the extension."
    }
  },
  {
    "id": "get-_api_v1_billinganalytics_overview",
    "method": "get",
    "path": "/api/v1/billing-analytics/overview",
    "displayName": "Get billing overview analytics",
    "summary": "Get billing overview analytics",
    "description": "Maps to ApiContractLineController.getBillingOverviewAnalytics() and returns tenant billing overview analytics. Authenticated and tenant-scoped via withApiKeyRouteAuth (req.context is populated before the handler runs).",
    "tags": [
      "Billing Analytics"
    ],
    "approvalRequired": false,
    "parameters": [],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "type": "object",
          "additionalProperties": {}
        },
        "count": {
          "type": "number"
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "post-_api_v1_financial_billing_calculate",
    "method": "post",
    "path": "/api/v1/financial/billing/calculate",
    "displayName": "Calculate client billing charges",
    "summary": "Calculate client billing charges",
    "description": "Calculates billing for one client and billing window using FinancialService.calculateBilling(). Requires financial:read permission.",
    "tags": [
      "Financial"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "client_id": {
          "type": "string",
          "format": "uuid"
        },
        "period_start": {
          "type": "string"
        },
        "period_end": {
          "type": "string"
        }
      },
      "required": [
        "client_id",
        "period_start",
        "period_end"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_financial_billing_paymentterms",
    "method": "get",
    "path": "/api/v1/financial/billing/payment-terms",
    "displayName": "List billing payment terms",
    "summary": "List billing payment terms",
    "description": "Returns payment terms from FinancialService.getPaymentTerms().",
    "tags": [
      "Financial"
    ],
    "approvalRequired": false,
    "parameters": [],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "post-_api_v1_financial_bulk_invoices",
    "method": "post",
    "path": "/api/v1/financial/bulk/invoices",
    "displayName": "Run bulk invoice operation",
    "summary": "Run bulk invoice operation",
    "description": "FinancialService.bulkInvoiceOperation() supports send/finalize/cancel/mark_paid operations.",
    "tags": [
      "Financial"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "operation": {
          "type": "string",
          "enum": [
            "send",
            "finalize",
            "cancel",
            "mark_paid"
          ]
        },
        "invoice_ids": {
          "type": "array",
          "items": {
            "type": "string",
            "format": "uuid"
          },
          "minItems": 1
        },
        "options": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "operation",
        "invoice_ids"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "post-_api_v1_financial_bulk_transactions",
    "method": "post",
    "path": "/api/v1/financial/bulk/transactions",
    "displayName": "Run bulk transaction operation",
    "summary": "Run bulk transaction operation",
    "description": "FinancialService.bulkTransactionOperation() applies approve/reject/reverse to existing transactions (1–100 ids). reverse posts a compensating transaction linked to the original via related_transaction_id, recomputes the running balance, and syncs the client credit balance for credit-type transactions. Returns per-id results { total_requested, successful, failed, results[] }.",
    "tags": [
      "Financial"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "operation": {
          "type": "string",
          "enum": [
            "approve",
            "reject",
            "void"
          ]
        },
        "transaction_ids": {
          "type": "array",
          "items": {
            "type": "string",
            "format": "uuid"
          },
          "minItems": 1
        },
        "options": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "operation",
        "transaction_ids"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "post-_api_v1_financial_bulk_credits",
    "method": "post",
    "path": "/api/v1/financial/bulk/credits",
    "displayName": "Run bulk credit operation",
    "summary": "Run bulk credit operation",
    "description": "FinancialService.bulkCreditOperation() applies expire/extend_expiration/transfer to existing credits (1–100 ids). expire forfeits the remaining amount via a credit_expiration transaction and reduces the client balance; extend_expiration sets a new expiration_date; transfer moves the remaining amount to parameters.target_client_id. Returns per-id results { total_requested, successful, failed, results[] }.",
    "tags": [
      "Financial"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "operation": {
          "type": "string",
          "enum": [
            "expire",
            "extend",
            "transfer"
          ]
        },
        "credit_ids": {
          "type": "array",
          "items": {
            "type": "string",
            "format": "uuid"
          },
          "minItems": 1
        },
        "options": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "operation",
        "credit_ids"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_financial_credits",
    "method": "get",
    "path": "/api/v1/financial/credits",
    "displayName": "List credit balances and records",
    "summary": "List credit balances and records",
    "description": "Lists credits with filters using FinancialService.listClientCredits().",
    "tags": [
      "Financial"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "page",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "limit",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "sort",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "order",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "asc",
            "desc"
          ]
        }
      },
      {
        "name": "search",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "created_from",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "created_to",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "updated_from",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "updated_to",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "client_id",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      },
      {
        "name": "invoice_id",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      },
      {
        "name": "type",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "status",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "amount_min",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "amount_max",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "include_expired",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ]
        }
      },
      {
        "name": "expiring_soon",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ]
        }
      },
      {
        "name": "has_remaining",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ]
        }
      },
      {
        "name": "has_expiration",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ]
        }
      },
      {
        "name": "date_from",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "date_to",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "group_by",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "day",
            "week",
            "month"
          ]
        }
      },
      {
        "name": "include_projections",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ]
        }
      },
      {
        "name": "as_of_date",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "type": "array",
          "items": {
            "type": "object",
            "additionalProperties": {}
          }
        },
        "pagination": {
          "type": "object",
          "properties": {
            "page": {
              "type": "integer"
            },
            "limit": {
              "type": "integer"
            },
            "total": {
              "type": "integer"
            },
            "totalPages": {
              "type": "integer"
            },
            "hasNext": {
              "type": "boolean"
            },
            "hasPrev": {
              "type": "boolean"
            }
          },
          "required": [
            "page",
            "limit",
            "total",
            "totalPages",
            "hasNext",
            "hasPrev"
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data",
        "pagination"
      ]
    }
  },
  {
    "id": "post-_api_v1_financial_credits_apply",
    "method": "post",
    "path": "/api/v1/financial/credits/apply",
    "displayName": "Apply credit to invoice",
    "summary": "Apply credit to invoice",
    "description": "Applies client credit to an invoice via FinancialService.applyCreditToInvoice().",
    "tags": [
      "Financial"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "client_id": {
          "type": "string",
          "format": "uuid"
        },
        "invoice_id": {
          "type": "string",
          "format": "uuid"
        },
        "requested_amount": {
          "type": "number",
          "minimum": 0
        }
      },
      "required": [
        "client_id",
        "invoice_id",
        "requested_amount"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "post-_api_v1_financial_credits_prepayment",
    "method": "post",
    "path": "/api/v1/financial/credits/prepayment",
    "displayName": "Create prepayment invoice",
    "summary": "Create prepayment invoice",
    "description": "Creates a prepayment invoice and corresponding credit allocation.",
    "tags": [
      "Financial"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "client_id": {
          "type": "string",
          "format": "uuid"
        },
        "amount": {
          "type": "number",
          "minimum": 0
        },
        "manual_expiration_date": {
          "type": "string"
        }
      },
      "required": [
        "client_id",
        "amount"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "post-_api_v1_financial_credits_transfer",
    "method": "post",
    "path": "/api/v1/financial/credits/transfer",
    "displayName": "Transfer credit between clients",
    "summary": "Transfer credit between clients",
    "description": "Transfers credit between clients via FinancialService.transferCredit().",
    "tags": [
      "Financial"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "source_credit_id": {
          "type": "string",
          "format": "uuid"
        },
        "target_client_id": {
          "type": "string",
          "format": "uuid"
        },
        "amount": {
          "type": "number",
          "minimum": 0
        },
        "user_id": {
          "type": "string",
          "format": "uuid"
        },
        "reason": {
          "type": "string"
        }
      },
      "required": [
        "source_credit_id",
        "target_client_id",
        "amount",
        "user_id"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "post-_api_v1_financial_credits_validate",
    "method": "post",
    "path": "/api/v1/financial/credits/validate",
    "displayName": "Validate client credit balance",
    "summary": "Validate client credit balance",
    "description": "Validates whether a client has sufficient usable credit.",
    "tags": [
      "Financial"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "client_id": {
          "type": "string",
          "format": "uuid"
        }
      },
      "required": [
        "client_id"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_financial_invoices",
    "method": "get",
    "path": "/api/v1/financial/invoices",
    "displayName": "List financial invoices (transaction list wiring)",
    "summary": "List financial invoices (transaction list wiring)",
    "description": "Route file maps to ApiFinancialController.list(), which is transaction-oriented (resource financial/transactions) rather than invoice-specific list logic. Current response is the generic transaction list envelope with financial report links.",
    "tags": [
      "Financial"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "page",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "limit",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "sort",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "order",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "asc",
            "desc"
          ]
        }
      },
      {
        "name": "search",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "created_from",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "created_to",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "updated_from",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "updated_to",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "client_id",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      },
      {
        "name": "invoice_id",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      },
      {
        "name": "type",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "status",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "amount_min",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "amount_max",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "include_expired",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ]
        }
      },
      {
        "name": "expiring_soon",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ]
        }
      },
      {
        "name": "has_remaining",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ]
        }
      },
      {
        "name": "has_expiration",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ]
        }
      },
      {
        "name": "date_from",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "date_to",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "group_by",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "day",
            "week",
            "month"
          ]
        }
      },
      {
        "name": "include_projections",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ]
        }
      },
      {
        "name": "as_of_date",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "type": "array",
          "items": {
            "type": "object",
            "additionalProperties": {}
          }
        },
        "pagination": {
          "type": "object",
          "properties": {
            "page": {
              "type": "integer"
            },
            "limit": {
              "type": "integer"
            },
            "total": {
              "type": "integer"
            },
            "totalPages": {
              "type": "integer"
            },
            "hasNext": {
              "type": "boolean"
            },
            "hasPrev": {
              "type": "boolean"
            }
          },
          "required": [
            "page",
            "limit",
            "total",
            "totalPages",
            "hasNext",
            "hasPrev"
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data",
        "pagination"
      ]
    }
  },
  {
    "id": "post-_api_v1_financial_invoices_id_finalize",
    "method": "post",
    "path": "/api/v1/financial/invoices/{id}/finalize",
    "displayName": "Finalize financial invoice (maps to generic update)",
    "summary": "Finalize financial invoice (maps to generic update)",
    "description": "Despite route naming, the handler calls ApiFinancialController.update() which performs generic financial update validation and update semantics. Path id is extracted as financial resource id and processed by FinancialService.update().",
    "tags": [
      "Financial"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Path UUID parameter resolved by ApiBaseController.extractIdFromPath().",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Path UUID parameter resolved by ApiBaseController.extractIdFromPath()."
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "client_id": {
          "type": "string",
          "format": "uuid"
        },
        "invoice_id": {
          "type": "string",
          "format": "uuid"
        },
        "amount": {
          "type": "number"
        },
        "type": {
          "type": "string"
        },
        "status": {
          "type": "string"
        },
        "parent_transaction_id": {
          "type": "string",
          "format": "uuid"
        },
        "description": {
          "type": "string"
        },
        "reference_number": {
          "type": "string"
        },
        "metadata": {
          "type": "object",
          "additionalProperties": {}
        },
        "balance_after": {
          "type": "number"
        },
        "expiration_date": {
          "type": "string"
        },
        "related_transaction_id": {
          "type": "string",
          "format": "uuid"
        }
      }
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "post-_api_v1_financial_invoices_id_items",
    "method": "post",
    "path": "/api/v1/financial/invoices/{id}/items",
    "displayName": "Add financial invoice item (maps to generic create)",
    "summary": "Add financial invoice item (maps to generic create)",
    "description": "Route maps to ApiFinancialController.create(), which validates createTransactionSchema and creates a financial transaction. The path {id} is not consumed by create().",
    "tags": [
      "Financial"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Path UUID parameter resolved by ApiBaseController.extractIdFromPath().",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Path UUID parameter resolved by ApiBaseController.extractIdFromPath()."
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "client_id": {
          "type": "string",
          "format": "uuid"
        },
        "invoice_id": {
          "type": "string",
          "format": "uuid"
        },
        "amount": {
          "type": "number"
        },
        "type": {
          "type": "string"
        },
        "status": {
          "type": "string"
        },
        "parent_transaction_id": {
          "type": "string",
          "format": "uuid"
        },
        "description": {
          "type": "string"
        },
        "reference_number": {
          "type": "string"
        },
        "metadata": {
          "type": "object",
          "additionalProperties": {}
        },
        "balance_after": {
          "type": "number"
        },
        "expiration_date": {
          "type": "string"
        },
        "related_transaction_id": {
          "type": "string",
          "format": "uuid"
        }
      },
      "required": [
        "client_id",
        "amount",
        "type",
        "balance_after"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_financial_paymentmethods",
    "method": "get",
    "path": "/api/v1/financial/payment-methods",
    "displayName": "List payment methods (transaction list wiring)",
    "summary": "List payment methods (transaction list wiring)",
    "description": "Current route wiring calls ApiFinancialController.list(), which lists transaction records and not payment methods. This discrepancy is documented as implementation behavior.",
    "tags": [
      "Financial"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "page",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "limit",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "sort",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "order",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "asc",
            "desc"
          ]
        }
      },
      {
        "name": "search",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "created_from",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "created_to",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "updated_from",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "updated_to",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "client_id",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      },
      {
        "name": "invoice_id",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      },
      {
        "name": "type",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "status",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "amount_min",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "amount_max",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "include_expired",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ]
        }
      },
      {
        "name": "expiring_soon",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ]
        }
      },
      {
        "name": "has_remaining",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ]
        }
      },
      {
        "name": "has_expiration",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ]
        }
      },
      {
        "name": "date_from",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "date_to",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "group_by",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "day",
            "week",
            "month"
          ]
        }
      },
      {
        "name": "include_projections",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ]
        }
      },
      {
        "name": "as_of_date",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "type": "array",
          "items": {
            "type": "object",
            "additionalProperties": {}
          }
        },
        "pagination": {
          "type": "object",
          "properties": {
            "page": {
              "type": "integer"
            },
            "limit": {
              "type": "integer"
            },
            "total": {
              "type": "integer"
            },
            "totalPages": {
              "type": "integer"
            },
            "hasNext": {
              "type": "boolean"
            },
            "hasPrev": {
              "type": "boolean"
            }
          },
          "required": [
            "page",
            "limit",
            "total",
            "totalPages",
            "hasNext",
            "hasPrev"
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data",
        "pagination"
      ]
    }
  },
  {
    "id": "post-_api_v1_financial_paymentmethods",
    "method": "post",
    "path": "/api/v1/financial/payment-methods",
    "displayName": "Create payment method",
    "summary": "Create payment method",
    "description": "Creates a payment method using FinancialService.createPaymentMethod().",
    "tags": [
      "Financial"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "client_id": {
          "type": "string",
          "format": "uuid"
        },
        "type": {
          "type": "string",
          "enum": [
            "credit_card",
            "bank_account"
          ]
        },
        "last4": {
          "type": "string",
          "minLength": 4,
          "maxLength": 4
        },
        "exp_month": {
          "type": "string"
        },
        "exp_year": {
          "type": "string"
        },
        "is_default": {
          "type": "boolean"
        },
        "is_deleted": {
          "type": "boolean"
        }
      },
      "required": [
        "client_id",
        "type",
        "last4"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_financial_paymentmethods_id",
    "method": "get",
    "path": "/api/v1/financial/payment-methods/{id}",
    "displayName": "Get payment method by id (transaction get wiring)",
    "summary": "Get payment method by id (transaction get wiring)",
    "description": "Route maps to ApiFinancialController.getById(), which fetches a financial transaction by id.",
    "tags": [
      "Financial"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Path UUID parameter resolved by ApiBaseController.extractIdFromPath().",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Path UUID parameter resolved by ApiBaseController.extractIdFromPath()."
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "put-_api_v1_financial_paymentmethods_id",
    "method": "put",
    "path": "/api/v1/financial/payment-methods/{id}",
    "displayName": "Update payment method by id (transaction update wiring)",
    "summary": "Update payment method by id (transaction update wiring)",
    "description": "Route maps to ApiFinancialController.update(), which updates generic financial resource fields.",
    "tags": [
      "Financial"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Path UUID parameter resolved by ApiBaseController.extractIdFromPath().",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Path UUID parameter resolved by ApiBaseController.extractIdFromPath()."
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "client_id": {
          "type": "string",
          "format": "uuid"
        },
        "invoice_id": {
          "type": "string",
          "format": "uuid"
        },
        "amount": {
          "type": "number"
        },
        "type": {
          "type": "string"
        },
        "status": {
          "type": "string"
        },
        "parent_transaction_id": {
          "type": "string",
          "format": "uuid"
        },
        "description": {
          "type": "string"
        },
        "reference_number": {
          "type": "string"
        },
        "metadata": {
          "type": "object",
          "additionalProperties": {}
        },
        "balance_after": {
          "type": "number"
        },
        "expiration_date": {
          "type": "string"
        },
        "related_transaction_id": {
          "type": "string",
          "format": "uuid"
        }
      }
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "delete-_api_v1_financial_paymentmethods_id",
    "method": "delete",
    "path": "/api/v1/financial/payment-methods/{id}",
    "displayName": "Delete payment method by id (transaction delete wiring)",
    "summary": "Delete payment method by id (transaction delete wiring)",
    "description": "Route maps to ApiFinancialController.delete(), deleting a generic financial resource by id.",
    "tags": [
      "Financial"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Path UUID parameter resolved by ApiBaseController.extractIdFromPath().",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Path UUID parameter resolved by ApiBaseController.extractIdFromPath()."
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "post-_api_v1_financial_reconciliation_run",
    "method": "post",
    "path": "/api/v1/financial/reconciliation/run",
    "displayName": "Run financial reconciliation",
    "summary": "Run financial reconciliation",
    "description": "Triggers FinancialService.runCreditReconciliation(). Optional client_id query narrows reconciliation target.",
    "tags": [
      "Financial"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "page",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "limit",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "sort",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "order",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "asc",
            "desc"
          ]
        }
      },
      {
        "name": "search",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "created_from",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "created_to",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "updated_from",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "updated_to",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "client_id",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      },
      {
        "name": "invoice_id",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      },
      {
        "name": "type",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "status",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "amount_min",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "amount_max",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "include_expired",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ]
        }
      },
      {
        "name": "expiring_soon",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ]
        }
      },
      {
        "name": "has_remaining",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ]
        }
      },
      {
        "name": "has_expiration",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ]
        }
      },
      {
        "name": "date_from",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "date_to",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "group_by",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "day",
            "week",
            "month"
          ]
        }
      },
      {
        "name": "include_projections",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ]
        }
      },
      {
        "name": "as_of_date",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "post-_api_v1_financial_reconciliation_id_resolve",
    "method": "post",
    "path": "/api/v1/financial/reconciliation/{id}/resolve",
    "displayName": "Resolve reconciliation report",
    "summary": "Resolve reconciliation report",
    "description": "Resolves one reconciliation report by id with optional operator notes.",
    "tags": [
      "Financial"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Path UUID parameter resolved by ApiBaseController.extractIdFromPath().",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Path UUID parameter resolved by ApiBaseController.extractIdFromPath()."
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "notes": {
          "type": "string"
        }
      }
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_financial_reports_aging",
    "method": "get",
    "path": "/api/v1/financial/reports/aging",
    "displayName": "Get aging report",
    "summary": "Get aging report",
    "description": "Returns aging buckets and summary for tenant-wide receivables or one client.",
    "tags": [
      "Financial"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "page",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "limit",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "sort",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "order",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "asc",
            "desc"
          ]
        }
      },
      {
        "name": "search",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "created_from",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "created_to",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "updated_from",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "updated_to",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "client_id",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      },
      {
        "name": "invoice_id",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      },
      {
        "name": "type",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "status",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "amount_min",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "amount_max",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "include_expired",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ]
        }
      },
      {
        "name": "expiring_soon",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ]
        }
      },
      {
        "name": "has_remaining",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ]
        }
      },
      {
        "name": "has_expiration",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ]
        }
      },
      {
        "name": "date_from",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "date_to",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "group_by",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "day",
            "week",
            "month"
          ]
        }
      },
      {
        "name": "include_projections",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ]
        }
      },
      {
        "name": "as_of_date",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_financial_reports_analytics",
    "method": "get",
    "path": "/api/v1/financial/reports/analytics",
    "displayName": "Get financial analytics",
    "summary": "Get financial analytics",
    "description": "Returns aggregate financial analytics for a date range.",
    "tags": [
      "Financial"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "page",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "limit",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "sort",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "order",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "asc",
            "desc"
          ]
        }
      },
      {
        "name": "search",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "created_from",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "created_to",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "updated_from",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "updated_to",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "client_id",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      },
      {
        "name": "invoice_id",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      },
      {
        "name": "type",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "status",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "amount_min",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "amount_max",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "include_expired",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ]
        }
      },
      {
        "name": "expiring_soon",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ]
        }
      },
      {
        "name": "has_remaining",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ]
        }
      },
      {
        "name": "has_expiration",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ]
        }
      },
      {
        "name": "date_from",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "date_to",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "group_by",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "day",
            "week",
            "month"
          ]
        }
      },
      {
        "name": "include_projections",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ]
        }
      },
      {
        "name": "as_of_date",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_financial_reports_balance",
    "method": "get",
    "path": "/api/v1/financial/reports/balance",
    "displayName": "Get account balance report",
    "summary": "Get account balance report",
    "description": "Returns balance summary for one client_id (required by controller).",
    "tags": [
      "Financial"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "page",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "limit",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "sort",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "order",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "asc",
            "desc"
          ]
        }
      },
      {
        "name": "search",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "created_from",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "created_to",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "updated_from",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "updated_to",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "client_id",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      },
      {
        "name": "invoice_id",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      },
      {
        "name": "type",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "status",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "amount_min",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "amount_max",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "include_expired",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ]
        }
      },
      {
        "name": "expiring_soon",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ]
        }
      },
      {
        "name": "has_remaining",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ]
        }
      },
      {
        "name": "has_expiration",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ]
        }
      },
      {
        "name": "date_from",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "date_to",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "group_by",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "day",
            "week",
            "month"
          ]
        }
      },
      {
        "name": "include_projections",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ]
        }
      },
      {
        "name": "as_of_date",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "post-_api_v1_financial_tax_calculate",
    "method": "post",
    "path": "/api/v1/financial/tax/calculate",
    "displayName": "Calculate financial tax",
    "summary": "Calculate financial tax",
    "description": "Calculates tax for a client/amount/tax_region tuple. Requires financial:read permission in current controller implementation.",
    "tags": [
      "Financial"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "client_id": {
          "type": "string",
          "format": "uuid"
        },
        "amount": {
          "type": "number",
          "minimum": 0
        },
        "tax_region": {
          "type": "string"
        },
        "date": {
          "type": "string"
        }
      },
      "required": [
        "client_id",
        "amount",
        "tax_region"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_financial_tax_rates",
    "method": "get",
    "path": "/api/v1/financial/tax/rates",
    "displayName": "List financial tax rates (transaction list wiring)",
    "summary": "List financial tax rates (transaction list wiring)",
    "description": "Route file currently maps to ApiFinancialController.list(), so the response is the generic financial transaction list rather than a tax-rate list.",
    "tags": [
      "Financial"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "page",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "limit",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "sort",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "order",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "asc",
            "desc"
          ]
        }
      },
      {
        "name": "search",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "created_from",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "created_to",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "updated_from",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "updated_to",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "client_id",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      },
      {
        "name": "invoice_id",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      },
      {
        "name": "type",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "status",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "amount_min",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "amount_max",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "include_expired",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ]
        }
      },
      {
        "name": "expiring_soon",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ]
        }
      },
      {
        "name": "has_remaining",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ]
        }
      },
      {
        "name": "has_expiration",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ]
        }
      },
      {
        "name": "date_from",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "date_to",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "group_by",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "day",
            "week",
            "month"
          ]
        }
      },
      {
        "name": "include_projections",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ]
        }
      },
      {
        "name": "as_of_date",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "type": "array",
          "items": {
            "type": "object",
            "additionalProperties": {}
          }
        },
        "pagination": {
          "type": "object",
          "properties": {
            "page": {
              "type": "integer"
            },
            "limit": {
              "type": "integer"
            },
            "total": {
              "type": "integer"
            },
            "totalPages": {
              "type": "integer"
            },
            "hasNext": {
              "type": "boolean"
            },
            "hasPrev": {
              "type": "boolean"
            }
          },
          "required": [
            "page",
            "limit",
            "total",
            "totalPages",
            "hasNext",
            "hasPrev"
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data",
        "pagination"
      ]
    }
  },
  {
    "id": "get-_api_v1_financial_transactions",
    "method": "get",
    "path": "/api/v1/financial/transactions",
    "displayName": "List financial transactions",
    "summary": "List financial transactions",
    "description": "Lists transactions with advanced filtering.",
    "tags": [
      "Financial"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "page",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "limit",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "sort",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "order",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "asc",
            "desc"
          ]
        }
      },
      {
        "name": "search",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "created_from",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "created_to",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "updated_from",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "updated_to",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "client_id",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      },
      {
        "name": "invoice_id",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      },
      {
        "name": "type",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "status",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "amount_min",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "amount_max",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "include_expired",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ]
        }
      },
      {
        "name": "expiring_soon",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ]
        }
      },
      {
        "name": "has_remaining",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ]
        }
      },
      {
        "name": "has_expiration",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ]
        }
      },
      {
        "name": "date_from",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "date_to",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "group_by",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "day",
            "week",
            "month"
          ]
        }
      },
      {
        "name": "include_projections",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ]
        }
      },
      {
        "name": "as_of_date",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "type": "array",
          "items": {
            "type": "object",
            "additionalProperties": {}
          }
        },
        "pagination": {
          "type": "object",
          "properties": {
            "page": {
              "type": "integer"
            },
            "limit": {
              "type": "integer"
            },
            "total": {
              "type": "integer"
            },
            "totalPages": {
              "type": "integer"
            },
            "hasNext": {
              "type": "boolean"
            },
            "hasPrev": {
              "type": "boolean"
            }
          },
          "required": [
            "page",
            "limit",
            "total",
            "totalPages",
            "hasNext",
            "hasPrev"
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data",
        "pagination"
      ]
    }
  },
  {
    "id": "post-_api_v1_financial_transactions",
    "method": "post",
    "path": "/api/v1/financial/transactions",
    "displayName": "Create financial transaction",
    "summary": "Create financial transaction",
    "description": "Creates one financial transaction.",
    "tags": [
      "Financial"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "client_id": {
          "type": "string",
          "format": "uuid"
        },
        "invoice_id": {
          "type": "string",
          "format": "uuid"
        },
        "amount": {
          "type": "number"
        },
        "type": {
          "type": "string"
        },
        "status": {
          "type": "string"
        },
        "parent_transaction_id": {
          "type": "string",
          "format": "uuid"
        },
        "description": {
          "type": "string"
        },
        "reference_number": {
          "type": "string"
        },
        "metadata": {
          "type": "object",
          "additionalProperties": {}
        },
        "balance_after": {
          "type": "number"
        },
        "expiration_date": {
          "type": "string"
        },
        "related_transaction_id": {
          "type": "string",
          "format": "uuid"
        }
      },
      "required": [
        "client_id",
        "amount",
        "type",
        "balance_after"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_financial_transactions_id",
    "method": "get",
    "path": "/api/v1/financial/transactions/{id}",
    "displayName": "Get financial transaction by id",
    "summary": "Get financial transaction by id",
    "description": "Loads one financial transaction by id.",
    "tags": [
      "Financial"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Path UUID parameter resolved by ApiBaseController.extractIdFromPath().",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Path UUID parameter resolved by ApiBaseController.extractIdFromPath()."
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "put-_api_v1_financial_transactions_id",
    "method": "put",
    "path": "/api/v1/financial/transactions/{id}",
    "displayName": "Update financial transaction",
    "summary": "Update financial transaction",
    "description": "Updates one transaction id with partial payload.",
    "tags": [
      "Financial"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Path UUID parameter resolved by ApiBaseController.extractIdFromPath().",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Path UUID parameter resolved by ApiBaseController.extractIdFromPath()."
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "client_id": {
          "type": "string",
          "format": "uuid"
        },
        "invoice_id": {
          "type": "string",
          "format": "uuid"
        },
        "amount": {
          "type": "number"
        },
        "type": {
          "type": "string"
        },
        "status": {
          "type": "string"
        },
        "parent_transaction_id": {
          "type": "string",
          "format": "uuid"
        },
        "description": {
          "type": "string"
        },
        "reference_number": {
          "type": "string"
        },
        "metadata": {
          "type": "object",
          "additionalProperties": {}
        },
        "balance_after": {
          "type": "number"
        },
        "expiration_date": {
          "type": "string"
        },
        "related_transaction_id": {
          "type": "string",
          "format": "uuid"
        }
      }
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_invoices",
    "method": "get",
    "path": "/api/v1/invoices",
    "displayName": "List invoices",
    "summary": "List invoices",
    "description": "Lists invoices with pagination, filter query keys, and include flags.",
    "tags": [
      "Invoices"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "page",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "limit",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "sort",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "order",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "asc",
            "desc"
          ]
        }
      },
      {
        "name": "include_items",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ]
        }
      },
      {
        "name": "include_client",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ]
        }
      },
      {
        "name": "include_billing_cycle",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ]
        }
      },
      {
        "name": "include_transactions",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ]
        }
      },
      {
        "name": "q",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "from",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "to",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "format",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "json",
            "csv"
          ]
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "type": "array",
          "items": {
            "type": "object",
            "additionalProperties": {}
          }
        },
        "pagination": {
          "type": "object",
          "properties": {
            "page": {
              "type": "integer"
            },
            "limit": {
              "type": "integer"
            },
            "total": {
              "type": "integer"
            },
            "totalPages": {
              "type": "integer"
            },
            "hasNext": {
              "type": "boolean"
            },
            "hasPrev": {
              "type": "boolean"
            }
          },
          "required": [
            "page",
            "limit",
            "total",
            "totalPages",
            "hasNext",
            "hasPrev"
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data",
        "pagination"
      ]
    }
  },
  {
    "id": "post-_api_v1_invoices",
    "method": "post",
    "path": "/api/v1/invoices",
    "displayName": "Create invoice",
    "summary": "Create invoice",
    "description": "Creates an invoice record via ApiBaseController.create() and invoice create schema.",
    "tags": [
      "Invoices"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "client_id": {
          "type": "string",
          "format": "uuid"
        },
        "invoice_date": {
          "type": "string"
        },
        "due_date": {
          "type": "string"
        },
        "subtotal": {
          "type": "integer",
          "minimum": 0
        },
        "tax": {
          "type": "integer",
          "minimum": 0
        },
        "total_amount": {
          "type": "integer",
          "minimum": 0
        },
        "status": {
          "type": "string",
          "enum": [
            "draft",
            "sent",
            "paid",
            "overdue",
            "cancelled",
            "pending",
            "prepayment",
            "partially_applied"
          ]
        },
        "credit_applied": {
          "type": "integer",
          "minimum": 0
        },
        "is_manual": {
          "type": "boolean"
        },
        "is_prepayment": {
          "type": "boolean"
        },
        "items": {
          "type": "array",
          "items": {
            "type": "object",
            "additionalProperties": {}
          }
        }
      },
      "required": [
        "client_id",
        "invoice_date",
        "due_date",
        "subtotal",
        "tax",
        "total_amount",
        "status"
      ],
      "additionalProperties": {}
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_invoices_analytics",
    "method": "get",
    "path": "/api/v1/invoices/analytics",
    "displayName": "Get invoice analytics",
    "summary": "Get invoice analytics",
    "description": "Returns aggregate analytics for invoice states and amounts over optional from/to range.",
    "tags": [
      "Invoices"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "page",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "limit",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "sort",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "order",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "asc",
            "desc"
          ]
        }
      },
      {
        "name": "include_items",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ]
        }
      },
      {
        "name": "include_client",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ]
        }
      },
      {
        "name": "include_billing_cycle",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ]
        }
      },
      {
        "name": "include_transactions",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ]
        }
      },
      {
        "name": "q",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "from",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "to",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "format",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "json",
            "csv"
          ]
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "post-_api_v1_invoices_bulk",
    "method": "post",
    "path": "/api/v1/invoices/bulk",
    "displayName": "Bulk update invoice status",
    "summary": "Bulk update invoice status",
    "description": "Bulk status transition route using bulkInvoiceStatusUpdateSchema.",
    "tags": [
      "Invoices"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "invoice_ids": {
          "type": "array",
          "items": {
            "type": "string",
            "format": "uuid"
          },
          "minItems": 1,
          "maxItems": 100
        },
        "status": {
          "type": "string",
          "enum": [
            "draft",
            "sent",
            "paid",
            "overdue",
            "cancelled",
            "pending",
            "prepayment",
            "partially_applied"
          ]
        },
        "finalized_at": {
          "type": "string"
        }
      },
      "required": [
        "invoice_ids",
        "status"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "post-_api_v1_invoices_bulk_credit",
    "method": "post",
    "path": "/api/v1/invoices/bulk/credit",
    "displayName": "Bulk apply invoice credits",
    "summary": "Bulk apply invoice credits",
    "description": "Applies the same credit amount to each listed invoice; response includes successes and per-invoice errors.",
    "tags": [
      "Invoices"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "invoice_ids": {
          "type": "array",
          "items": {
            "type": "string",
            "format": "uuid"
          },
          "minItems": 1,
          "maxItems": 100
        },
        "credit_amount_per_invoice": {
          "type": "integer",
          "minimum": 0
        }
      },
      "required": [
        "invoice_ids",
        "credit_amount_per_invoice"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "post-_api_v1_invoices_bulk_delete",
    "method": "post",
    "path": "/api/v1/invoices/bulk/delete",
    "displayName": "Bulk delete invoices",
    "summary": "Bulk delete invoices",
    "description": "Deletes multiple invoice records in one request.",
    "tags": [
      "Invoices"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "ids": {
          "type": "array",
          "items": {
            "type": "string",
            "format": "uuid"
          },
          "minItems": 1
        },
        "force": {
          "type": "boolean"
        }
      },
      "required": [
        "ids"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "post-_api_v1_invoices_bulk_send",
    "method": "post",
    "path": "/api/v1/invoices/bulk/send",
    "displayName": "Bulk send invoices",
    "summary": "Bulk send invoices",
    "description": "Enqueues or executes invoice send for multiple invoice IDs.",
    "tags": [
      "Invoices"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "invoice_ids": {
          "type": "array",
          "items": {
            "type": "string",
            "format": "uuid"
          },
          "minItems": 1,
          "maxItems": 50
        },
        "email_template": {
          "type": "string"
        },
        "include_pdf": {
          "type": "boolean"
        }
      },
      "required": [
        "invoice_ids"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_invoices_export",
    "method": "get",
    "path": "/api/v1/invoices/export",
    "displayName": "Export invoices",
    "summary": "Export invoices",
    "description": "Exports invoice data. format=csv returns text/csv attachment; default is JSON success envelope.",
    "tags": [
      "Invoices"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "page",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "limit",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "sort",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "order",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "asc",
            "desc"
          ]
        }
      },
      {
        "name": "include_items",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ]
        }
      },
      {
        "name": "include_client",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ]
        }
      },
      {
        "name": "include_billing_cycle",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ]
        }
      },
      {
        "name": "include_transactions",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ]
        }
      },
      {
        "name": "q",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "from",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "to",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "format",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "json",
            "csv"
          ]
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "post-_api_v1_invoices_generate",
    "method": "post",
    "path": "/api/v1/invoices/generate",
    "displayName": "Generate recurring invoice",
    "summary": "Generate recurring invoice",
    "description": "Generates one recurring invoice using canonical selector_input payload.",
    "tags": [
      "Invoices"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "selector_input": {
          "type": "object",
          "properties": {
            "clientId": {
              "type": "string",
              "format": "uuid"
            },
            "windowStart": {
              "type": "string"
            },
            "windowEnd": {
              "type": "string"
            },
            "executionWindow": {
              "type": "object",
              "properties": {
                "kind": {
                  "type": "string",
                  "enum": [
                    "client_cadence_window",
                    "contract_cadence_window"
                  ]
                },
                "identityKey": {
                  "type": "string"
                },
                "cadenceOwner": {
                  "type": "string",
                  "enum": [
                    "client",
                    "contract"
                  ]
                },
                "clientId": {
                  "type": "string",
                  "format": "uuid"
                },
                "billingCycleId": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "format": "uuid"
                },
                "contractId": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "format": "uuid"
                },
                "contractLineId": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "format": "uuid"
                },
                "windowStart": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "windowEnd": {
                  "type": [
                    "string",
                    "null"
                  ]
                }
              },
              "required": [
                "kind",
                "identityKey",
                "cadenceOwner"
              ]
            }
          },
          "required": [
            "clientId",
            "windowStart",
            "windowEnd",
            "executionWindow"
          ]
        }
      },
      "required": [
        "selector_input"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "post-_api_v1_invoices_manual",
    "method": "post",
    "path": "/api/v1/invoices/manual",
    "displayName": "Create manual invoice",
    "summary": "Create manual invoice",
    "description": "Creates a manual invoice using clientId + items payload.",
    "tags": [
      "Invoices"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "clientId": {
          "type": "string",
          "format": "uuid"
        },
        "items": {
          "type": "array",
          "items": {
            "type": "object",
            "additionalProperties": {}
          },
          "minItems": 1
        },
        "expirationDate": {
          "type": "string"
        },
        "isPrepayment": {
          "type": "boolean"
        }
      },
      "required": [
        "clientId",
        "items"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "post-_api_v1_invoices_preview",
    "method": "post",
    "path": "/api/v1/invoices/preview",
    "displayName": "Preview recurring invoice",
    "summary": "Preview recurring invoice",
    "description": "Previews invoice output for selector_input payload without committing final invoice state.",
    "tags": [
      "Invoices"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "selector_input": {
          "type": "object",
          "properties": {
            "clientId": {
              "type": "string",
              "format": "uuid"
            },
            "windowStart": {
              "type": "string"
            },
            "windowEnd": {
              "type": "string"
            },
            "executionWindow": {
              "type": "object",
              "properties": {
                "kind": {
                  "type": "string",
                  "enum": [
                    "client_cadence_window",
                    "contract_cadence_window"
                  ]
                },
                "identityKey": {
                  "type": "string"
                },
                "cadenceOwner": {
                  "type": "string",
                  "enum": [
                    "client",
                    "contract"
                  ]
                },
                "clientId": {
                  "type": "string",
                  "format": "uuid"
                },
                "billingCycleId": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "format": "uuid"
                },
                "contractId": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "format": "uuid"
                },
                "contractLineId": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "format": "uuid"
                },
                "windowStart": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "windowEnd": {
                  "type": [
                    "string",
                    "null"
                  ]
                }
              },
              "required": [
                "kind",
                "identityKey",
                "cadenceOwner"
              ]
            }
          },
          "required": [
            "clientId",
            "windowStart",
            "windowEnd",
            "executionWindow"
          ]
        }
      },
      "required": [
        "selector_input"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_invoices_recurring",
    "method": "get",
    "path": "/api/v1/invoices/recurring",
    "displayName": "List recurring invoice templates",
    "summary": "List recurring invoice templates",
    "description": "Current implementation returns an empty list placeholder (TODO in ApiInvoiceController.listRecurringTemplates).",
    "tags": [
      "Invoices"
    ],
    "approvalRequired": false,
    "parameters": [],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "post-_api_v1_invoices_recurring",
    "method": "post",
    "path": "/api/v1/invoices/recurring",
    "displayName": "Create recurring invoice template",
    "summary": "Create recurring invoice template",
    "description": "Creates a recurring template used for scheduled invoice generation.",
    "tags": [
      "Invoices"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "client_id": {
          "type": "string",
          "format": "uuid"
        },
        "name": {
          "type": "string"
        },
        "frequency": {
          "type": "string",
          "enum": [
            "daily",
            "weekly",
            "monthly",
            "quarterly",
            "annually"
          ]
        },
        "start_date": {
          "type": "string"
        },
        "end_date": {
          "type": "string"
        },
        "is_active": {
          "type": "boolean"
        },
        "invoice_template": {
          "type": "object",
          "additionalProperties": {}
        },
        "max_generations": {
          "type": "number"
        }
      },
      "required": [
        "client_id",
        "name",
        "frequency",
        "start_date",
        "invoice_template"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "put-_api_v1_invoices_recurring_id",
    "method": "put",
    "path": "/api/v1/invoices/recurring/{id}",
    "displayName": "Update recurring invoice template",
    "summary": "Update recurring invoice template",
    "description": "Current implementation echoes payload and id without persistence (TODO in ApiInvoiceController.updateRecurringTemplate).",
    "tags": [
      "Invoices"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Path UUID parameter resolved by ApiBaseController.extractIdFromPath().",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Path UUID parameter resolved by ApiBaseController.extractIdFromPath()."
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "client_id": {
          "type": "string",
          "format": "uuid"
        },
        "name": {
          "type": "string"
        },
        "frequency": {
          "type": "string",
          "enum": [
            "daily",
            "weekly",
            "monthly",
            "quarterly",
            "annually"
          ]
        },
        "start_date": {
          "type": "string"
        },
        "end_date": {
          "type": "string"
        },
        "is_active": {
          "type": "boolean"
        },
        "invoice_template": {
          "type": "object",
          "additionalProperties": {}
        },
        "max_generations": {
          "type": "number"
        }
      },
      "required": [
        "client_id",
        "name",
        "frequency",
        "start_date",
        "invoice_template"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "delete-_api_v1_invoices_recurring_id",
    "method": "delete",
    "path": "/api/v1/invoices/recurring/{id}",
    "displayName": "Delete recurring invoice template",
    "summary": "Delete recurring invoice template",
    "description": "Current implementation is TODO and returns 204 without delete persistence.",
    "tags": [
      "Invoices"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Path UUID parameter resolved by ApiBaseController.extractIdFromPath().",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Path UUID parameter resolved by ApiBaseController.extractIdFromPath()."
        }
      }
    ]
  },
  {
    "id": "get-_api_v1_invoices_search",
    "method": "get",
    "path": "/api/v1/invoices/search",
    "displayName": "Search invoices",
    "summary": "Search invoices",
    "description": "Searches invoices by free-text q with paginated response.",
    "tags": [
      "Invoices"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "page",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "limit",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "sort",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "order",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "asc",
            "desc"
          ]
        }
      },
      {
        "name": "include_items",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ]
        }
      },
      {
        "name": "include_client",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ]
        }
      },
      {
        "name": "include_billing_cycle",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ]
        }
      },
      {
        "name": "include_transactions",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ]
        }
      },
      {
        "name": "q",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "from",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "to",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "format",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "json",
            "csv"
          ]
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "type": "array",
          "items": {
            "type": "object",
            "additionalProperties": {}
          }
        },
        "pagination": {
          "type": "object",
          "properties": {
            "page": {
              "type": "integer"
            },
            "limit": {
              "type": "integer"
            },
            "total": {
              "type": "integer"
            },
            "totalPages": {
              "type": "integer"
            },
            "hasNext": {
              "type": "boolean"
            },
            "hasPrev": {
              "type": "boolean"
            }
          },
          "required": [
            "page",
            "limit",
            "total",
            "totalPages",
            "hasNext",
            "hasPrev"
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data",
        "pagination"
      ]
    }
  },
  {
    "id": "get-_api_v1_invoices_id",
    "method": "get",
    "path": "/api/v1/invoices/{id}",
    "displayName": "Get invoice by id",
    "summary": "Get invoice by id",
    "description": "Returns one invoice with optional include flags.",
    "tags": [
      "Invoices"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Path UUID parameter resolved by ApiBaseController.extractIdFromPath().",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Path UUID parameter resolved by ApiBaseController.extractIdFromPath()."
        }
      },
      {
        "name": "page",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "limit",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "sort",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "order",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "asc",
            "desc"
          ]
        }
      },
      {
        "name": "include_items",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ]
        }
      },
      {
        "name": "include_client",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ]
        }
      },
      {
        "name": "include_billing_cycle",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ]
        }
      },
      {
        "name": "include_transactions",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ]
        }
      },
      {
        "name": "q",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "from",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "to",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "format",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "json",
            "csv"
          ]
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "put-_api_v1_invoices_id",
    "method": "put",
    "path": "/api/v1/invoices/{id}",
    "displayName": "Update invoice",
    "summary": "Update invoice",
    "description": "Updates an invoice using ApiBaseController.update().",
    "tags": [
      "Invoices"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Path UUID parameter resolved by ApiBaseController.extractIdFromPath().",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Path UUID parameter resolved by ApiBaseController.extractIdFromPath()."
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "client_id": {
          "type": "string",
          "format": "uuid"
        },
        "invoice_date": {
          "type": "string"
        },
        "due_date": {
          "type": "string"
        },
        "subtotal": {
          "type": "integer",
          "minimum": 0
        },
        "tax": {
          "type": "integer",
          "minimum": 0
        },
        "total_amount": {
          "type": "integer",
          "minimum": 0
        },
        "status": {
          "type": "string",
          "enum": [
            "draft",
            "sent",
            "paid",
            "overdue",
            "cancelled",
            "pending",
            "prepayment",
            "partially_applied"
          ]
        },
        "credit_applied": {
          "type": "integer",
          "minimum": 0
        },
        "is_manual": {
          "type": "boolean"
        },
        "is_prepayment": {
          "type": "boolean"
        },
        "items": {
          "type": "array",
          "items": {
            "type": "object",
            "additionalProperties": {}
          }
        }
      },
      "additionalProperties": {}
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "delete-_api_v1_invoices_id",
    "method": "delete",
    "path": "/api/v1/invoices/{id}",
    "displayName": "Delete invoice",
    "summary": "Delete invoice",
    "description": "Deletes one invoice using ApiBaseController.delete().",
    "tags": [
      "Invoices"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Path UUID parameter resolved by ApiBaseController.extractIdFromPath().",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Path UUID parameter resolved by ApiBaseController.extractIdFromPath()."
        }
      }
    ]
  },
  {
    "id": "post-_api_v1_invoices_id_approve",
    "method": "post",
    "path": "/api/v1/invoices/{id}/approve",
    "displayName": "Approve invoice",
    "summary": "Approve invoice",
    "description": "Approves one invoice; optional execution_id query is forwarded to workflow context.",
    "tags": [
      "Invoices"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Path UUID parameter resolved by ApiBaseController.extractIdFromPath().",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Path UUID parameter resolved by ApiBaseController.extractIdFromPath()."
        }
      },
      {
        "name": "execution_id",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "reason",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "post-_api_v1_invoices_id_credit",
    "method": "post",
    "path": "/api/v1/invoices/{id}/credit",
    "displayName": "Apply credit to invoice",
    "summary": "Apply credit to invoice",
    "description": "Applies credit amount to one invoice.",
    "tags": [
      "Invoices"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Path UUID parameter resolved by ApiBaseController.extractIdFromPath().",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Path UUID parameter resolved by ApiBaseController.extractIdFromPath()."
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "credit_amount": {
          "type": "integer",
          "minimum": 0
        },
        "transaction_id": {
          "type": "string",
          "format": "uuid"
        }
      },
      "required": [
        "credit_amount"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "post-_api_v1_invoices_id_duplicate",
    "method": "post",
    "path": "/api/v1/invoices/{id}/duplicate",
    "displayName": "Duplicate invoice",
    "summary": "Duplicate invoice",
    "description": "Clones an invoice into a new draft/manual invoice.",
    "tags": [
      "Invoices"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Path UUID parameter resolved by ApiBaseController.extractIdFromPath().",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Path UUID parameter resolved by ApiBaseController.extractIdFromPath()."
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "post-_api_v1_invoices_id_finalize",
    "method": "post",
    "path": "/api/v1/invoices/{id}/finalize",
    "displayName": "Finalize invoice",
    "summary": "Finalize invoice",
    "description": "Finalizes one invoice. invoice_id is path-derived and merged into finalize schema.",
    "tags": [
      "Invoices"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Path UUID parameter resolved by ApiBaseController.extractIdFromPath().",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Path UUID parameter resolved by ApiBaseController.extractIdFromPath()."
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "finalized_at": {
          "type": "string"
        }
      }
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "post-_api_v1_invoices_id_payment",
    "method": "post",
    "path": "/api/v1/invoices/{id}/payment",
    "displayName": "Record invoice payment",
    "summary": "Record invoice payment",
    "description": "Records payment for one invoice.",
    "tags": [
      "Invoices"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Path UUID parameter resolved by ApiBaseController.extractIdFromPath().",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Path UUID parameter resolved by ApiBaseController.extractIdFromPath()."
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "payment_amount": {
          "type": "integer",
          "minimum": 0
        },
        "payment_method": {
          "type": "string"
        },
        "payment_date": {
          "type": "string"
        },
        "reference_number": {
          "type": "string"
        },
        "notes": {
          "type": "string"
        }
      },
      "required": [
        "payment_amount",
        "payment_method"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "post-_api_v1_invoices_id_reject",
    "method": "post",
    "path": "/api/v1/invoices/{id}/reject",
    "displayName": "Reject invoice",
    "summary": "Reject invoice",
    "description": "Rejects one invoice. Optional reason/execution_id come from query string.",
    "tags": [
      "Invoices"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Path UUID parameter resolved by ApiBaseController.extractIdFromPath().",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Path UUID parameter resolved by ApiBaseController.extractIdFromPath()."
        }
      },
      {
        "name": "execution_id",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "reason",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "post-_api_v1_invoices_id_send",
    "method": "post",
    "path": "/api/v1/invoices/{id}/send",
    "displayName": "Send invoice",
    "summary": "Send invoice",
    "description": "Sends one invoice to provided recipient addresses.",
    "tags": [
      "Invoices"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Path UUID parameter resolved by ApiBaseController.extractIdFromPath().",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Path UUID parameter resolved by ApiBaseController.extractIdFromPath()."
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "email_addresses": {
          "type": "array",
          "items": {
            "type": "string",
            "format": "email"
          },
          "minItems": 1
        },
        "subject": {
          "type": "string"
        },
        "message": {
          "type": "string"
        },
        "include_pdf": {
          "type": "boolean"
        }
      },
      "required": [
        "email_addresses"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "post-_api_v1_invoices_id_tax",
    "method": "post",
    "path": "/api/v1/invoices/{id}/tax",
    "displayName": "Calculate invoice tax",
    "summary": "Calculate invoice tax",
    "description": "Calculates tax for invoice context; uses billing permission gate.",
    "tags": [
      "Invoices"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Path UUID parameter resolved by ApiBaseController.extractIdFromPath().",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Path UUID parameter resolved by ApiBaseController.extractIdFromPath()."
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "client_id": {
          "type": "string",
          "format": "uuid"
        },
        "amount": {
          "type": "integer",
          "minimum": 0
        },
        "tax_region": {
          "type": "string"
        },
        "calculation_date": {
          "type": "string"
        }
      },
      "required": [
        "client_id",
        "amount",
        "tax_region"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_invoices_id_items",
    "method": "get",
    "path": "/api/v1/invoices/{id}/items",
    "displayName": "List invoice items",
    "summary": "List invoice items",
    "description": "Returns invoice_charges array for one invoice id.",
    "tags": [
      "Invoices"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Path UUID parameter resolved by ApiBaseController.extractIdFromPath().",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Path UUID parameter resolved by ApiBaseController.extractIdFromPath()."
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_invoices_id_transactions",
    "method": "get",
    "path": "/api/v1/invoices/{id}/transactions",
    "displayName": "List invoice transactions",
    "summary": "List invoice transactions",
    "description": "Returns transactions array for one invoice id.",
    "tags": [
      "Invoices"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Path UUID parameter resolved by ApiBaseController.extractIdFromPath().",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Path UUID parameter resolved by ApiBaseController.extractIdFromPath()."
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_invoices_id_pdf",
    "method": "get",
    "path": "/api/v1/invoices/{id}/pdf",
    "displayName": "Redirect to invoice PDF download",
    "summary": "Redirect to invoice PDF download",
    "description": "Attempts to generate/load PDF metadata and redirects to download_url when present.",
    "tags": [
      "Invoices"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Path UUID parameter resolved by ApiBaseController.extractIdFromPath().",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Path UUID parameter resolved by ApiBaseController.extractIdFromPath()."
        }
      }
    ]
  },
  {
    "id": "post-_api_v1_invoices_id_pdf",
    "method": "post",
    "path": "/api/v1/invoices/{id}/pdf",
    "displayName": "Generate invoice PDF asset",
    "summary": "Generate invoice PDF asset",
    "description": "Generates/refreshes invoice PDF metadata and returns file_id plus optional download_url.",
    "tags": [
      "Invoices"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Path UUID parameter resolved by ApiBaseController.extractIdFromPath().",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Path UUID parameter resolved by ApiBaseController.extractIdFromPath()."
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_financial",
    "method": "get",
    "path": "/api/v1/financial",
    "displayName": "Financial API namespace root",
    "summary": "Financial API namespace root",
    "description": "Namespace root with no resource of its own — it returns 404. Use the financial sub-resources instead: /api/v1/financial/invoices, /api/v1/financial/transactions, /api/v1/financial/credits, /api/v1/financial/bulk/{invoices,transactions,credits}, and /api/v1/billing-analytics/overview.",
    "tags": [
      "Financial"
    ],
    "approvalRequired": false,
    "parameters": []
  },
  {
    "id": "get-_api_v1_kbarticles",
    "method": "get",
    "path": "/api/v1/kb-articles",
    "displayName": "List knowledge base articles",
    "summary": "List knowledge base articles",
    "description": "List knowledge base articles with optional filtering by status, audience, type, and category. Returns paginated results with article metadata and document names.",
    "tags": [
      "Knowledge Base"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "page",
        "in": "query",
        "required": false,
        "schema": {
          "type": "integer",
          "minimum": 1
        }
      },
      {
        "name": "limit",
        "in": "query",
        "required": false,
        "schema": {
          "type": "integer",
          "minimum": 1,
          "maximum": 100
        }
      },
      {
        "name": "status",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "draft",
            "review",
            "published",
            "archived"
          ]
        }
      },
      {
        "name": "audience",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "internal",
            "client",
            "public"
          ]
        }
      },
      {
        "name": "article_type",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "how_to",
            "faq",
            "troubleshooting",
            "reference"
          ]
        }
      },
      {
        "name": "category_id",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      },
      {
        "name": "search",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "type": "array",
          "items": {
            "$ref": "#/components/schemas/KbArticle"
          }
        },
        "pagination": {
          "type": "object",
          "properties": {
            "page": {
              "type": "integer"
            },
            "limit": {
              "type": "integer"
            },
            "total": {
              "type": "integer"
            },
            "totalPages": {
              "type": "integer"
            },
            "hasNext": {
              "type": "boolean"
            },
            "hasPrev": {
              "type": "boolean"
            }
          },
          "required": [
            "page",
            "limit",
            "total",
            "totalPages",
            "hasNext",
            "hasPrev"
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data",
        "pagination"
      ]
    },
    "examples": [
      {
        "name": "List published articles",
        "request": {
          "query": {
            "status": "published",
            "limit": 10
          }
        }
      },
      {
        "name": "Search articles",
        "request": {
          "query": {
            "search": "password reset"
          }
        }
      }
    ]
  },
  {
    "id": "post-_api_v1_kbarticles",
    "method": "post",
    "path": "/api/v1/kb-articles",
    "displayName": "Create a knowledge base article",
    "summary": "Create a knowledge base article",
    "description": "Create a new KB article. Before creating, call GET /api/v1/kb-articles/categories to find available categories. Content can be markdown text or BlockNote JSON. Articles are created in 'draft' status — call POST /api/v1/kb-articles/{id}/publish to make them visible.",
    "tags": [
      "Knowledge Base"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "title": {
          "type": "string",
          "minLength": 1,
          "maxLength": 255
        },
        "slug": {
          "type": "string",
          "description": "Optional; generated from the title when omitted."
        },
        "article_type": {
          "type": "string",
          "enum": [
            "how_to",
            "faq",
            "troubleshooting",
            "reference"
          ],
          "description": "Defaults to how_to."
        },
        "audience": {
          "type": "string",
          "enum": [
            "internal",
            "client",
            "public"
          ],
          "description": "Defaults to internal."
        },
        "category_id": {
          "type": "string",
          "format": "uuid"
        },
        "review_cycle_days": {
          "type": "integer"
        },
        "content": {
          "type": "string",
          "description": "Initial body content."
        },
        "content_format": {
          "type": "string",
          "enum": [
            "markdown",
            "blocknote"
          ],
          "description": "Defaults to markdown."
        }
      },
      "required": [
        "title"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "$ref": "#/components/schemas/KbArticle"
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    },
    "examples": [
      {
        "name": "Create a how-to article with markdown content",
        "request": {
          "body": {
            "title": "How to Reset User Password",
            "article_type": "how_to",
            "audience": "internal",
            "content": "# Steps\n\n1. Navigate to Settings > Users\n2. Find the user\n3. Click Reset Password\n4. The user will receive an email with a reset link",
            "content_format": "markdown"
          }
        }
      },
      {
        "name": "Create a troubleshooting article for clients",
        "request": {
          "body": {
            "title": "VPN Connection Issues",
            "article_type": "troubleshooting",
            "audience": "client",
            "content": "# Problem\n\nVPN disconnects frequently.\n\n# Solution\n\n1. Check your internet connection\n2. Restart the VPN client\n3. If the issue persists, contact support",
            "content_format": "markdown"
          }
        }
      }
    ]
  },
  {
    "id": "get-_api_v1_kbarticles_categories",
    "method": "get",
    "path": "/api/v1/kb-articles/categories",
    "displayName": "List KB article categories",
    "summary": "List KB article categories",
    "description": "List available categories for KB articles. Call this before creating articles to find the right category_id.",
    "tags": [
      "Knowledge Base"
    ],
    "approvalRequired": false,
    "parameters": [],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "category_id": {
                "type": "string",
                "format": "uuid"
              },
              "category_name": {
                "type": "string"
              },
              "display_order": {
                "type": "integer"
              }
            },
            "required": [
              "category_id",
              "category_name"
            ]
          }
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_kbarticles_templates",
    "method": "get",
    "path": "/api/v1/kb-articles/templates",
    "displayName": "List KB article templates",
    "summary": "List KB article templates",
    "description": "List KB article templates. Templates provide pre-built content structures for different article types.",
    "tags": [
      "Knowledge Base"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "article_type",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "how_to",
            "faq",
            "troubleshooting",
            "reference"
          ]
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "template_id": {
                "type": "string",
                "format": "uuid"
              },
              "name": {
                "type": "string"
              },
              "article_type": {
                "type": "string",
                "enum": [
                  "how_to",
                  "faq",
                  "troubleshooting",
                  "reference"
                ]
              }
            },
            "required": [
              "template_id",
              "name"
            ]
          }
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "post-_api_v1_kbarticles_fromticket_ticketid",
    "method": "post",
    "path": "/api/v1/kb-articles/from-ticket/{ticketId}",
    "displayName": "Create a KB article from a ticket",
    "summary": "Create a KB article from a ticket",
    "description": "Create a KB article pre-populated from a ticket's title, description, and resolution. Useful for turning resolved tickets into knowledge base documentation.",
    "tags": [
      "Knowledge Base"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "ticketId",
        "in": "path",
        "required": true,
        "description": "Source ticket UUID.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Source ticket UUID."
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "$ref": "#/components/schemas/KbArticle"
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_kbarticles_id",
    "method": "get",
    "path": "/api/v1/kb-articles/{id}",
    "displayName": "Get a knowledge base article",
    "summary": "Get a knowledge base article",
    "description": "Get a KB article by ID, including its document name and block content data.",
    "tags": [
      "Knowledge Base"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "KB article UUID.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "KB article UUID."
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "$ref": "#/components/schemas/KbArticle"
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "put-_api_v1_kbarticles_id",
    "method": "put",
    "path": "/api/v1/kb-articles/{id}",
    "displayName": "Update a knowledge base article",
    "summary": "Update a knowledge base article",
    "description": "Update KB article metadata (title, slug, type, audience, category, status). To update the article body content, use PUT /api/v1/kb-articles/{id}/content instead.",
    "tags": [
      "Knowledge Base"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "KB article UUID.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "KB article UUID."
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "title": {
          "type": "string",
          "minLength": 1,
          "maxLength": 255
        },
        "slug": {
          "type": "string"
        },
        "article_type": {
          "type": "string",
          "enum": [
            "how_to",
            "faq",
            "troubleshooting",
            "reference"
          ]
        },
        "audience": {
          "type": "string",
          "enum": [
            "internal",
            "client",
            "public"
          ]
        },
        "category_id": {
          "type": "string",
          "format": "uuid"
        },
        "review_cycle_days": {
          "type": "integer"
        },
        "status": {
          "type": "string",
          "enum": [
            "draft",
            "review",
            "published",
            "archived"
          ]
        }
      }
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "$ref": "#/components/schemas/KbArticle"
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "delete-_api_v1_kbarticles_id",
    "method": "delete",
    "path": "/api/v1/kb-articles/{id}",
    "displayName": "Delete a knowledge base article",
    "summary": "Delete a knowledge base article",
    "description": "Deletes the KB article and cascades to remove the linked document and its block content.",
    "tags": [
      "Knowledge Base"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "KB article UUID.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "KB article UUID."
        }
      }
    ]
  },
  {
    "id": "post-_api_v1_kbarticles_id_archive",
    "method": "post",
    "path": "/api/v1/kb-articles/{id}/archive",
    "displayName": "Archive a knowledge base article",
    "summary": "Archive a knowledge base article",
    "description": "Sets the article status to archived and clears client visibility on the linked document. Returns the updated article.",
    "tags": [
      "Knowledge Base"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "KB article UUID.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "KB article UUID."
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "$ref": "#/components/schemas/KbArticle"
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_kbarticles_id_content",
    "method": "get",
    "path": "/api/v1/kb-articles/{id}/content",
    "displayName": "Get KB article content as text",
    "summary": "Get KB article content as text",
    "description": "Get the body content of a KB article as readable markdown text. Use this to read what an article currently says.",
    "tags": [
      "Knowledge Base"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "KB article UUID.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "KB article UUID."
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "type": "object",
          "properties": {
            "article_id": {
              "type": "string",
              "format": "uuid"
            },
            "content": {
              "type": "string",
              "description": "Article body rendered as readable text."
            }
          },
          "required": [
            "content"
          ]
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "put-_api_v1_kbarticles_id_content",
    "method": "put",
    "path": "/api/v1/kb-articles/{id}/content",
    "displayName": "Update KB article content",
    "summary": "Update KB article content",
    "description": "Update the body content of a KB article. Send content as markdown (default) or BlockNote JSON. Markdown is recommended for AI-generated content.",
    "tags": [
      "Knowledge Base"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "KB article UUID.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "KB article UUID."
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "content": {
          "type": "string",
          "minLength": 1
        },
        "format": {
          "type": "string",
          "enum": [
            "markdown",
            "blocknote"
          ],
          "description": "Defaults to markdown."
        }
      },
      "required": [
        "content"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "$ref": "#/components/schemas/KbArticle"
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    },
    "examples": [
      {
        "name": "Update content with markdown",
        "request": {
          "body": {
            "content": "# Updated Article\n\nNew content goes here.",
            "format": "markdown"
          }
        }
      }
    ]
  },
  {
    "id": "post-_api_v1_kbarticles_id_publish",
    "method": "post",
    "path": "/api/v1/kb-articles/{id}/publish",
    "displayName": "Publish a knowledge base article",
    "summary": "Publish a knowledge base article",
    "description": "Publish a KB article. Sets status to 'published' and auto-enables client visibility for client/public audience articles.",
    "tags": [
      "Knowledge Base"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "KB article UUID.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "KB article UUID."
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "$ref": "#/components/schemas/KbArticle"
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_billing",
    "method": "get",
    "path": "/api/v1/billing",
    "displayName": "Billing API namespace root",
    "summary": "Billing API namespace root",
    "description": "Namespace root with no resource of its own — it returns 404. Use /api/v1/financial/invoices, /api/v1/financial/transactions, /api/v1/financial/credits, and /api/v1/billing-analytics/overview.",
    "tags": [
      "Billing"
    ],
    "approvalRequired": false,
    "parameters": []
  },
  {
    "id": "get-_api_v1_comments",
    "method": "get",
    "path": "/api/v1/comments",
    "displayName": "Comments API namespace root",
    "summary": "Comments API namespace root",
    "description": "Namespace root with no resource of its own — it returns 404. Comments are accessed per ticket: /api/v1/tickets/{id}/comments and its sub-paths.",
    "tags": [
      "Comments"
    ],
    "approvalRequired": false,
    "parameters": []
  },
  {
    "id": "get-_api_v1_documents",
    "method": "get",
    "path": "/api/v1/documents",
    "displayName": "Documents API namespace root",
    "summary": "Documents API namespace root",
    "description": "Namespace root with no resource of its own — it returns 404. Documents are accessed per parent entity, e.g. /api/v1/tickets/{id}/documents.",
    "tags": [
      "Documents"
    ],
    "approvalRequired": false,
    "parameters": []
  },
  {
    "id": "get-_api_v1_email",
    "method": "get",
    "path": "/api/v1/email",
    "displayName": "Email API namespace root",
    "summary": "Email API namespace root",
    "description": "Namespace root with no resource of its own — it returns 404. Use the email provider and webhook endpoints rather than this root.",
    "tags": [
      "Email"
    ],
    "approvalRequired": false,
    "parameters": []
  },
  {
    "id": "post-_api_v1_ai_documentassist",
    "method": "post",
    "path": "/api/v1/ai/document-assist",
    "displayName": "AI document assistance (streaming, EE)",
    "summary": "AI document assistance (streaming, EE)",
    "description": "Streams AI-generated document edits using the tenant's configured LLM provider. Enterprise Edition feature gated by the AI add-on tier and a feature flag; authenticated with the AI_DOCUMENT_API_KEY via the x-api-key header. Returns a streamed text response (501 on Community Edition).",
    "tags": [
      "AI"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "instruction": {
          "type": "string",
          "description": "What the assistant should do."
        },
        "documentContext": {
          "type": "string",
          "description": "Current document text/context."
        },
        "documentId": {
          "type": "string",
          "format": "uuid"
        },
        "tenantId": {
          "type": "string",
          "format": "uuid"
        },
        "connectedUserNames": {
          "type": "array",
          "items": {
            "type": "string"
          }
        }
      },
      "required": [
        "instruction",
        "documentContext",
        "tenantId"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_software_search",
    "method": "get",
    "path": "/api/v1/software/search",
    "displayName": "Search software across the fleet",
    "summary": "Search software across the fleet",
    "description": "Searches installed software across all assets in the tenant, with filters for name/publisher search, category, software_type, is_managed, is_security_relevant, and client_id. Paginated. Authenticated by the global x-api-key middleware and tenant-scoped by the underlying withAuth action (it calls the searchSoftwareFleetWide server action directly rather than using a route-level controller wrapper).",
    "tags": [
      "Software"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "search",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "category",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "software_type",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "is_managed",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ]
        }
      },
      {
        "name": "is_security_relevant",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ]
        }
      },
      {
        "name": "client_id",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      },
      {
        "name": "page",
        "in": "query",
        "required": false,
        "schema": {
          "type": "integer",
          "minimum": 1
        }
      },
      {
        "name": "limit",
        "in": "query",
        "required": false,
        "schema": {
          "type": "integer",
          "minimum": 1,
          "maximum": 200
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_priorities",
    "method": "get",
    "path": "/api/v1/priorities",
    "displayName": "List priorities",
    "summary": "List priorities",
    "description": "Lists ticket priorities for the tenant with pagination and sorting.",
    "tags": [
      "Priorities"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "page",
        "in": "query",
        "required": false,
        "schema": {
          "type": "integer",
          "minimum": 1
        }
      },
      {
        "name": "limit",
        "in": "query",
        "required": false,
        "schema": {
          "type": "integer",
          "minimum": 1,
          "maximum": 100
        }
      },
      {
        "name": "sort",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "order",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "asc",
            "desc"
          ]
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_priorities_id",
    "method": "get",
    "path": "/api/v1/priorities/{id}",
    "displayName": "Get a priority",
    "summary": "Get a priority",
    "description": "Returns a single priority by id.",
    "tags": [
      "Priorities"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "post-_api_v1_extensions_install",
    "method": "post",
    "path": "/api/v1/extensions/install",
    "displayName": "Install an extension (EE)",
    "summary": "Install an extension (EE)",
    "description": "Installs a tenant extension. Enterprise Edition feature requiring the extensions capability and the psa product; returns 501 on Community Edition.",
    "tags": [
      "Extensions"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "additionalProperties": {},
      "description": "Extension install/uninstall payload (handled by the EE extension service)."
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "post-_api_v1_extensions_uninstall",
    "method": "post",
    "path": "/api/v1/extensions/uninstall",
    "displayName": "Uninstall an extension (EE)",
    "summary": "Uninstall an extension (EE)",
    "description": "Uninstalls a tenant extension. Enterprise Edition feature requiring the extensions capability and the psa product; returns 501 on Community Edition.",
    "tags": [
      "Extensions"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "additionalProperties": {},
      "description": "Extension install/uninstall payload (handled by the EE extension service)."
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_companycontractlines",
    "method": "get",
    "path": "/api/v1/company-contract-lines",
    "displayName": "List company contract lines (deprecated)",
    "summary": "List company contract lines (deprecated)",
    "description": "Lists client contract lines (contract_lines joined to client contracts), with filters and pagination. Deprecated: use /api/v1/client-contract-lines. This path is an alias kept for backwards compatibility.",
    "tags": [
      "Contract Lines"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "page",
        "in": "query",
        "required": false,
        "schema": {
          "type": "integer",
          "minimum": 1
        }
      },
      {
        "name": "limit",
        "in": "query",
        "required": false,
        "schema": {
          "type": "integer",
          "minimum": 1,
          "maximum": 100
        }
      },
      {
        "name": "client_id",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      },
      {
        "name": "contract_line_id",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "post-_api_v1_companycontractlines",
    "method": "post",
    "path": "/api/v1/company-contract-lines",
    "displayName": "Assign contract line to client (deprecated)",
    "summary": "Assign contract line to client (deprecated)",
    "description": "Assigns a contract line to a client by cloning a template line into the client contract. Deprecated: use /api/v1/client-contract-lines. This path is an alias kept for backwards compatibility.",
    "tags": [
      "Contract Lines"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "client_id": {
          "type": "string",
          "format": "uuid"
        },
        "contract_line_id": {
          "type": "string",
          "format": "uuid"
        },
        "client_contract_id": {
          "type": "string",
          "format": "uuid"
        },
        "custom_rate": {
          "type": "number"
        }
      },
      "required": [
        "client_id",
        "contract_line_id"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "delete-_api_v1_companycontractlines_id",
    "method": "delete",
    "path": "/api/v1/company-contract-lines/{id}",
    "displayName": "Unassign contract line (deprecated)",
    "summary": "Unassign contract line (deprecated)",
    "description": "Deactivates a client-owned contract line by id. Deprecated: use /api/v1/client-contract-lines. This path is an alias kept for backwards compatibility.",
    "tags": [
      "Contract Lines"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      }
    ]
  },
  {
    "id": "get-_api_v1_accountingexports_xerocsv_clientexport",
    "method": "get",
    "path": "/api/v1/accounting-exports/xero-csv/client-export",
    "displayName": "Export clients as Xero Contacts CSV",
    "summary": "Export clients as Xero Contacts CSV",
    "description": "Generates a Xero Contacts import CSV from the tenant clients (optionally limited to clientIds). Returns a CSV file. Requires billing:manage.",
    "tags": [
      "Accounting Exports"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "clientIds",
        "in": "query",
        "required": false,
        "description": "Comma-separated client UUIDs to limit the export.",
        "schema": {
          "type": "string",
          "description": "Comma-separated client UUIDs to limit the export."
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "post-_api_v1_accountingexports_xerocsv_clientimport",
    "method": "post",
    "path": "/api/v1/accounting-exports/xero-csv/client-import",
    "displayName": "Import Xero Contacts CSV",
    "summary": "Import Xero Contacts CSV",
    "description": "Ingests a Xero Contacts CSV and matches/creates/updates clients. Accepts multipart file, JSON csvContent, or raw CSV. Supports preview mode and createNew/updateExisting/matchBy options. Requires billing:manage.",
    "tags": [
      "Accounting Exports"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "preview",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ]
        }
      },
      {
        "name": "createNew",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ]
        }
      },
      {
        "name": "updateExisting",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ]
        }
      },
      {
        "name": "matchBy",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "post-_api_v1_accountingexports_xerocsv_taximport",
    "method": "post",
    "path": "/api/v1/accounting-exports/xero-csv/tax-import",
    "displayName": "Import Xero invoice tax CSV",
    "summary": "Import Xero invoice tax CSV",
    "description": "Ingests a Xero Invoice Details Report CSV, extracts per-invoice tax amounts, and updates the matching Alga invoices. Accepts multipart file, JSON csvContent, or raw CSV; supports preview mode. Requires billing:manage.",
    "tags": [
      "Accounting Exports"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "preview",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ]
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_accountingexports_batchid_download",
    "method": "get",
    "path": "/api/v1/accounting-exports/{batchId}/download",
    "displayName": "Download an accounting export batch",
    "summary": "Download an accounting export batch",
    "description": "Regenerates and returns the export file (CSV/IIF) for a stored export batch using its registered adapter (xero_csv, quickbooks_desktop). Requires billing_settings:update.",
    "tags": [
      "Accounting Exports"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "batchId",
        "in": "path",
        "required": true,
        "description": "Export batch identifier.",
        "schema": {
          "type": "string",
          "description": "Export batch identifier."
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_projects_templates",
    "method": "get",
    "path": "/api/projects/templates",
    "displayName": "List project templates",
    "summary": "List project templates",
    "description": "Lists the tenant project templates.",
    "tags": [
      "Project Templates"
    ],
    "approvalRequired": false,
    "parameters": [],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "post-_api_projects_templates",
    "method": "post",
    "path": "/api/projects/templates",
    "displayName": "Create project template",
    "summary": "Create project template",
    "description": "Creates a project template from an existing project.",
    "tags": [
      "Project Templates"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "project_id": {
          "type": "string",
          "format": "uuid"
        },
        "template_name": {
          "type": "string",
          "minLength": 1
        },
        "description": {
          "type": "string"
        },
        "category": {
          "type": "string"
        }
      },
      "required": [
        "project_id",
        "template_name"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_projects_templates_templateid",
    "method": "get",
    "path": "/api/projects/templates/{templateId}",
    "displayName": "Get a project template",
    "summary": "Get a project template",
    "description": "Returns a single project template by id.",
    "tags": [
      "Project Templates"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "templateId",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "patch-_api_projects_templates_templateid",
    "method": "patch",
    "path": "/api/projects/templates/{templateId}",
    "displayName": "Update project template",
    "summary": "Update project template",
    "description": "Updates the template name, description, or category.",
    "tags": [
      "Project Templates"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "templateId",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "template_name": {
          "type": "string",
          "minLength": 1
        },
        "description": {
          "type": "string"
        },
        "category": {
          "type": "string"
        }
      }
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "delete-_api_projects_templates_templateid",
    "method": "delete",
    "path": "/api/projects/templates/{templateId}",
    "displayName": "Delete a project template",
    "summary": "Delete a project template",
    "description": "Deletes a project template by id.",
    "tags": [
      "Project Templates"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "templateId",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      }
    ]
  },
  {
    "id": "post-_api_projects_templates_templateid_apply",
    "method": "post",
    "path": "/api/projects/templates/{templateId}/apply",
    "displayName": "Create project from template",
    "summary": "Create project from template",
    "description": "Creates a new project from the template, copying the selected parts (phases, statuses, tasks, etc.).",
    "tags": [
      "Project Templates"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "templateId",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "project_name": {
          "type": "string",
          "minLength": 1
        },
        "client_id": {
          "type": "string",
          "format": "uuid"
        },
        "start_date": {
          "type": "string",
          "format": "date-time"
        },
        "assigned_to": {
          "type": "string",
          "format": "uuid"
        },
        "options": {
          "$ref": "#/components/schemas/ProjectTemplateCopyOptions"
        }
      },
      "required": [
        "project_name",
        "client_id"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "post-_api_projects_templates_templateid_duplicate",
    "method": "post",
    "path": "/api/projects/templates/{templateId}/duplicate",
    "displayName": "Duplicate project template",
    "summary": "Duplicate project template",
    "description": "Creates a complete copy of the template and returns the new template id. No request body.",
    "tags": [
      "Project Templates"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "templateId",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_workflowdefinitions",
    "method": "get",
    "path": "/api/workflow-definitions",
    "displayName": "List workflow definitions",
    "summary": "List workflow definitions",
    "description": "Lists workflow definitions for the tenant.",
    "tags": [
      "Workflow Definitions"
    ],
    "approvalRequired": false,
    "parameters": [],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "post-_api_workflowdefinitions",
    "method": "post",
    "path": "/api/workflow-definitions",
    "displayName": "Create workflow definition",
    "summary": "Create workflow definition",
    "description": "Creates a new workflow with a draft definition.",
    "tags": [
      "Workflow Definitions"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "key": {
          "type": "string",
          "pattern": "^[a-z0-9][a-z0-9._-]*$",
          "description": "Stable workflow key; generated when omitted."
        },
        "definition": {
          "$ref": "#/components/schemas/WorkflowDefinitionDocument"
        },
        "payloadSchemaMode": {
          "type": "string",
          "enum": [
            "inferred",
            "pinned"
          ]
        },
        "pinnedPayloadSchemaRef": {
          "type": "string"
        }
      },
      "required": [
        "definition"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "post-_api_workflowdefinitions_import",
    "method": "post",
    "path": "/api/workflow-definitions/import",
    "displayName": "Import a v1 workflow bundle",
    "summary": "Import a v1 workflow bundle",
    "description": "Imports a legacy v1 workflow bundle. Pass force=true (query) to overwrite an existing definition.",
    "tags": [
      "Workflow Definitions"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "force",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ]
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "bundle": {
          "description": "Legacy v1 workflow bundle document."
        }
      }
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "put-_api_workflowdefinitions_workflowid_metadata",
    "method": "put",
    "path": "/api/workflow-definitions/{workflowId}/metadata",
    "displayName": "Update workflow metadata",
    "summary": "Update workflow metadata",
    "description": "Updates workflow metadata: key, visibility, pause state, concurrency limit, failure thresholds, and retention policy.",
    "tags": [
      "Workflow Definitions"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "workflowId",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "key": {
          "type": "string"
        },
        "isVisible": {
          "type": "boolean"
        },
        "isPaused": {
          "type": "boolean"
        },
        "concurrencyLimit": {
          "type": "integer",
          "minimum": 0
        },
        "autoPauseOnFailure": {
          "type": "boolean"
        },
        "failureRateThreshold": {
          "type": "number",
          "minimum": 0,
          "maximum": 1
        },
        "failureRateMinRuns": {
          "type": "integer",
          "minimum": 0
        },
        "retentionPolicyOverride": {
          "type": "object",
          "additionalProperties": {}
        }
      }
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_workflowdefinitions_workflowid_version",
    "method": "get",
    "path": "/api/workflow-definitions/{workflowId}/{version}",
    "displayName": "Get a workflow version",
    "summary": "Get a workflow version",
    "description": "Returns the definition document for a specific workflow version.",
    "tags": [
      "Workflow Definitions"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "workflowId",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      },
      {
        "name": "version",
        "in": "path",
        "required": true,
        "description": "Draft version number (coerced to a positive integer).",
        "schema": {
          "type": "string",
          "description": "Draft version number (coerced to a positive integer)."
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "put-_api_workflowdefinitions_workflowid_version",
    "method": "put",
    "path": "/api/workflow-definitions/{workflowId}/{version}",
    "displayName": "Update workflow draft definition",
    "summary": "Update workflow draft definition",
    "description": "Replaces the draft definition for a specific version.",
    "tags": [
      "Workflow Definitions"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "workflowId",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      },
      {
        "name": "version",
        "in": "path",
        "required": true,
        "description": "Draft version number (coerced to a positive integer).",
        "schema": {
          "type": "string",
          "description": "Draft version number (coerced to a positive integer)."
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "definition": {
          "$ref": "#/components/schemas/WorkflowDefinitionDocument"
        }
      },
      "required": [
        "definition"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "post-_api_workflowdefinitions_workflowid_version_publish",
    "method": "post",
    "path": "/api/workflow-definitions/{workflowId}/{version}/publish",
    "displayName": "Publish a workflow version",
    "summary": "Publish a workflow version",
    "description": "Publishes the draft as an active version (auto-increments when the requested version is below the next expected). An optional definition in the body overrides the stored draft.",
    "tags": [
      "Workflow Definitions"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "workflowId",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      },
      {
        "name": "version",
        "in": "path",
        "required": true,
        "description": "Draft version number (coerced to a positive integer).",
        "schema": {
          "type": "string",
          "description": "Draft version number (coerced to a positive integer)."
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "definition": {
          "$ref": "#/components/schemas/WorkflowDefinitionDocument"
        }
      }
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_workflowruns",
    "method": "get",
    "path": "/api/workflow-runs",
    "displayName": "List workflow runs",
    "summary": "List workflow runs",
    "description": "Lists workflow runs for the tenant.",
    "tags": [
      "Workflow Runs"
    ],
    "approvalRequired": false,
    "parameters": [],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "post-_api_workflowruns",
    "method": "post",
    "path": "/api/workflow-runs",
    "displayName": "Start a workflow run",
    "summary": "Start a workflow run",
    "description": "Starts a workflow execution with an optional version override and input payload (payload capped ~2MB; rate-limited per tenant).",
    "tags": [
      "Workflow Runs"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "workflowId": {
          "type": "string"
        },
        "workflowVersion": {
          "type": "integer",
          "exclusiveMinimum": 0
        },
        "payload": {
          "type": "object",
          "additionalProperties": {}
        },
        "eventType": {
          "type": "string"
        },
        "sourcePayloadSchemaRef": {
          "type": "string"
        }
      },
      "required": [
        "workflowId"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "post-_api_workflowruns_runid_cancel",
    "method": "post",
    "path": "/api/workflow-runs/{runId}/cancel",
    "displayName": "Cancel a workflow run",
    "summary": "Cancel a workflow run",
    "description": "Stops the run and marks its waits as canceled.",
    "tags": [
      "Workflow Runs"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "runId",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string"
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "reason": {
          "type": "string",
          "description": "Audit reason for the action."
        },
        "source": {
          "type": "string",
          "description": "Origin label; defaults to 'api'."
        }
      }
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "post-_api_workflowruns_runid_replay",
    "method": "post",
    "path": "/api/workflow-runs/{runId}/replay",
    "displayName": "Replay a workflow run",
    "summary": "Replay a workflow run",
    "description": "Re-executes the workflow from the start with a new input payload.",
    "tags": [
      "Workflow Runs"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "runId",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string"
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "reason": {
          "type": "string"
        },
        "source": {
          "type": "string"
        },
        "payload": {
          "type": "object",
          "additionalProperties": {}
        }
      }
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "post-_api_workflowruns_runid_requeue",
    "method": "post",
    "path": "/api/workflow-runs/{runId}/requeue",
    "displayName": "Requeue a workflow run",
    "summary": "Requeue a workflow run",
    "description": "Re-initializes the run's event wait (for runs stuck awaiting an external event).",
    "tags": [
      "Workflow Runs"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "runId",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string"
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "reason": {
          "type": "string",
          "description": "Audit reason for the action."
        },
        "source": {
          "type": "string",
          "description": "Origin label; defaults to 'api'."
        }
      }
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "post-_api_workflowruns_runid_resume",
    "method": "post",
    "path": "/api/workflow-runs/{runId}/resume",
    "displayName": "Resume a workflow run",
    "summary": "Resume a workflow run",
    "description": "Resolves waiting steps and resumes a paused/waiting run.",
    "tags": [
      "Workflow Runs"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "runId",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string"
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "reason": {
          "type": "string",
          "description": "Audit reason for the action."
        },
        "source": {
          "type": "string",
          "description": "Origin label; defaults to 'api'."
        }
      }
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "post-_api_workflowruns_runid_retry",
    "method": "post",
    "path": "/api/workflow-runs/{runId}/retry",
    "displayName": "Retry a failed workflow run",
    "summary": "Retry a failed workflow run",
    "description": "Restarts a FAILED run from its last failed node.",
    "tags": [
      "Workflow Runs"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "runId",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string"
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "reason": {
          "type": "string",
          "description": "Audit reason for the action."
        },
        "source": {
          "type": "string",
          "description": "Origin label; defaults to 'api'."
        }
      }
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_workflow_events",
    "method": "get",
    "path": "/api/workflow/events",
    "displayName": "List workflow events",
    "summary": "List workflow events",
    "description": "Lists submitted workflow events for the tenant.",
    "tags": [
      "Workflow Runs"
    ],
    "approvalRequired": false,
    "parameters": [],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "post-_api_workflow_events",
    "method": "post",
    "path": "/api/workflow/events",
    "displayName": "Submit a workflow event",
    "summary": "Submit a workflow event",
    "description": "Injects an event into the workflow runtime, correlating it to waiting runs by event name and correlation key.",
    "tags": [
      "Workflow Runs"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "eventName": {
          "type": "string"
        },
        "workflowCorrelationKey": {
          "type": "string"
        },
        "correlationKey": {
          "type": "string"
        },
        "payloadSchemaRef": {
          "type": "string"
        },
        "payload": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "eventName"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_projects_templates_categories",
    "method": "get",
    "path": "/api/projects/templates/categories",
    "displayName": "List project template categories",
    "summary": "List project template categories",
    "description": "Lists the available project-template categories.",
    "tags": [
      "Project Templates"
    ],
    "approvalRequired": false,
    "parameters": [],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_workflowdefinitions_workflowid_versions",
    "method": "get",
    "path": "/api/workflow-definitions/{workflowId}/versions",
    "displayName": "List workflow versions",
    "summary": "List workflow versions",
    "description": "Lists the versions (draft and published) of a workflow definition.",
    "tags": [
      "Workflow Definitions"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "workflowId",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_workflowdefinitions_workflowid_export",
    "method": "get",
    "path": "/api/workflow-definitions/{workflowId}/export",
    "displayName": "Export a workflow definition",
    "summary": "Export a workflow definition",
    "description": "Exports the workflow definition document (JSON).",
    "tags": [
      "Workflow Definitions"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "workflowId",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_workflowdefinitions_workflowid_audit",
    "method": "get",
    "path": "/api/workflow-definitions/{workflowId}/audit",
    "displayName": "Get workflow audit log",
    "summary": "Get workflow audit log",
    "description": "Returns the audit-log entries for a workflow definition.",
    "tags": [
      "Workflow Definitions"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "workflowId",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_workflowdefinitions_workflowid_audit_export",
    "method": "get",
    "path": "/api/workflow-definitions/{workflowId}/audit/export",
    "displayName": "Export workflow audit log",
    "summary": "Export workflow audit log",
    "description": "Exports the workflow definition audit log.",
    "tags": [
      "Workflow Definitions"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "workflowId",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_workflowruns_deadletter",
    "method": "get",
    "path": "/api/workflow-runs/dead-letter",
    "displayName": "List dead-lettered runs",
    "summary": "List dead-lettered runs",
    "description": "Lists runs that failed terminally and were moved to the dead-letter set.",
    "tags": [
      "Workflow Runs"
    ],
    "approvalRequired": false,
    "parameters": [],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_workflowruns_export",
    "method": "get",
    "path": "/api/workflow-runs/export",
    "displayName": "Export workflow runs",
    "summary": "Export workflow runs",
    "description": "Exports workflow runs (JSON/CSV).",
    "tags": [
      "Workflow Runs"
    ],
    "approvalRequired": false,
    "parameters": [],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_workflowruns_latest",
    "method": "get",
    "path": "/api/workflow-runs/latest",
    "displayName": "Get latest workflow runs",
    "summary": "Get latest workflow runs",
    "description": "Returns the most recent workflow runs.",
    "tags": [
      "Workflow Runs"
    ],
    "approvalRequired": false,
    "parameters": [],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_workflowruns_summary",
    "method": "get",
    "path": "/api/workflow-runs/summary",
    "displayName": "Get workflow runs summary",
    "summary": "Get workflow runs summary",
    "description": "Returns aggregate run metrics across the tenant.",
    "tags": [
      "Workflow Runs"
    ],
    "approvalRequired": false,
    "parameters": [],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_workflowruns_runid",
    "method": "get",
    "path": "/api/workflow-runs/{runId}",
    "displayName": "Get a workflow run",
    "summary": "Get a workflow run",
    "description": "Returns a single workflow run by id.",
    "tags": [
      "Workflow Runs"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "runId",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string"
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_workflowruns_runid_steps",
    "method": "get",
    "path": "/api/workflow-runs/{runId}/steps",
    "displayName": "Get workflow run steps",
    "summary": "Get workflow run steps",
    "description": "Returns the step/node states for a run.",
    "tags": [
      "Workflow Runs"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "runId",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string"
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_workflowruns_runid_timeline",
    "method": "get",
    "path": "/api/workflow-runs/{runId}/timeline",
    "displayName": "Get workflow run timeline",
    "summary": "Get workflow run timeline",
    "description": "Returns the chronological event timeline for a run.",
    "tags": [
      "Workflow Runs"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "runId",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string"
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_workflowruns_runid_summary",
    "method": "get",
    "path": "/api/workflow-runs/{runId}/summary",
    "displayName": "Get workflow run summary",
    "summary": "Get workflow run summary",
    "description": "Returns a summary of a single run.",
    "tags": [
      "Workflow Runs"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "runId",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string"
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_workflowruns_runid_audit",
    "method": "get",
    "path": "/api/workflow-runs/{runId}/audit",
    "displayName": "Get workflow run audit log",
    "summary": "Get workflow run audit log",
    "description": "Returns the audit-log entries for a run.",
    "tags": [
      "Workflow Runs"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "runId",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string"
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_workflowruns_runid_audit_export",
    "method": "get",
    "path": "/api/workflow-runs/{runId}/audit/export",
    "displayName": "Export workflow run audit log",
    "summary": "Export workflow run audit log",
    "description": "Exports the audit log for a run.",
    "tags": [
      "Workflow Runs"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "runId",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string"
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_workflowruns_runid_export",
    "method": "get",
    "path": "/api/workflow-runs/{runId}/export",
    "displayName": "Export a workflow run",
    "summary": "Export a workflow run",
    "description": "Exports a single workflow run (JSON).",
    "tags": [
      "Workflow Runs"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "runId",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string"
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_workflow_events_export",
    "method": "get",
    "path": "/api/workflow/events/export",
    "displayName": "Export workflow events",
    "summary": "Export workflow events",
    "description": "Exports workflow events (JSON/CSV).",
    "tags": [
      "Workflow Runs"
    ],
    "approvalRequired": false,
    "parameters": [],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_workflow_events_summary",
    "method": "get",
    "path": "/api/workflow/events/summary",
    "displayName": "Get workflow events summary",
    "summary": "Get workflow events summary",
    "description": "Returns aggregate workflow-event metrics.",
    "tags": [
      "Workflow Runs"
    ],
    "approvalRequired": false,
    "parameters": [],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_workflow_events_eventid",
    "method": "get",
    "path": "/api/workflow/events/{eventId}",
    "displayName": "Get a workflow event",
    "summary": "Get a workflow event",
    "description": "Returns a single workflow event by id.",
    "tags": [
      "Workflow Runs"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "eventId",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string"
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_workflow_registry_actions",
    "method": "get",
    "path": "/api/workflow/registry/actions",
    "displayName": "List workflow registry actions",
    "summary": "List workflow registry actions",
    "description": "Lists every action registered in the workflow runtime — the building blocks workflow definitions can invoke — including JSON Schemas for each action's input and output. Returns a bare array (no envelope).",
    "tags": [
      "Workflow Registry"
    ],
    "approvalRequired": false,
    "parameters": [],
    "responseBodySchema": {
      "type": "array",
      "items": {
        "$ref": "#/components/schemas/WorkflowRegistryAction"
      }
    }
  },
  {
    "id": "get-_api_workflow_registry_nodes",
    "method": "get",
    "path": "/api/workflow/registry/nodes",
    "displayName": "List workflow registry node types",
    "summary": "List workflow registry node types",
    "description": "Lists the node types available to workflow definitions (triggers, control flow, action nodes, etc.) with each node's configuration JSON Schema and default retry policy. Returns a bare array (no envelope).",
    "tags": [
      "Workflow Registry"
    ],
    "approvalRequired": false,
    "parameters": [],
    "responseBodySchema": {
      "type": "array",
      "items": {
        "$ref": "#/components/schemas/WorkflowRegistryNode"
      }
    }
  },
  {
    "id": "get-_api_workflow_registry_designercatalog",
    "method": "get",
    "path": "/api/workflow/registry/designer-catalog",
    "displayName": "Get the workflow designer action catalog",
    "summary": "Get the workflow designer action catalog",
    "description": "Returns the action catalog the workflow designer renders: registry actions and integration modules grouped into tiles, filtered to the integrations actually available to the tenant. Returns a bare array of catalog records (no envelope).",
    "tags": [
      "Workflow Registry"
    ],
    "approvalRequired": false,
    "parameters": [],
    "responseBodySchema": {
      "type": "array",
      "items": {
        "type": "object",
        "additionalProperties": {},
        "description": "Catalog tile (groupKey, tileKind, actions, UI metadata)."
      }
    }
  },
  {
    "id": "get-_api_workflow_registry_schemas_schemaref",
    "method": "get",
    "path": "/api/workflow/registry/schemas/{schemaRef}",
    "displayName": "Get a workflow schema by ref",
    "summary": "Get a workflow schema by ref",
    "description": "Resolves a registered workflow schema reference (URL-encoded) to its JSON Schema document.",
    "tags": [
      "Workflow Registry"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "schemaRef",
        "in": "path",
        "required": true,
        "description": "Registered schema reference; URL-encode it in the path.",
        "schema": {
          "type": "string",
          "description": "Registered schema reference; URL-encode it in the path."
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "ref": {
          "type": "string",
          "description": "The resolved schema reference."
        },
        "schema": {
          "$ref": "#/components/schemas/WorkflowJsonSchemaDocument"
        }
      },
      "required": [
        "ref",
        "schema"
      ]
    }
  },
  {
    "id": "get-_api_projects",
    "method": "get",
    "path": "/api/projects",
    "displayName": "List projects",
    "summary": "List projects",
    "description": "Lists all projects for the tenant. Returns a bare array of project records (no envelope); responds 403 with an error message when the caller lacks project read permission.",
    "tags": [
      "Projects"
    ],
    "approvalRequired": false,
    "parameters": [],
    "responseBodySchema": {
      "type": "array",
      "items": {
        "type": "object",
        "additionalProperties": {},
        "description": "Project record."
      }
    }
  },
  {
    "id": "get-_api_files_fileid_download",
    "method": "get",
    "path": "/api/files/{fileId}/download",
    "displayName": "Download file by ID",
    "summary": "Download file by ID",
    "description": "Downloads a stored external file as an attachment by external_files.file_id. The route is skipped by API-key middleware and relies on session/tenant resolution through createTenantKnex and StorageService. Storage lookup is tenant-scoped to external_files.tenant and is_deleted=false, but the handler performs no explicit per-document authorization; any user resolved into the tenant can download a file by fileId. The response body is binary and Content-Type is taken from stored file metadata.",
    "tags": [
      "Files"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "fileId",
        "in": "path",
        "required": true,
        "description": "File UUID from external_files.file_id to download. The handler does not validate UUID syntax before querying storage metadata.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "File UUID from external_files.file_id to download. The handler does not validate UUID syntax before querying storage metadata."
        }
      }
    ]
  },
  {
    "id": "get-_api_v1_inboundwebhooks",
    "method": "get",
    "path": "/api/v1/inbound-webhooks",
    "displayName": "List inbound webhooks",
    "summary": "List inbound webhooks",
    "description": "Lists tenant inbound webhook configurations.",
    "tags": [
      "Inbound Webhooks"
    ],
    "approvalRequired": false,
    "parameters": [],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "type": "array",
          "items": {
            "$ref": "#/components/schemas/InboundWebhookConfig"
          }
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "post-_api_v1_inboundwebhooks",
    "method": "post",
    "path": "/api/v1/inbound-webhooks",
    "displayName": "Create inbound webhook",
    "summary": "Create inbound webhook",
    "description": "Creates an inbound webhook configuration and returns any one-time generated secret.",
    "tags": [
      "Inbound Webhooks"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "name": {
          "type": "string",
          "minLength": 1
        },
        "slug": {
          "type": "string",
          "pattern": "^[a-z0-9][a-z0-9-]*[a-z0-9]$|^[a-z0-9]$"
        },
        "description": {
          "type": [
            "string",
            "null"
          ]
        },
        "auth_type": {
          "type": "string",
          "enum": [
            "hmac_sha256",
            "bearer",
            "ip_allowlist",
            "path_token"
          ]
        },
        "auth_config": {
          "type": "object",
          "additionalProperties": {}
        },
        "idempotency_source": {
          "type": [
            "object",
            "null"
          ],
          "properties": {
            "type": {
              "type": "string",
              "enum": [
                "header",
                "jsonata"
              ]
            },
            "value": {
              "type": "string"
            }
          },
          "required": [
            "type",
            "value"
          ]
        },
        "idempotency_window_seconds": {
          "type": "integer",
          "exclusiveMinimum": 0
        },
        "handler_type": {
          "type": "string",
          "enum": [
            "direct_action",
            "workflow"
          ]
        },
        "handler_config": {
          "type": "object",
          "additionalProperties": {}
        },
        "is_active": {
          "type": "boolean"
        },
        "rate_limit_per_minute": {
          "type": "integer",
          "exclusiveMinimum": 0
        }
      },
      "required": [
        "name",
        "slug",
        "auth_type",
        "auth_config",
        "handler_type",
        "handler_config"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "$ref": "#/components/schemas/InboundWebhookConfig"
        },
        "secret": {
          "type": [
            "string",
            "null"
          ]
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_inboundwebhooks_actions",
    "method": "get",
    "path": "/api/v1/inbound-webhooks/actions",
    "displayName": "List inbound webhook actions",
    "summary": "List inbound webhook actions",
    "description": "Returns registered direct-action definitions with target field schemas.",
    "tags": [
      "Inbound Webhooks"
    ],
    "approvalRequired": false,
    "parameters": [],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "type": "array",
          "items": {
            "$ref": "#/components/schemas/InboundActionDefinition"
          }
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_inboundwebhooks_id",
    "method": "get",
    "path": "/api/v1/inbound-webhooks/{id}",
    "displayName": "Get inbound webhook",
    "summary": "Get inbound webhook",
    "description": "Returns a single inbound webhook configuration.",
    "tags": [
      "Inbound Webhooks"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Inbound webhook UUID.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Inbound webhook UUID."
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "$ref": "#/components/schemas/InboundWebhookConfig"
        },
        "secret": {
          "type": [
            "string",
            "null"
          ]
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "put-_api_v1_inboundwebhooks_id",
    "method": "put",
    "path": "/api/v1/inbound-webhooks/{id}",
    "displayName": "Update inbound webhook",
    "summary": "Update inbound webhook",
    "description": "Updates an inbound webhook configuration by id.",
    "tags": [
      "Inbound Webhooks"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Inbound webhook UUID.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Inbound webhook UUID."
        }
      }
    ],
    "requestBodySchema": {
      "allOf": [
        {
          "$ref": "#/components/schemas/InboundWebhookCreateInput"
        },
        {
          "type": "object",
          "properties": {
            "inbound_webhook_id": {
              "type": "string",
              "format": "uuid"
            }
          }
        }
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "$ref": "#/components/schemas/InboundWebhookConfig"
        },
        "secret": {
          "type": [
            "string",
            "null"
          ]
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "delete-_api_v1_inboundwebhooks_id",
    "method": "delete",
    "path": "/api/v1/inbound-webhooks/{id}",
    "displayName": "Delete inbound webhook",
    "summary": "Delete inbound webhook",
    "description": "Deletes an inbound webhook configuration by id.",
    "tags": [
      "Inbound Webhooks"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Inbound webhook UUID.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Inbound webhook UUID."
        }
      }
    ]
  },
  {
    "id": "post-_api_v1_inboundwebhooks_id_rotatesecret",
    "method": "post",
    "path": "/api/v1/inbound-webhooks/{id}/rotate-secret",
    "displayName": "Rotate inbound webhook secret",
    "summary": "Rotate inbound webhook secret",
    "description": "Rotates the inbound webhook authentication secret and returns the replacement once.",
    "tags": [
      "Inbound Webhooks"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Inbound webhook UUID.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Inbound webhook UUID."
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "$ref": "#/components/schemas/InboundWebhookConfig"
        },
        "secret": {
          "type": [
            "string",
            "null"
          ]
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "post-_api_v1_inboundwebhooks_id_test",
    "method": "post",
    "path": "/api/v1/inbound-webhooks/{id}/test",
    "displayName": "Send inbound webhook test request",
    "summary": "Send inbound webhook test request",
    "description": "Dispatches a synthetic inbound request through the current webhook configuration.",
    "tags": [
      "Inbound Webhooks"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Inbound webhook UUID.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Inbound webhook UUID."
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "body": {},
        "headers": {
          "type": "object",
          "additionalProperties": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            ]
          }
        }
      }
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "$ref": "#/components/schemas/InboundWebhookDelivery"
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "post-_api_v1_inboundwebhooks_id_capturesample",
    "method": "post",
    "path": "/api/v1/inbound-webhooks/{id}/capture-sample",
    "displayName": "Enable inbound webhook sample capture",
    "summary": "Enable inbound webhook sample capture",
    "description": "Enables capture mode so the next verified request stores its body as the sample payload.",
    "tags": [
      "Inbound Webhooks"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Inbound webhook UUID.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Inbound webhook UUID."
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "$ref": "#/components/schemas/InboundWebhookConfig"
        },
        "secret": {
          "type": [
            "string",
            "null"
          ]
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "delete-_api_v1_inboundwebhooks_id_capturesample",
    "method": "delete",
    "path": "/api/v1/inbound-webhooks/{id}/capture-sample",
    "displayName": "Clear inbound webhook sample payload",
    "summary": "Clear inbound webhook sample payload",
    "description": "Clears the saved sample payload and disables sample capture.",
    "tags": [
      "Inbound Webhooks"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Inbound webhook UUID.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Inbound webhook UUID."
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "$ref": "#/components/schemas/InboundWebhookConfig"
        },
        "secret": {
          "type": [
            "string",
            "null"
          ]
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_inboundwebhooks_id_deliveries",
    "method": "get",
    "path": "/api/v1/inbound-webhooks/{id}/deliveries",
    "displayName": "List inbound webhook deliveries",
    "summary": "List inbound webhook deliveries",
    "description": "Returns paginated delivery history for one inbound webhook.",
    "tags": [
      "Inbound Webhooks"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Inbound webhook UUID.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Inbound webhook UUID."
        }
      },
      {
        "name": "page",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "limit",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "status",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "pending",
            "dispatched",
            "duplicate",
            "failed"
          ]
        }
      },
      {
        "name": "date_from",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "format": "date-time"
        }
      },
      {
        "name": "date_to",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "format": "date-time"
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "type": "array",
          "items": {
            "$ref": "#/components/schemas/InboundWebhookDelivery"
          }
        },
        "meta": {
          "type": "object",
          "properties": {
            "page": {
              "type": "integer"
            },
            "limit": {
              "type": "integer"
            },
            "total": {
              "type": "integer"
            }
          },
          "required": [
            "page",
            "limit",
            "total"
          ]
        }
      },
      "required": [
        "data",
        "meta"
      ]
    }
  },
  {
    "id": "get-_api_v1_inboundwebhooks_id_deliveries_deliveryid",
    "method": "get",
    "path": "/api/v1/inbound-webhooks/{id}/deliveries/{deliveryId}",
    "displayName": "Get inbound webhook delivery",
    "summary": "Get inbound webhook delivery",
    "description": "Returns a single inbound webhook delivery row including request and response details.",
    "tags": [
      "Inbound Webhooks"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Inbound webhook UUID.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Inbound webhook UUID."
        }
      },
      {
        "name": "deliveryId",
        "in": "path",
        "required": true,
        "description": "Inbound delivery UUID.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Inbound delivery UUID."
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "$ref": "#/components/schemas/InboundWebhookDelivery"
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "post-_api_v1_inboundwebhooks_id_deliveries_deliveryid_replay",
    "method": "post",
    "path": "/api/v1/inbound-webhooks/{id}/deliveries/{deliveryId}/replay",
    "displayName": "Replay inbound webhook delivery",
    "summary": "Replay inbound webhook delivery",
    "description": "Re-dispatches a stored inbound delivery against the current webhook configuration.",
    "tags": [
      "Inbound Webhooks"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Inbound webhook UUID.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Inbound webhook UUID."
        }
      },
      {
        "name": "deliveryId",
        "in": "path",
        "required": true,
        "description": "Inbound delivery UUID.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Inbound delivery UUID."
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "$ref": "#/components/schemas/InboundWebhookDelivery"
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "post-_api_inbound_tenantslug_webhookslug",
    "method": "post",
    "path": "/api/inbound/{tenantSlug}/{webhookSlug}",
    "displayName": "Receive inbound webhook payload",
    "summary": "Receive inbound webhook payload",
    "description": "Receives a JSON payload for a tenant inbound webhook. Authentication, idempotency, rate limit, and handler behavior are controlled by the webhook configuration.",
    "tags": [
      "Inbound Webhooks"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "tenantSlug",
        "in": "path",
        "required": true,
        "description": "URL-safe tenant slug used for inbound webhook routing.",
        "schema": {
          "type": "string",
          "description": "URL-safe tenant slug used for inbound webhook routing."
        }
      },
      {
        "name": "webhookSlug",
        "in": "path",
        "required": true,
        "description": "URL-safe inbound webhook slug unique within the tenant.",
        "schema": {
          "type": "string",
          "description": "URL-safe inbound webhook slug unique within the tenant."
        }
      },
      {
        "name": "content-type",
        "in": "header",
        "required": false,
        "description": "Expected to be application/json for JSON payloads.",
        "schema": {
          "type": "string",
          "description": "Expected to be application/json for JSON payloads."
        }
      },
      {
        "name": "x-signature",
        "in": "header",
        "required": false,
        "description": "Example HMAC-SHA256 signature header. Actual header name is webhook-configurable.",
        "schema": {
          "type": "string",
          "description": "Example HMAC-SHA256 signature header. Actual header name is webhook-configurable."
        }
      },
      {
        "name": "x-idempotency-key",
        "in": "header",
        "required": false,
        "description": "Optional idempotency key header when the webhook uses a header idempotency source.",
        "schema": {
          "type": "string",
          "description": "Optional idempotency key header when the webhook uses a header idempotency source."
        }
      }
    ],
    "requestBodySchema": {},
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "delivery_id": {
          "type": "string",
          "format": "uuid"
        }
      },
      "required": [
        "delivery_id"
      ]
    }
  },
  {
    "id": "put-_api_inbound_tenantslug_webhookslug",
    "method": "put",
    "path": "/api/inbound/{tenantSlug}/{webhookSlug}",
    "displayName": "PUT inbound",
    "summary": "PUT inbound",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "inbound"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "tenantSlug",
        "in": "path",
        "required": true,
        "description": "TenantSlug path parameter.",
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "webhookSlug",
        "in": "path",
        "required": true,
        "description": "WebhookSlug path parameter.",
        "schema": {
          "type": "string"
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "properties": {}
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "patch-_api_inbound_tenantslug_webhookslug",
    "method": "patch",
    "path": "/api/inbound/{tenantSlug}/{webhookSlug}",
    "displayName": "PATCH inbound",
    "summary": "PATCH inbound",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "inbound"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "tenantSlug",
        "in": "path",
        "required": true,
        "description": "TenantSlug path parameter.",
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "webhookSlug",
        "in": "path",
        "required": true,
        "description": "WebhookSlug path parameter.",
        "schema": {
          "type": "string"
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "properties": {}
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "get-_api_health",
    "method": "get",
    "path": "/api/health",
    "displayName": "Health check",
    "summary": "Health check",
    "description": "Simple unauthenticated liveness check for the Next.js API process. It performs no database, Redis, or downstream dependency checks and returns a fixed status/version payload when the process can serve HTTP requests.",
    "tags": [
      "System"
    ],
    "approvalRequired": false,
    "parameters": [],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "status": {
          "type": "string",
          "enum": [
            "ok"
          ],
          "description": "Always ok when the API process is reachable."
        },
        "version": {
          "type": "string",
          "description": "Hardcoded API version string returned by the handler."
        }
      },
      "required": [
        "status",
        "version"
      ]
    }
  },
  {
    "id": "get-_api_healthz",
    "method": "get",
    "path": "/api/healthz",
    "displayName": "Liveness probe",
    "summary": "Liveness probe",
    "description": "Kubernetes liveness endpoint. It returns a fixed healthy status with timestamp, uptime, version, and environment when the process can serve HTTP. It does not check database, Redis, or downstream dependencies; use /api/readyz for dependency-aware readiness.",
    "tags": [
      "System"
    ],
    "approvalRequired": false,
    "parameters": [],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "status": {
          "type": "string",
          "enum": [
            "healthy"
          ],
          "description": "Always healthy when the process can serve HTTP."
        },
        "timestamp": {
          "type": "string",
          "format": "date-time",
          "description": "ISO timestamp generated when the liveness check is handled."
        },
        "uptime": {
          "type": "number",
          "minimum": 0,
          "description": "Process uptime in seconds from process.uptime()."
        },
        "version": {
          "type": "string",
          "description": "Application version from the environment/package metadata, with a fallback in the handler."
        },
        "environment": {
          "type": "string",
          "description": "NODE_ENV value returned by the Next.js /api/healthz handler."
        }
      },
      "required": [
        "status",
        "timestamp",
        "uptime",
        "version"
      ]
    }
  },
  {
    "id": "get-_api_readyz",
    "method": "get",
    "path": "/api/readyz",
    "displayName": "Readiness probe",
    "summary": "Readiness probe",
    "description": "Kubernetes readiness endpoint for the Next.js API route. It checks database connectivity with SELECT 1 and returns 200 only when critical dependencies are available. The Redis check is currently a placeholder that mirrors the database result. This endpoint is unauthenticated and is explicitly skipped by API-key middleware.",
    "tags": [
      "System"
    ],
    "approvalRequired": false,
    "parameters": [],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "status": {
          "type": "string",
          "enum": [
            "ready"
          ],
          "description": "All critical dependencies checked by this handler are available."
        },
        "timestamp": {
          "type": "string",
          "format": "date-time",
          "description": "ISO timestamp generated when the readiness check is handled."
        },
        "uptime": {
          "type": "number",
          "minimum": 0,
          "description": "Process uptime in seconds from process.uptime()."
        },
        "version": {
          "type": "string",
          "description": "Application version from npm_package_version, with handler fallback."
        },
        "checks": {
          "$ref": "#/components/schemas/ReadyzChecks"
        }
      },
      "required": [
        "status",
        "timestamp",
        "uptime",
        "version",
        "checks"
      ]
    }
  },
  {
    "id": "get-_api_installs_lookupbyhost",
    "method": "get",
    "path": "/api/installs/lookup-by-host",
    "displayName": "Lookup extension install by runner host",
    "summary": "Lookup extension install by runner host",
    "description": "Internal endpoint for extension runners. Given a runner domain, resolves the tenant, extension registry ID, and current bundle content hash needed to serve extension content. The EE implementation queries tenant_extension_install.runner_domain with an admin connection and then selects the latest extension_bundle row for the installed version. In non-EE builds the product-extension action is a stub. Requires x-api-key; the Express middleware allows the ALGA_AUTH_KEY runner secret or a valid database API key.",
    "tags": [
      "Extension Installs"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "host",
        "in": "query",
        "required": true,
        "description": "Runner domain hostname to resolve. The implementation lowercases the value and strips any port before matching tenant_extension_install.runner_domain.",
        "schema": {
          "type": "string",
          "minLength": 1,
          "description": "Runner domain hostname to resolve. The implementation lowercases the value and strips any port before matching tenant_extension_install.runner_domain."
        }
      },
      {
        "name": "x-canary",
        "in": "header",
        "required": false,
        "description": "Optional runner canary identifier used only for logging and cache variance.",
        "schema": {
          "type": "string",
          "description": "Optional runner canary identifier used only for logging and cache variance."
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "tenant_id": {
          "type": "string",
          "description": "Tenant ID from tenant_extension_install.tenant_id for the matching runner domain."
        },
        "extension_id": {
          "type": "string",
          "format": "uuid",
          "description": "Extension registry UUID from tenant_extension_install.registry_id."
        },
        "content_hash": {
          "type": "string",
          "description": "Content hash from extension_bundle.content_hash for the install version. Usually sha256:<64 hex chars>."
        }
      },
      "required": [
        "tenant_id",
        "extension_id",
        "content_hash"
      ]
    }
  },
  {
    "id": "get-_api_installs_validate",
    "method": "get",
    "path": "/api/installs/validate",
    "displayName": "Validate extension bundle content hash",
    "summary": "Validate extension bundle content hash",
    "description": "Internal endpoint for extension runners and deployment validation. It checks whether a supplied content hash belongs to the currently installed extension version for the supplied tenant and extension registry ID. The EE action uses an admin database connection, reads tenant_extension_install by tenant_id and registry_id, and checks extension_bundle for a matching version_id and content_hash. A negative validation result is returned as 200 with valid=false, not as 404. Requires x-api-key; the Express middleware allows the ALGA_AUTH_KEY runner secret or a valid database API key.",
    "tags": [
      "Extension Installs"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "tenant",
        "in": "query",
        "required": true,
        "description": "Tenant UUID from tenant_extension_install.tenant_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Tenant UUID from tenant_extension_install.tenant_id."
        }
      },
      {
        "name": "extension",
        "in": "query",
        "required": true,
        "description": "Extension registry UUID from tenant_extension_install.registry_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Extension registry UUID from tenant_extension_install.registry_id."
        }
      },
      {
        "name": "hash",
        "in": "query",
        "required": true,
        "description": "Bundle content hash to validate. The EE action accepts sha256:<64 hex chars> or a raw 64-character hex string and normalizes raw hex to sha256: form.",
        "schema": {
          "type": "string",
          "minLength": 1,
          "description": "Bundle content hash to validate. The EE action accepts sha256:<64 hex chars> or a raw 64-character hex string and normalizes raw hex to sha256: form."
        }
      },
      {
        "name": "x-canary",
        "in": "header",
        "required": false,
        "description": "Optional runner canary identifier used only for logging and cache variance.",
        "schema": {
          "type": "string",
          "description": "Optional runner canary identifier used only for logging and cache variance."
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "valid": {
          "type": "boolean",
          "description": "True when the hash matches a bundle for the currently installed extension version; false when validation completes but does not match."
        }
      },
      "required": [
        "valid"
      ]
    }
  },
  {
    "id": "get-_api_integrations_qbo_status",
    "method": "get",
    "path": "/api/integrations/qbo/status",
    "displayName": "QuickBooks Online status route unavailable",
    "summary": "QuickBooks Online status route unavailable",
    "description": "This path appears in the generated route inventory, but server/src/app/api/integrations/qbo/status/route.ts is not present in the current worktree. Without an x-api-key, API middleware returns 401 before routing. With the middleware requirement satisfied, Next.js has no handler for this path and returns the framework not-found response. QuickBooks connection status is currently exposed through server actions such as getQboConnectionStatus and through versioned QuickBooks API routes, not this inventory-only path.",
    "tags": [
      "Integrations - QuickBooks"
    ],
    "approvalRequired": false,
    "parameters": []
  },
  {
    "id": "get-_api_integrations_qbo_connect",
    "method": "get",
    "path": "/api/integrations/qbo/connect",
    "displayName": "Start QuickBooks Online OAuth flow",
    "summary": "Start QuickBooks Online OAuth flow",
    "description": "Browser-navigated endpoint that initiates the QuickBooks Online OAuth 2.0 authorization flow. The handler resolves tenant context with createTenantKnex, reads qbo_client_id from app secrets, generates a random CSRF value, embeds {tenantId, csrf} as base64url JSON in the state parameter, and redirects to Intuit at appcenter.intuit.com/connect/oauth2. The CSRF value is currently logged but not persisted, and the callback currently treats CSRF as valid. The route is not currently listed in apiKeySkipPaths, so middleware may require x-api-key before the browser can reach the handler.",
    "tags": [
      "Integrations - QuickBooks"
    ],
    "approvalRequired": false,
    "parameters": []
  },
  {
    "id": "get-_api_integrations_qbo_callback",
    "method": "get",
    "path": "/api/integrations/qbo/callback",
    "displayName": "Handle QuickBooks Online OAuth callback",
    "summary": "Handle QuickBooks Online OAuth callback",
    "description": "OAuth 2.0 redirect endpoint for QuickBooks Online. Intuit redirects the browser here with code, state, and realmId after authorization. The handler decodes tenantId and csrf from the base64url state parameter, exchanges the code for access and refresh tokens, stores credentials in the tenant secret qbo_credentials keyed by realmId, and redirects back to /msp/settings with qbo_status=success or qbo_status=failure and an error code. The route returns redirects rather than JSON from the handler. Like the connect route, it is not currently listed in apiKeySkipPaths, so middleware may reject real Intuit callbacks that do not include x-api-key.",
    "tags": [
      "Integrations - QuickBooks"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "code",
        "in": "query",
        "required": false,
        "description": "OAuth 2.0 authorization code returned by Intuit. Required unless Intuit sends an error parameter.",
        "schema": {
          "type": "string",
          "description": "OAuth 2.0 authorization code returned by Intuit. Required unless Intuit sends an error parameter."
        }
      },
      {
        "name": "state",
        "in": "query",
        "required": false,
        "description": "Base64url-encoded JSON containing tenantId and csrf generated by the connect endpoint.",
        "schema": {
          "type": "string",
          "description": "Base64url-encoded JSON containing tenantId and csrf generated by the connect endpoint."
        }
      },
      {
        "name": "realmId",
        "in": "query",
        "required": false,
        "description": "QuickBooks company/realm ID returned by Intuit.",
        "schema": {
          "type": "string",
          "description": "QuickBooks company/realm ID returned by Intuit."
        }
      },
      {
        "name": "error",
        "in": "query",
        "required": false,
        "description": "OAuth error returned by Intuit when authorization fails or is denied.",
        "schema": {
          "type": "string",
          "description": "OAuth error returned by Intuit when authorization fails or is denied."
        }
      }
    ]
  },
  {
    "id": "get-_api_v1_integrations_quickbooks_accounts",
    "method": "get",
    "path": "/api/v1/integrations/quickbooks/accounts",
    "displayName": "Get QuickBooks chart of accounts",
    "summary": "Get QuickBooks chart of accounts",
    "description": "Returns QuickBooks accounts list; current implementation is a stub empty array. Both /api/v1/integrations/quickbooks/* and /api/v1/quickbooks/* map to the same ApiQuickBooksController method (getAccounts). This family uses route handlers that instantiate ApiQuickBooksController and usually wrap calls in explicit try/catch handleApiError blocks.",
    "tags": [
      "QuickBooks v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "page",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "limit",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "active",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ]
        }
      },
      {
        "name": "search",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "entity_type",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "force_refresh",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ]
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_integrations_quickbooks_accounts_mappings",
    "method": "get",
    "path": "/api/v1/integrations/quickbooks/accounts/mappings",
    "displayName": "List account mappings",
    "summary": "List account mappings",
    "description": "Returns paginated account mapping configuration; current implementation is stubbed. Both /api/v1/integrations/quickbooks/* and /api/v1/quickbooks/* map to the same ApiQuickBooksController method (getAccountMappings). This family uses route handlers that instantiate ApiQuickBooksController and usually wrap calls in explicit try/catch handleApiError blocks.",
    "tags": [
      "QuickBooks v1"
    ],
    "approvalRequired": false,
    "parameters": [],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "type": "array",
          "items": {
            "type": "object",
            "additionalProperties": {}
          }
        },
        "pagination": {
          "type": "object",
          "properties": {
            "page": {
              "type": "integer"
            },
            "limit": {
              "type": "integer"
            },
            "total": {
              "type": "integer"
            },
            "totalPages": {
              "type": "integer"
            },
            "hasNext": {
              "type": "boolean"
            },
            "hasPrev": {
              "type": "boolean"
            }
          },
          "required": [
            "page",
            "limit",
            "total",
            "totalPages",
            "hasNext",
            "hasPrev"
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data",
        "pagination"
      ]
    }
  },
  {
    "id": "put-_api_v1_integrations_quickbooks_accounts_mappings",
    "method": "put",
    "path": "/api/v1/integrations/quickbooks/accounts/mappings",
    "displayName": "Configure account mappings",
    "summary": "Configure account mappings",
    "description": "Stores/updates account mapping configuration for integration export/import. Both /api/v1/integrations/quickbooks/* and /api/v1/quickbooks/* map to the same ApiQuickBooksController method (configureAccountMappings). This family uses route handlers that instantiate ApiQuickBooksController and usually wrap calls in explicit try/catch handleApiError blocks.",
    "tags": [
      "QuickBooks v1"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "mappings": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "account_type": {
                "type": "string",
                "enum": [
                  "income",
                  "expense",
                  "asset",
                  "liability",
                  "equity"
                ]
              },
              "alga_account_name": {
                "type": "string"
              },
              "qbo_account_id": {
                "type": "string"
              },
              "is_default": {
                "type": "boolean"
              }
            },
            "required": [
              "account_type",
              "alga_account_name",
              "qbo_account_id"
            ]
          },
          "minItems": 1
        },
        "replace_existing": {
          "type": "boolean"
        }
      },
      "required": [
        "mappings"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "post-_api_v1_integrations_quickbooks_connection_refresh",
    "method": "post",
    "path": "/api/v1/integrations/quickbooks/connection/refresh",
    "displayName": "Refresh QuickBooks connection tokens",
    "summary": "Refresh QuickBooks connection tokens",
    "description": "Refresh endpoint currently returns synthetic success payload (service TODO). Both /api/v1/integrations/quickbooks/* and /api/v1/quickbooks/* map to the same ApiQuickBooksController method (refreshConnection). This family uses route handlers that instantiate ApiQuickBooksController and usually wrap calls in explicit try/catch handleApiError blocks.",
    "tags": [
      "QuickBooks v1"
    ],
    "approvalRequired": false,
    "parameters": [],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_integrations_quickbooks_connection_status",
    "method": "get",
    "path": "/api/v1/integrations/quickbooks/connection/status",
    "displayName": "Get QuickBooks connection status",
    "summary": "Get QuickBooks connection status",
    "description": "Returns tenant connection status and quick links for integration actions. Both /api/v1/integrations/quickbooks/* and /api/v1/quickbooks/* map to the same ApiQuickBooksController method (getConnectionStatus). This family uses route handlers that instantiate ApiQuickBooksController and usually wrap calls in explicit try/catch handleApiError blocks.",
    "tags": [
      "QuickBooks v1"
    ],
    "approvalRequired": false,
    "parameters": [],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "post-_api_v1_integrations_quickbooks_connection_test",
    "method": "post",
    "path": "/api/v1/integrations/quickbooks/connection/test",
    "displayName": "Run QuickBooks connection test",
    "summary": "Run QuickBooks connection test",
    "description": "Runs connection diagnostics against configured QuickBooks tenant. Both /api/v1/integrations/quickbooks/* and /api/v1/quickbooks/* map to the same ApiQuickBooksController method (testConnection). This family uses route handlers that instantiate ApiQuickBooksController and usually wrap calls in explicit try/catch handleApiError blocks.",
    "tags": [
      "QuickBooks v1"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "testType": {
          "type": "string",
          "enum": [
            "clientInfo",
            "items",
            "customers",
            "full"
          ]
        },
        "forceRefresh": {
          "type": "boolean"
        }
      }
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_integrations_quickbooks_customers_mappings",
    "method": "get",
    "path": "/api/v1/integrations/quickbooks/customers/mappings",
    "displayName": "List customer mappings",
    "summary": "List customer mappings",
    "description": "Returns paginated customer mapping records. Both /api/v1/integrations/quickbooks/* and /api/v1/quickbooks/* map to the same ApiQuickBooksController method (getCustomerMappings). This family uses route handlers that instantiate ApiQuickBooksController and usually wrap calls in explicit try/catch handleApiError blocks.",
    "tags": [
      "QuickBooks v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "page",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "limit",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "active",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ]
        }
      },
      {
        "name": "search",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "entity_type",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "force_refresh",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ]
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "type": "array",
          "items": {
            "type": "object",
            "additionalProperties": {}
          }
        },
        "pagination": {
          "type": "object",
          "properties": {
            "page": {
              "type": "integer"
            },
            "limit": {
              "type": "integer"
            },
            "total": {
              "type": "integer"
            },
            "totalPages": {
              "type": "integer"
            },
            "hasNext": {
              "type": "boolean"
            },
            "hasPrev": {
              "type": "boolean"
            }
          },
          "required": [
            "page",
            "limit",
            "total",
            "totalPages",
            "hasNext",
            "hasPrev"
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data",
        "pagination"
      ]
    }
  },
  {
    "id": "delete-_api_v1_integrations_quickbooks_customers_mappings_mapping_id",
    "method": "delete",
    "path": "/api/v1/integrations/quickbooks/customers/mappings/{mapping_id}",
    "displayName": "Delete customer mapping",
    "summary": "Delete customer mapping",
    "description": "Delete handler currently returns 204 stub response (service TODO). Both /api/v1/integrations/quickbooks/* and /api/v1/quickbooks/* map to the same ApiQuickBooksController method (deleteCustomerMapping). This family uses route handlers that instantiate ApiQuickBooksController and usually wrap calls in explicit try/catch handleApiError blocks.",
    "tags": [
      "QuickBooks v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "mapping_id",
        "in": "path",
        "required": true,
        "description": "Mapping identifier extracted from path segment mapping_id.",
        "schema": {
          "type": "string",
          "description": "Mapping identifier extracted from path segment mapping_id."
        }
      }
    ]
  },
  {
    "id": "post-_api_v1_integrations_quickbooks_customers_sync",
    "method": "post",
    "path": "/api/v1/integrations/quickbooks/customers/sync",
    "displayName": "Sync customers",
    "summary": "Sync customers",
    "description": "Synchronizes customer entities between Alga and QuickBooks. Both /api/v1/integrations/quickbooks/* and /api/v1/quickbooks/* map to the same ApiQuickBooksController method (syncCustomers). This family uses route handlers that instantiate ApiQuickBooksController and usually wrap calls in explicit try/catch handleApiError blocks.",
    "tags": [
      "QuickBooks v1"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "client_id": {
          "type": "string",
          "format": "uuid"
        },
        "sync_type": {
          "type": "string",
          "enum": [
            "create",
            "update",
            "bidirectional"
          ]
        },
        "force_update": {
          "type": "boolean"
        },
        "include_inactive": {
          "type": "boolean"
        }
      }
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "post-_api_v1_integrations_quickbooks_diagnostics",
    "method": "post",
    "path": "/api/v1/integrations/quickbooks/diagnostics",
    "displayName": "Run QuickBooks diagnostics",
    "summary": "Run QuickBooks diagnostics",
    "description": "Runs diagnostic checks; current implementation returns synthetic health data. Both /api/v1/integrations/quickbooks/* and /api/v1/quickbooks/* map to the same ApiQuickBooksController method (runDiagnostics). This family uses route handlers that instantiate ApiQuickBooksController and usually wrap calls in explicit try/catch handleApiError blocks.",
    "tags": [
      "QuickBooks v1"
    ],
    "approvalRequired": false,
    "parameters": [],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_integrations_quickbooks_health",
    "method": "get",
    "path": "/api/v1/integrations/quickbooks/health",
    "displayName": "Get integration health",
    "summary": "Get integration health",
    "description": "Returns integration health summary from QuickBooksService. Both /api/v1/integrations/quickbooks/* and /api/v1/quickbooks/* map to the same ApiQuickBooksController method (getHealth). This family uses route handlers that instantiate ApiQuickBooksController and usually wrap calls in explicit try/catch handleApiError blocks.",
    "tags": [
      "QuickBooks v1"
    ],
    "approvalRequired": false,
    "parameters": [],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_integrations_quickbooks_health_config",
    "method": "get",
    "path": "/api/v1/integrations/quickbooks/health/config",
    "displayName": "Get health monitoring config",
    "summary": "Get health monitoring config",
    "description": "Returns health monitoring configuration; current implementation is stubbed. Both /api/v1/integrations/quickbooks/* and /api/v1/quickbooks/* map to the same ApiQuickBooksController method (getHealthConfig). This family uses route handlers that instantiate ApiQuickBooksController and usually wrap calls in explicit try/catch handleApiError blocks.",
    "tags": [
      "QuickBooks v1"
    ],
    "approvalRequired": false,
    "parameters": [],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "put-_api_v1_integrations_quickbooks_health_config",
    "method": "put",
    "path": "/api/v1/integrations/quickbooks/health/config",
    "displayName": "Update health monitoring config",
    "summary": "Update health monitoring config",
    "description": "Updates health monitoring configuration (controller-side synthetic response). Both /api/v1/integrations/quickbooks/* and /api/v1/quickbooks/* map to the same ApiQuickBooksController method (updateHealthConfig). This family uses route handlers that instantiate ApiQuickBooksController and usually wrap calls in explicit try/catch handleApiError blocks.",
    "tags": [
      "QuickBooks v1"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "monitoring_enabled": {
          "type": "boolean"
        },
        "check_interval": {
          "type": "integer",
          "minimum": 1
        },
        "alert_thresholds": {
          "type": "object",
          "additionalProperties": {}
        }
      }
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "post-_api_v1_integrations_quickbooks_invoices_export",
    "method": "post",
    "path": "/api/v1/integrations/quickbooks/invoices/export",
    "displayName": "Export invoices to QuickBooks",
    "summary": "Export invoices to QuickBooks",
    "description": "Exports selected invoices to QuickBooks and returns job/result metadata. Both /api/v1/integrations/quickbooks/* and /api/v1/quickbooks/* map to the same ApiQuickBooksController method (exportInvoices). This family uses route handlers that instantiate ApiQuickBooksController and usually wrap calls in explicit try/catch handleApiError blocks.",
    "tags": [
      "QuickBooks v1"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "invoice_id": {
          "type": "string",
          "format": "uuid"
        },
        "date_range": {
          "type": "object",
          "properties": {
            "start_date": {
              "type": "string"
            },
            "end_date": {
              "type": "string"
            }
          },
          "required": [
            "start_date",
            "end_date"
          ]
        },
        "status_filter": {
          "type": "array",
          "items": {
            "type": "string",
            "enum": [
              "draft",
              "sent",
              "paid",
              "overdue",
              "cancelled"
            ]
          }
        },
        "client_id": {
          "type": "string",
          "format": "uuid"
        },
        "export_format": {
          "type": "string",
          "enum": [
            "qbo",
            "json"
          ]
        },
        "include_line_items": {
          "type": "boolean"
        },
        "auto_create_items": {
          "type": "boolean"
        },
        "skip_existing": {
          "type": "boolean"
        }
      }
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "post-_api_v1_integrations_quickbooks_invoices_import",
    "method": "post",
    "path": "/api/v1/integrations/quickbooks/invoices/import",
    "displayName": "Import invoices from QuickBooks",
    "summary": "Import invoices from QuickBooks",
    "description": "Imports QuickBooks invoices into Alga with optional upsert behavior. Both /api/v1/integrations/quickbooks/* and /api/v1/quickbooks/* map to the same ApiQuickBooksController method (importInvoices). This family uses route handlers that instantiate ApiQuickBooksController and usually wrap calls in explicit try/catch handleApiError blocks.",
    "tags": [
      "QuickBooks v1"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "qbo_invoice_id": {
          "type": "string"
        },
        "date_range": {
          "type": "object",
          "properties": {
            "start_date": {
              "type": "string"
            },
            "end_date": {
              "type": "string"
            }
          },
          "required": [
            "start_date",
            "end_date"
          ]
        },
        "import_payments": {
          "type": "boolean"
        },
        "auto_create_clients": {
          "type": "boolean"
        },
        "update_existing": {
          "type": "boolean"
        }
      }
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_integrations_quickbooks_items",
    "method": "get",
    "path": "/api/v1/integrations/quickbooks/items",
    "displayName": "List QuickBooks items",
    "summary": "List QuickBooks items",
    "description": "Returns items/services catalog; current implementation returns sample stub rows. Both /api/v1/integrations/quickbooks/* and /api/v1/quickbooks/* map to the same ApiQuickBooksController method (getItems). This family uses route handlers that instantiate ApiQuickBooksController and usually wrap calls in explicit try/catch handleApiError blocks.",
    "tags": [
      "QuickBooks v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "page",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "limit",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "active",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ]
        }
      },
      {
        "name": "search",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "entity_type",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "force_refresh",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ]
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_integrations_quickbooks_mappings",
    "method": "get",
    "path": "/api/v1/integrations/quickbooks/mappings",
    "displayName": "List data mappings",
    "summary": "List data mappings",
    "description": "Returns paginated list of generic QuickBooks data mapping configurations. Both /api/v1/integrations/quickbooks/* and /api/v1/quickbooks/* map to the same ApiQuickBooksController method (getDataMappings). This family uses route handlers that instantiate ApiQuickBooksController and usually wrap calls in explicit try/catch handleApiError blocks.",
    "tags": [
      "QuickBooks v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "page",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "limit",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "active",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ]
        }
      },
      {
        "name": "search",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "entity_type",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "force_refresh",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ]
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "type": "array",
          "items": {
            "type": "object",
            "additionalProperties": {}
          }
        },
        "pagination": {
          "type": "object",
          "properties": {
            "page": {
              "type": "integer"
            },
            "limit": {
              "type": "integer"
            },
            "total": {
              "type": "integer"
            },
            "totalPages": {
              "type": "integer"
            },
            "hasNext": {
              "type": "boolean"
            },
            "hasPrev": {
              "type": "boolean"
            }
          },
          "required": [
            "page",
            "limit",
            "total",
            "totalPages",
            "hasNext",
            "hasPrev"
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data",
        "pagination"
      ]
    }
  },
  {
    "id": "post-_api_v1_integrations_quickbooks_mappings",
    "method": "post",
    "path": "/api/v1/integrations/quickbooks/mappings",
    "displayName": "Create data mapping",
    "summary": "Create data mapping",
    "description": "Creates one data mapping configuration; current implementation returns synthetic mapping id. Both /api/v1/integrations/quickbooks/* and /api/v1/quickbooks/* map to the same ApiQuickBooksController method (createDataMapping). This family uses route handlers that instantiate ApiQuickBooksController and usually wrap calls in explicit try/catch handleApiError blocks.",
    "tags": [
      "QuickBooks v1"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "entity_type": {
          "type": "string",
          "enum": [
            "customer",
            "invoice",
            "payment",
            "item",
            "tax_code"
          ]
        },
        "mapping_name": {
          "type": "string"
        },
        "field_mappings": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "alga_field": {
                "type": "string"
              },
              "qbo_field": {
                "type": "string"
              },
              "transform_function": {
                "type": "string"
              },
              "is_required": {
                "type": "boolean"
              },
              "default_value": {},
              "validation_rule": {
                "type": "string"
              }
            },
            "required": [
              "alga_field",
              "qbo_field"
            ]
          },
          "minItems": 1
        },
        "is_default": {
          "type": "boolean"
        },
        "description": {
          "type": "string"
        }
      },
      "required": [
        "entity_type",
        "mapping_name",
        "field_mappings"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_integrations_quickbooks_mappings_mapping_id",
    "method": "get",
    "path": "/api/v1/integrations/quickbooks/mappings/{mapping_id}",
    "displayName": "Get data mapping by id",
    "summary": "Get data mapping by id",
    "description": "Returns one data mapping record by mapping_id. Both /api/v1/integrations/quickbooks/* and /api/v1/quickbooks/* map to the same ApiQuickBooksController method (getDataMappingById). This family uses route handlers that instantiate ApiQuickBooksController and usually wrap calls in explicit try/catch handleApiError blocks.",
    "tags": [
      "QuickBooks v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "mapping_id",
        "in": "path",
        "required": true,
        "description": "Mapping identifier extracted from path segment mapping_id.",
        "schema": {
          "type": "string",
          "description": "Mapping identifier extracted from path segment mapping_id."
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "put-_api_v1_integrations_quickbooks_mappings_mapping_id",
    "method": "put",
    "path": "/api/v1/integrations/quickbooks/mappings/{mapping_id}",
    "displayName": "Update data mapping",
    "summary": "Update data mapping",
    "description": "Updates one data mapping configuration by mapping_id. Both /api/v1/integrations/quickbooks/* and /api/v1/quickbooks/* map to the same ApiQuickBooksController method (updateDataMapping). This family uses route handlers that instantiate ApiQuickBooksController and usually wrap calls in explicit try/catch handleApiError blocks.",
    "tags": [
      "QuickBooks v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "mapping_id",
        "in": "path",
        "required": true,
        "description": "Mapping identifier extracted from path segment mapping_id.",
        "schema": {
          "type": "string",
          "description": "Mapping identifier extracted from path segment mapping_id."
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "entity_type": {
          "type": "string",
          "enum": [
            "customer",
            "invoice",
            "payment",
            "item",
            "tax_code"
          ]
        },
        "mapping_name": {
          "type": "string"
        },
        "field_mappings": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "alga_field": {
                "type": "string"
              },
              "qbo_field": {
                "type": "string"
              },
              "transform_function": {
                "type": "string"
              },
              "is_required": {
                "type": "boolean"
              },
              "default_value": {},
              "validation_rule": {
                "type": "string"
              }
            },
            "required": [
              "alga_field",
              "qbo_field"
            ]
          },
          "minItems": 1
        },
        "is_default": {
          "type": "boolean"
        },
        "description": {
          "type": "string"
        }
      },
      "required": [
        "entity_type",
        "mapping_name",
        "field_mappings"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "delete-_api_v1_integrations_quickbooks_mappings_mapping_id",
    "method": "delete",
    "path": "/api/v1/integrations/quickbooks/mappings/{mapping_id}",
    "displayName": "Delete data mapping",
    "summary": "Delete data mapping",
    "description": "Deletes one data mapping configuration (current controller returns 204 stub). Both /api/v1/integrations/quickbooks/* and /api/v1/quickbooks/* map to the same ApiQuickBooksController method (deleteDataMapping). This family uses route handlers that instantiate ApiQuickBooksController and usually wrap calls in explicit try/catch handleApiError blocks.",
    "tags": [
      "QuickBooks v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "mapping_id",
        "in": "path",
        "required": true,
        "description": "Mapping identifier extracted from path segment mapping_id.",
        "schema": {
          "type": "string",
          "description": "Mapping identifier extracted from path segment mapping_id."
        }
      }
    ]
  },
  {
    "id": "post-_api_v1_integrations_quickbooks_oauth_callback",
    "method": "post",
    "path": "/api/v1/integrations/quickbooks/oauth/callback",
    "displayName": "Handle QuickBooks OAuth callback payload",
    "summary": "Handle QuickBooks OAuth callback payload",
    "description": "Consumes OAuth callback payload with code/state/realm and persists connection tokens. Both /api/v1/integrations/quickbooks/* and /api/v1/quickbooks/* map to the same ApiQuickBooksController method (handleOAuthCallback). This family uses route handlers that instantiate ApiQuickBooksController and usually wrap calls in explicit try/catch handleApiError blocks.",
    "tags": [
      "QuickBooks v1"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "code": {
          "type": "string",
          "minLength": 1
        },
        "state": {
          "type": "string",
          "minLength": 1
        },
        "realmId": {
          "type": "string",
          "minLength": 1
        },
        "error": {
          "type": "string"
        },
        "error_description": {
          "type": "string"
        }
      },
      "required": [
        "code",
        "state",
        "realmId"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "delete-_api_v1_integrations_quickbooks_oauth_disconnect",
    "method": "delete",
    "path": "/api/v1/integrations/quickbooks/oauth/disconnect",
    "displayName": "Disconnect QuickBooks OAuth",
    "summary": "Disconnect QuickBooks OAuth",
    "description": "Revokes/disconnects QuickBooks tenant credentials and returns 204. Both /api/v1/integrations/quickbooks/* and /api/v1/quickbooks/* map to the same ApiQuickBooksController method (disconnectOAuth). This family uses route handlers that instantiate ApiQuickBooksController and usually wrap calls in explicit try/catch handleApiError blocks.",
    "tags": [
      "QuickBooks v1"
    ],
    "approvalRequired": false,
    "parameters": []
  },
  {
    "id": "post-_api_v1_integrations_quickbooks_oauth_initiate",
    "method": "post",
    "path": "/api/v1/integrations/quickbooks/oauth/initiate",
    "displayName": "Initiate QuickBooks OAuth flow",
    "summary": "Initiate QuickBooks OAuth flow",
    "description": "Generates authorization URL for QuickBooks OAuth with tenant-scoped state. Both /api/v1/integrations/quickbooks/* and /api/v1/quickbooks/* map to the same ApiQuickBooksController method (initiateOAuth). This family uses route handlers that instantiate ApiQuickBooksController and usually wrap calls in explicit try/catch handleApiError blocks.",
    "tags": [
      "QuickBooks v1"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "state": {
          "type": "string",
          "minLength": 1
        },
        "redirect_uri": {
          "type": "string",
          "format": "uri"
        },
        "scope": {
          "type": "string"
        }
      },
      "required": [
        "state"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_integrations_quickbooks_paymentmethods",
    "method": "get",
    "path": "/api/v1/integrations/quickbooks/payment-methods",
    "displayName": "List QuickBooks payment methods",
    "summary": "List QuickBooks payment methods",
    "description": "Returns payment methods; current implementation returns sample stub rows. Both /api/v1/integrations/quickbooks/* and /api/v1/quickbooks/* map to the same ApiQuickBooksController method (getPaymentMethods). This family uses route handlers that instantiate ApiQuickBooksController and usually wrap calls in explicit try/catch handleApiError blocks.",
    "tags": [
      "QuickBooks v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "page",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "limit",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "active",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ]
        }
      },
      {
        "name": "search",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "entity_type",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "force_refresh",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ]
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "post-_api_v1_integrations_quickbooks_payments_sync",
    "method": "post",
    "path": "/api/v1/integrations/quickbooks/payments/sync",
    "displayName": "Sync payments",
    "summary": "Sync payments",
    "description": "Synchronizes payment records between Alga and QuickBooks. Both /api/v1/integrations/quickbooks/* and /api/v1/quickbooks/* map to the same ApiQuickBooksController method (syncPayments). This family uses route handlers that instantiate ApiQuickBooksController and usually wrap calls in explicit try/catch handleApiError blocks.",
    "tags": [
      "QuickBooks v1"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "payment_id": {
          "type": "string",
          "format": "uuid"
        },
        "invoice_id": {
          "type": "string",
          "format": "uuid"
        },
        "date_range": {
          "type": "object",
          "properties": {
            "start_date": {
              "type": "string"
            },
            "end_date": {
              "type": "string"
            }
          },
          "required": [
            "start_date",
            "end_date"
          ]
        },
        "sync_type": {
          "type": "string",
          "enum": [
            "create",
            "update",
            "bidirectional"
          ]
        },
        "include_unapplied": {
          "type": "boolean"
        }
      }
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "post-_api_v1_integrations_quickbooks_sync_bulk",
    "method": "post",
    "path": "/api/v1/integrations/quickbooks/sync/bulk",
    "displayName": "Run bulk QuickBooks sync",
    "summary": "Run bulk QuickBooks sync",
    "description": "Starts multi-operation bulk sync and returns accepted job payload. Both /api/v1/integrations/quickbooks/* and /api/v1/quickbooks/* map to the same ApiQuickBooksController method (bulkSync). This family uses route handlers that instantiate ApiQuickBooksController and usually wrap calls in explicit try/catch handleApiError blocks.",
    "tags": [
      "QuickBooks v1"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "operations": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "operation_type": {
                "type": "string",
                "enum": [
                  "customer_sync",
                  "invoice_export",
                  "invoice_import",
                  "payment_sync",
                  "item_sync",
                  "tax_sync",
                  "full_sync",
                  "test_connection"
                ]
              },
              "entity_ids": {
                "type": "array",
                "items": {
                  "type": "string",
                  "format": "uuid"
                }
              },
              "qbo_entity_ids": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "date_range": {
                "type": "object",
                "properties": {
                  "start_date": {
                    "type": "string"
                  },
                  "end_date": {
                    "type": "string"
                  }
                },
                "required": [
                  "start_date",
                  "end_date"
                ]
              },
              "parameters": {
                "type": "object",
                "additionalProperties": {}
              }
            },
            "required": [
              "operation_type"
            ]
          },
          "minItems": 1,
          "maxItems": 10
        },
        "execution_mode": {
          "type": "string",
          "enum": [
            "sequential",
            "parallel"
          ]
        },
        "stop_on_error": {
          "type": "boolean"
        },
        "notification_email": {
          "type": "string",
          "format": "email"
        }
      },
      "required": [
        "operations"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "post-_api_v1_integrations_quickbooks_sync_full",
    "method": "post",
    "path": "/api/v1/integrations/quickbooks/sync/full",
    "displayName": "Run full QuickBooks sync",
    "summary": "Run full QuickBooks sync",
    "description": "Starts full synchronization workflow and returns accepted job payload. Both /api/v1/integrations/quickbooks/* and /api/v1/quickbooks/* map to the same ApiQuickBooksController method (fullSync). This family uses route handlers that instantiate ApiQuickBooksController and usually wrap calls in explicit try/catch handleApiError blocks.",
    "tags": [
      "QuickBooks v1"
    ],
    "approvalRequired": false,
    "parameters": [],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_integrations_quickbooks_sync_history",
    "method": "get",
    "path": "/api/v1/integrations/quickbooks/sync/history",
    "displayName": "List sync history",
    "summary": "List sync history",
    "description": "Returns paginated synchronization history with status/type/date filters. Both /api/v1/integrations/quickbooks/* and /api/v1/quickbooks/* map to the same ApiQuickBooksController method (getSyncHistory). This family uses route handlers that instantiate ApiQuickBooksController and usually wrap calls in explicit try/catch handleApiError blocks.",
    "tags": [
      "QuickBooks v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "page",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "limit",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "status",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "pending",
            "in_progress",
            "completed",
            "failed",
            "cancelled",
            "partial"
          ]
        }
      },
      {
        "name": "operation_type",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "customer_sync",
            "invoice_export",
            "invoice_import",
            "payment_sync",
            "item_sync",
            "tax_sync",
            "full_sync",
            "test_connection"
          ]
        }
      },
      {
        "name": "date_from",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "date_to",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "type": "array",
          "items": {
            "type": "object",
            "additionalProperties": {}
          }
        },
        "pagination": {
          "type": "object",
          "properties": {
            "page": {
              "type": "integer"
            },
            "limit": {
              "type": "integer"
            },
            "total": {
              "type": "integer"
            },
            "totalPages": {
              "type": "integer"
            },
            "hasNext": {
              "type": "boolean"
            },
            "hasPrev": {
              "type": "boolean"
            }
          },
          "required": [
            "page",
            "limit",
            "total",
            "totalPages",
            "hasNext",
            "hasPrev"
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data",
        "pagination"
      ]
    }
  },
  {
    "id": "get-_api_v1_integrations_quickbooks_sync_status",
    "method": "get",
    "path": "/api/v1/integrations/quickbooks/sync/status",
    "displayName": "Get current sync status",
    "summary": "Get current sync status",
    "description": "Returns current sync status summary (currently stub status payload). Both /api/v1/integrations/quickbooks/* and /api/v1/quickbooks/* map to the same ApiQuickBooksController method (getSyncStatus). This family uses route handlers that instantiate ApiQuickBooksController and usually wrap calls in explicit try/catch handleApiError blocks.",
    "tags": [
      "QuickBooks v1"
    ],
    "approvalRequired": false,
    "parameters": [],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_integrations_quickbooks_sync_status_sync_id",
    "method": "get",
    "path": "/api/v1/integrations/quickbooks/sync/status/{sync_id}",
    "displayName": "Get sync status by id",
    "summary": "Get sync status by id",
    "description": "Returns detailed status for one sync operation id. Both /api/v1/integrations/quickbooks/* and /api/v1/quickbooks/* map to the same ApiQuickBooksController method (getSyncStatusById). This family uses route handlers that instantiate ApiQuickBooksController and usually wrap calls in explicit try/catch handleApiError blocks.",
    "tags": [
      "QuickBooks v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "sync_id",
        "in": "path",
        "required": true,
        "description": "Sync operation identifier extracted from path segment sync_id.",
        "schema": {
          "type": "string",
          "description": "Sync operation identifier extracted from path segment sync_id."
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "post-_api_v1_integrations_quickbooks_sync_sync_id_cancel",
    "method": "post",
    "path": "/api/v1/integrations/quickbooks/sync/{sync_id}/cancel",
    "displayName": "Cancel sync operation",
    "summary": "Cancel sync operation",
    "description": "Cancel endpoint currently returns 204 stub response (service TODO). Both /api/v1/integrations/quickbooks/* and /api/v1/quickbooks/* map to the same ApiQuickBooksController method (cancelSync). This family uses route handlers that instantiate ApiQuickBooksController and usually wrap calls in explicit try/catch handleApiError blocks.",
    "tags": [
      "QuickBooks v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "sync_id",
        "in": "path",
        "required": true,
        "description": "Sync operation identifier extracted from path segment sync_id.",
        "schema": {
          "type": "string",
          "description": "Sync operation identifier extracted from path segment sync_id."
        }
      }
    ]
  },
  {
    "id": "post-_api_v1_integrations_quickbooks_sync_sync_id_retry",
    "method": "post",
    "path": "/api/v1/integrations/quickbooks/sync/{sync_id}/retry",
    "displayName": "Retry sync operation",
    "summary": "Retry sync operation",
    "description": "Retries a failed sync and returns synthetic new retry sync id. Both /api/v1/integrations/quickbooks/* and /api/v1/quickbooks/* map to the same ApiQuickBooksController method (retrySync). This family uses route handlers that instantiate ApiQuickBooksController and usually wrap calls in explicit try/catch handleApiError blocks.",
    "tags": [
      "QuickBooks v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "sync_id",
        "in": "path",
        "required": true,
        "description": "Sync operation identifier extracted from path segment sync_id.",
        "schema": {
          "type": "string",
          "description": "Sync operation identifier extracted from path segment sync_id."
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_integrations_quickbooks_taxcodes",
    "method": "get",
    "path": "/api/v1/integrations/quickbooks/tax-codes",
    "displayName": "List QuickBooks tax codes",
    "summary": "List QuickBooks tax codes",
    "description": "Returns tax code list; current implementation is a stub empty array. Both /api/v1/integrations/quickbooks/* and /api/v1/quickbooks/* map to the same ApiQuickBooksController method (getTaxCodes). This family uses route handlers that instantiate ApiQuickBooksController and usually wrap calls in explicit try/catch handleApiError blocks.",
    "tags": [
      "QuickBooks v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "page",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "limit",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "active",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ]
        }
      },
      {
        "name": "search",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "entity_type",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "force_refresh",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ]
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_integrations_quickbooks_taxcodes_mappings",
    "method": "get",
    "path": "/api/v1/integrations/quickbooks/tax-codes/mappings",
    "displayName": "List tax mappings",
    "summary": "List tax mappings",
    "description": "Returns paginated tax mapping configuration; current implementation is stubbed. Both /api/v1/integrations/quickbooks/* and /api/v1/quickbooks/* map to the same ApiQuickBooksController method (getTaxMappings). This family uses route handlers that instantiate ApiQuickBooksController and usually wrap calls in explicit try/catch handleApiError blocks.",
    "tags": [
      "QuickBooks v1"
    ],
    "approvalRequired": false,
    "parameters": [],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "type": "array",
          "items": {
            "type": "object",
            "additionalProperties": {}
          }
        },
        "pagination": {
          "type": "object",
          "properties": {
            "page": {
              "type": "integer"
            },
            "limit": {
              "type": "integer"
            },
            "total": {
              "type": "integer"
            },
            "totalPages": {
              "type": "integer"
            },
            "hasNext": {
              "type": "boolean"
            },
            "hasPrev": {
              "type": "boolean"
            }
          },
          "required": [
            "page",
            "limit",
            "total",
            "totalPages",
            "hasNext",
            "hasPrev"
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data",
        "pagination"
      ]
    }
  },
  {
    "id": "put-_api_v1_integrations_quickbooks_taxcodes_mappings",
    "method": "put",
    "path": "/api/v1/integrations/quickbooks/tax-codes/mappings",
    "displayName": "Configure tax mappings",
    "summary": "Configure tax mappings",
    "description": "Stores/updates mapping from Alga tax regions to QuickBooks tax codes. Both /api/v1/integrations/quickbooks/* and /api/v1/quickbooks/* map to the same ApiQuickBooksController method (configureTaxMappings). This family uses route handlers that instantiate ApiQuickBooksController and usually wrap calls in explicit try/catch handleApiError blocks.",
    "tags": [
      "QuickBooks v1"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "mappings": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "alga_tax_region": {
                "type": "string"
              },
              "qbo_tax_code_id": {
                "type": "string"
              },
              "is_default": {
                "type": "boolean"
              }
            },
            "required": [
              "alga_tax_region",
              "qbo_tax_code_id"
            ]
          },
          "minItems": 1
        },
        "replace_existing": {
          "type": "boolean"
        }
      },
      "required": [
        "mappings"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_integrations_quickbooks_terms",
    "method": "get",
    "path": "/api/v1/integrations/quickbooks/terms",
    "displayName": "List QuickBooks terms",
    "summary": "List QuickBooks terms",
    "description": "Returns payment terms catalog; current implementation returns sample stub rows. Both /api/v1/integrations/quickbooks/* and /api/v1/quickbooks/* map to the same ApiQuickBooksController method (getTerms). This family uses route handlers that instantiate ApiQuickBooksController and usually wrap calls in explicit try/catch handleApiError blocks.",
    "tags": [
      "QuickBooks v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "page",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "limit",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "active",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ]
        }
      },
      {
        "name": "search",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "entity_type",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "force_refresh",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ]
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_quickbooks_accounts",
    "method": "get",
    "path": "/api/v1/quickbooks/accounts",
    "displayName": "Get QuickBooks chart of accounts",
    "summary": "Get QuickBooks chart of accounts",
    "description": "Returns QuickBooks accounts list; current implementation is a stub empty array. Both /api/v1/integrations/quickbooks/* and /api/v1/quickbooks/* map to the same ApiQuickBooksController method (getAccounts). This family is a path alias that binds controller methods directly (for example `export const GET = controller.getAccounts()`) and relies on controller-level error handling.",
    "tags": [
      "QuickBooks v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "page",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "limit",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "active",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ]
        }
      },
      {
        "name": "search",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "entity_type",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "force_refresh",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ]
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_quickbooks_accounts_mappings",
    "method": "get",
    "path": "/api/v1/quickbooks/accounts/mappings",
    "displayName": "List account mappings",
    "summary": "List account mappings",
    "description": "Returns paginated account mapping configuration; current implementation is stubbed. Both /api/v1/integrations/quickbooks/* and /api/v1/quickbooks/* map to the same ApiQuickBooksController method (getAccountMappings). This family is a path alias that binds controller methods directly (for example `export const GET = controller.getAccounts()`) and relies on controller-level error handling.",
    "tags": [
      "QuickBooks v1"
    ],
    "approvalRequired": false,
    "parameters": [],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "type": "array",
          "items": {
            "type": "object",
            "additionalProperties": {}
          }
        },
        "pagination": {
          "type": "object",
          "properties": {
            "page": {
              "type": "integer"
            },
            "limit": {
              "type": "integer"
            },
            "total": {
              "type": "integer"
            },
            "totalPages": {
              "type": "integer"
            },
            "hasNext": {
              "type": "boolean"
            },
            "hasPrev": {
              "type": "boolean"
            }
          },
          "required": [
            "page",
            "limit",
            "total",
            "totalPages",
            "hasNext",
            "hasPrev"
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data",
        "pagination"
      ]
    }
  },
  {
    "id": "put-_api_v1_quickbooks_accounts_mappings",
    "method": "put",
    "path": "/api/v1/quickbooks/accounts/mappings",
    "displayName": "Configure account mappings",
    "summary": "Configure account mappings",
    "description": "Stores/updates account mapping configuration for integration export/import. Both /api/v1/integrations/quickbooks/* and /api/v1/quickbooks/* map to the same ApiQuickBooksController method (configureAccountMappings). This family is a path alias that binds controller methods directly (for example `export const GET = controller.getAccounts()`) and relies on controller-level error handling.",
    "tags": [
      "QuickBooks v1"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "mappings": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "account_type": {
                "type": "string",
                "enum": [
                  "income",
                  "expense",
                  "asset",
                  "liability",
                  "equity"
                ]
              },
              "alga_account_name": {
                "type": "string"
              },
              "qbo_account_id": {
                "type": "string"
              },
              "is_default": {
                "type": "boolean"
              }
            },
            "required": [
              "account_type",
              "alga_account_name",
              "qbo_account_id"
            ]
          },
          "minItems": 1
        },
        "replace_existing": {
          "type": "boolean"
        }
      },
      "required": [
        "mappings"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "post-_api_v1_quickbooks_connection_refresh",
    "method": "post",
    "path": "/api/v1/quickbooks/connection/refresh",
    "displayName": "Refresh QuickBooks connection tokens",
    "summary": "Refresh QuickBooks connection tokens",
    "description": "Refresh endpoint currently returns synthetic success payload (service TODO). Both /api/v1/integrations/quickbooks/* and /api/v1/quickbooks/* map to the same ApiQuickBooksController method (refreshConnection). This family is a path alias that binds controller methods directly (for example `export const GET = controller.getAccounts()`) and relies on controller-level error handling.",
    "tags": [
      "QuickBooks v1"
    ],
    "approvalRequired": false,
    "parameters": [],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_quickbooks_connection_status",
    "method": "get",
    "path": "/api/v1/quickbooks/connection/status",
    "displayName": "Get QuickBooks connection status",
    "summary": "Get QuickBooks connection status",
    "description": "Returns tenant connection status and quick links for integration actions. Both /api/v1/integrations/quickbooks/* and /api/v1/quickbooks/* map to the same ApiQuickBooksController method (getConnectionStatus). This family is a path alias that binds controller methods directly (for example `export const GET = controller.getAccounts()`) and relies on controller-level error handling.",
    "tags": [
      "QuickBooks v1"
    ],
    "approvalRequired": false,
    "parameters": [],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "post-_api_v1_quickbooks_connection_test",
    "method": "post",
    "path": "/api/v1/quickbooks/connection/test",
    "displayName": "Run QuickBooks connection test",
    "summary": "Run QuickBooks connection test",
    "description": "Runs connection diagnostics against configured QuickBooks tenant. Both /api/v1/integrations/quickbooks/* and /api/v1/quickbooks/* map to the same ApiQuickBooksController method (testConnection). This family is a path alias that binds controller methods directly (for example `export const GET = controller.getAccounts()`) and relies on controller-level error handling.",
    "tags": [
      "QuickBooks v1"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "testType": {
          "type": "string",
          "enum": [
            "clientInfo",
            "items",
            "customers",
            "full"
          ]
        },
        "forceRefresh": {
          "type": "boolean"
        }
      }
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_quickbooks_customers_mappings",
    "method": "get",
    "path": "/api/v1/quickbooks/customers/mappings",
    "displayName": "List customer mappings",
    "summary": "List customer mappings",
    "description": "Returns paginated customer mapping records. Both /api/v1/integrations/quickbooks/* and /api/v1/quickbooks/* map to the same ApiQuickBooksController method (getCustomerMappings). This family is a path alias that binds controller methods directly (for example `export const GET = controller.getAccounts()`) and relies on controller-level error handling.",
    "tags": [
      "QuickBooks v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "page",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "limit",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "active",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ]
        }
      },
      {
        "name": "search",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "entity_type",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "force_refresh",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ]
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "type": "array",
          "items": {
            "type": "object",
            "additionalProperties": {}
          }
        },
        "pagination": {
          "type": "object",
          "properties": {
            "page": {
              "type": "integer"
            },
            "limit": {
              "type": "integer"
            },
            "total": {
              "type": "integer"
            },
            "totalPages": {
              "type": "integer"
            },
            "hasNext": {
              "type": "boolean"
            },
            "hasPrev": {
              "type": "boolean"
            }
          },
          "required": [
            "page",
            "limit",
            "total",
            "totalPages",
            "hasNext",
            "hasPrev"
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data",
        "pagination"
      ]
    }
  },
  {
    "id": "delete-_api_v1_quickbooks_customers_mappings_mapping_id",
    "method": "delete",
    "path": "/api/v1/quickbooks/customers/mappings/{mapping_id}",
    "displayName": "Delete customer mapping",
    "summary": "Delete customer mapping",
    "description": "Delete handler currently returns 204 stub response (service TODO). Both /api/v1/integrations/quickbooks/* and /api/v1/quickbooks/* map to the same ApiQuickBooksController method (deleteCustomerMapping). This family is a path alias that binds controller methods directly (for example `export const GET = controller.getAccounts()`) and relies on controller-level error handling.",
    "tags": [
      "QuickBooks v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "mapping_id",
        "in": "path",
        "required": true,
        "description": "Mapping identifier extracted from path segment mapping_id.",
        "schema": {
          "type": "string",
          "description": "Mapping identifier extracted from path segment mapping_id."
        }
      }
    ]
  },
  {
    "id": "post-_api_v1_quickbooks_customers_sync",
    "method": "post",
    "path": "/api/v1/quickbooks/customers/sync",
    "displayName": "Sync customers",
    "summary": "Sync customers",
    "description": "Synchronizes customer entities between Alga and QuickBooks. Both /api/v1/integrations/quickbooks/* and /api/v1/quickbooks/* map to the same ApiQuickBooksController method (syncCustomers). This family is a path alias that binds controller methods directly (for example `export const GET = controller.getAccounts()`) and relies on controller-level error handling.",
    "tags": [
      "QuickBooks v1"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "client_id": {
          "type": "string",
          "format": "uuid"
        },
        "sync_type": {
          "type": "string",
          "enum": [
            "create",
            "update",
            "bidirectional"
          ]
        },
        "force_update": {
          "type": "boolean"
        },
        "include_inactive": {
          "type": "boolean"
        }
      }
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "post-_api_v1_quickbooks_diagnostics",
    "method": "post",
    "path": "/api/v1/quickbooks/diagnostics",
    "displayName": "Run QuickBooks diagnostics",
    "summary": "Run QuickBooks diagnostics",
    "description": "Runs diagnostic checks; current implementation returns synthetic health data. Both /api/v1/integrations/quickbooks/* and /api/v1/quickbooks/* map to the same ApiQuickBooksController method (runDiagnostics). This family is a path alias that binds controller methods directly (for example `export const GET = controller.getAccounts()`) and relies on controller-level error handling.",
    "tags": [
      "QuickBooks v1"
    ],
    "approvalRequired": false,
    "parameters": [],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_quickbooks_health",
    "method": "get",
    "path": "/api/v1/quickbooks/health",
    "displayName": "Get integration health",
    "summary": "Get integration health",
    "description": "Returns integration health summary from QuickBooksService. Both /api/v1/integrations/quickbooks/* and /api/v1/quickbooks/* map to the same ApiQuickBooksController method (getHealth). This family is a path alias that binds controller methods directly (for example `export const GET = controller.getAccounts()`) and relies on controller-level error handling.",
    "tags": [
      "QuickBooks v1"
    ],
    "approvalRequired": false,
    "parameters": [],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_quickbooks_health_config",
    "method": "get",
    "path": "/api/v1/quickbooks/health/config",
    "displayName": "Get health monitoring config",
    "summary": "Get health monitoring config",
    "description": "Returns health monitoring configuration; current implementation is stubbed. Both /api/v1/integrations/quickbooks/* and /api/v1/quickbooks/* map to the same ApiQuickBooksController method (getHealthConfig). This family is a path alias that binds controller methods directly (for example `export const GET = controller.getAccounts()`) and relies on controller-level error handling.",
    "tags": [
      "QuickBooks v1"
    ],
    "approvalRequired": false,
    "parameters": [],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "put-_api_v1_quickbooks_health_config",
    "method": "put",
    "path": "/api/v1/quickbooks/health/config",
    "displayName": "Update health monitoring config",
    "summary": "Update health monitoring config",
    "description": "Updates health monitoring configuration (controller-side synthetic response). Both /api/v1/integrations/quickbooks/* and /api/v1/quickbooks/* map to the same ApiQuickBooksController method (updateHealthConfig). This family is a path alias that binds controller methods directly (for example `export const GET = controller.getAccounts()`) and relies on controller-level error handling.",
    "tags": [
      "QuickBooks v1"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "monitoring_enabled": {
          "type": "boolean"
        },
        "check_interval": {
          "type": "integer",
          "minimum": 1
        },
        "alert_thresholds": {
          "type": "object",
          "additionalProperties": {}
        }
      }
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "post-_api_v1_quickbooks_invoices_export",
    "method": "post",
    "path": "/api/v1/quickbooks/invoices/export",
    "displayName": "Export invoices to QuickBooks",
    "summary": "Export invoices to QuickBooks",
    "description": "Exports selected invoices to QuickBooks and returns job/result metadata. Both /api/v1/integrations/quickbooks/* and /api/v1/quickbooks/* map to the same ApiQuickBooksController method (exportInvoices). This family is a path alias that binds controller methods directly (for example `export const GET = controller.getAccounts()`) and relies on controller-level error handling.",
    "tags": [
      "QuickBooks v1"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "invoice_id": {
          "type": "string",
          "format": "uuid"
        },
        "date_range": {
          "type": "object",
          "properties": {
            "start_date": {
              "type": "string"
            },
            "end_date": {
              "type": "string"
            }
          },
          "required": [
            "start_date",
            "end_date"
          ]
        },
        "status_filter": {
          "type": "array",
          "items": {
            "type": "string",
            "enum": [
              "draft",
              "sent",
              "paid",
              "overdue",
              "cancelled"
            ]
          }
        },
        "client_id": {
          "type": "string",
          "format": "uuid"
        },
        "export_format": {
          "type": "string",
          "enum": [
            "qbo",
            "json"
          ]
        },
        "include_line_items": {
          "type": "boolean"
        },
        "auto_create_items": {
          "type": "boolean"
        },
        "skip_existing": {
          "type": "boolean"
        }
      }
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "post-_api_v1_quickbooks_invoices_import",
    "method": "post",
    "path": "/api/v1/quickbooks/invoices/import",
    "displayName": "Import invoices from QuickBooks",
    "summary": "Import invoices from QuickBooks",
    "description": "Imports QuickBooks invoices into Alga with optional upsert behavior. Both /api/v1/integrations/quickbooks/* and /api/v1/quickbooks/* map to the same ApiQuickBooksController method (importInvoices). This family is a path alias that binds controller methods directly (for example `export const GET = controller.getAccounts()`) and relies on controller-level error handling.",
    "tags": [
      "QuickBooks v1"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "qbo_invoice_id": {
          "type": "string"
        },
        "date_range": {
          "type": "object",
          "properties": {
            "start_date": {
              "type": "string"
            },
            "end_date": {
              "type": "string"
            }
          },
          "required": [
            "start_date",
            "end_date"
          ]
        },
        "import_payments": {
          "type": "boolean"
        },
        "auto_create_clients": {
          "type": "boolean"
        },
        "update_existing": {
          "type": "boolean"
        }
      }
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_quickbooks_items",
    "method": "get",
    "path": "/api/v1/quickbooks/items",
    "displayName": "List QuickBooks items",
    "summary": "List QuickBooks items",
    "description": "Returns items/services catalog; current implementation returns sample stub rows. Both /api/v1/integrations/quickbooks/* and /api/v1/quickbooks/* map to the same ApiQuickBooksController method (getItems). This family is a path alias that binds controller methods directly (for example `export const GET = controller.getAccounts()`) and relies on controller-level error handling.",
    "tags": [
      "QuickBooks v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "page",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "limit",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "active",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ]
        }
      },
      {
        "name": "search",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "entity_type",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "force_refresh",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ]
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_quickbooks_mappings",
    "method": "get",
    "path": "/api/v1/quickbooks/mappings",
    "displayName": "List data mappings",
    "summary": "List data mappings",
    "description": "Returns paginated list of generic QuickBooks data mapping configurations. Both /api/v1/integrations/quickbooks/* and /api/v1/quickbooks/* map to the same ApiQuickBooksController method (getDataMappings). This family is a path alias that binds controller methods directly (for example `export const GET = controller.getAccounts()`) and relies on controller-level error handling.",
    "tags": [
      "QuickBooks v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "page",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "limit",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "active",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ]
        }
      },
      {
        "name": "search",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "entity_type",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "force_refresh",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ]
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "type": "array",
          "items": {
            "type": "object",
            "additionalProperties": {}
          }
        },
        "pagination": {
          "type": "object",
          "properties": {
            "page": {
              "type": "integer"
            },
            "limit": {
              "type": "integer"
            },
            "total": {
              "type": "integer"
            },
            "totalPages": {
              "type": "integer"
            },
            "hasNext": {
              "type": "boolean"
            },
            "hasPrev": {
              "type": "boolean"
            }
          },
          "required": [
            "page",
            "limit",
            "total",
            "totalPages",
            "hasNext",
            "hasPrev"
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data",
        "pagination"
      ]
    }
  },
  {
    "id": "post-_api_v1_quickbooks_mappings",
    "method": "post",
    "path": "/api/v1/quickbooks/mappings",
    "displayName": "Create data mapping",
    "summary": "Create data mapping",
    "description": "Creates one data mapping configuration; current implementation returns synthetic mapping id. Both /api/v1/integrations/quickbooks/* and /api/v1/quickbooks/* map to the same ApiQuickBooksController method (createDataMapping). This family is a path alias that binds controller methods directly (for example `export const GET = controller.getAccounts()`) and relies on controller-level error handling.",
    "tags": [
      "QuickBooks v1"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "entity_type": {
          "type": "string",
          "enum": [
            "customer",
            "invoice",
            "payment",
            "item",
            "tax_code"
          ]
        },
        "mapping_name": {
          "type": "string"
        },
        "field_mappings": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "alga_field": {
                "type": "string"
              },
              "qbo_field": {
                "type": "string"
              },
              "transform_function": {
                "type": "string"
              },
              "is_required": {
                "type": "boolean"
              },
              "default_value": {},
              "validation_rule": {
                "type": "string"
              }
            },
            "required": [
              "alga_field",
              "qbo_field"
            ]
          },
          "minItems": 1
        },
        "is_default": {
          "type": "boolean"
        },
        "description": {
          "type": "string"
        }
      },
      "required": [
        "entity_type",
        "mapping_name",
        "field_mappings"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_quickbooks_mappings_mapping_id",
    "method": "get",
    "path": "/api/v1/quickbooks/mappings/{mapping_id}",
    "displayName": "Get data mapping by id",
    "summary": "Get data mapping by id",
    "description": "Returns one data mapping record by mapping_id. Both /api/v1/integrations/quickbooks/* and /api/v1/quickbooks/* map to the same ApiQuickBooksController method (getDataMappingById). This family is a path alias that binds controller methods directly (for example `export const GET = controller.getAccounts()`) and relies on controller-level error handling.",
    "tags": [
      "QuickBooks v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "mapping_id",
        "in": "path",
        "required": true,
        "description": "Mapping identifier extracted from path segment mapping_id.",
        "schema": {
          "type": "string",
          "description": "Mapping identifier extracted from path segment mapping_id."
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "put-_api_v1_quickbooks_mappings_mapping_id",
    "method": "put",
    "path": "/api/v1/quickbooks/mappings/{mapping_id}",
    "displayName": "Update data mapping",
    "summary": "Update data mapping",
    "description": "Updates one data mapping configuration by mapping_id. Both /api/v1/integrations/quickbooks/* and /api/v1/quickbooks/* map to the same ApiQuickBooksController method (updateDataMapping). This family is a path alias that binds controller methods directly (for example `export const GET = controller.getAccounts()`) and relies on controller-level error handling.",
    "tags": [
      "QuickBooks v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "mapping_id",
        "in": "path",
        "required": true,
        "description": "Mapping identifier extracted from path segment mapping_id.",
        "schema": {
          "type": "string",
          "description": "Mapping identifier extracted from path segment mapping_id."
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "entity_type": {
          "type": "string",
          "enum": [
            "customer",
            "invoice",
            "payment",
            "item",
            "tax_code"
          ]
        },
        "mapping_name": {
          "type": "string"
        },
        "field_mappings": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "alga_field": {
                "type": "string"
              },
              "qbo_field": {
                "type": "string"
              },
              "transform_function": {
                "type": "string"
              },
              "is_required": {
                "type": "boolean"
              },
              "default_value": {},
              "validation_rule": {
                "type": "string"
              }
            },
            "required": [
              "alga_field",
              "qbo_field"
            ]
          },
          "minItems": 1
        },
        "is_default": {
          "type": "boolean"
        },
        "description": {
          "type": "string"
        }
      },
      "required": [
        "entity_type",
        "mapping_name",
        "field_mappings"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "delete-_api_v1_quickbooks_mappings_mapping_id",
    "method": "delete",
    "path": "/api/v1/quickbooks/mappings/{mapping_id}",
    "displayName": "Delete data mapping",
    "summary": "Delete data mapping",
    "description": "Deletes one data mapping configuration (current controller returns 204 stub). Both /api/v1/integrations/quickbooks/* and /api/v1/quickbooks/* map to the same ApiQuickBooksController method (deleteDataMapping). This family is a path alias that binds controller methods directly (for example `export const GET = controller.getAccounts()`) and relies on controller-level error handling.",
    "tags": [
      "QuickBooks v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "mapping_id",
        "in": "path",
        "required": true,
        "description": "Mapping identifier extracted from path segment mapping_id.",
        "schema": {
          "type": "string",
          "description": "Mapping identifier extracted from path segment mapping_id."
        }
      }
    ]
  },
  {
    "id": "post-_api_v1_quickbooks_oauth_callback",
    "method": "post",
    "path": "/api/v1/quickbooks/oauth/callback",
    "displayName": "Handle QuickBooks OAuth callback payload",
    "summary": "Handle QuickBooks OAuth callback payload",
    "description": "Consumes OAuth callback payload with code/state/realm and persists connection tokens. Both /api/v1/integrations/quickbooks/* and /api/v1/quickbooks/* map to the same ApiQuickBooksController method (handleOAuthCallback). This family is a path alias that binds controller methods directly (for example `export const GET = controller.getAccounts()`) and relies on controller-level error handling.",
    "tags": [
      "QuickBooks v1"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "code": {
          "type": "string",
          "minLength": 1
        },
        "state": {
          "type": "string",
          "minLength": 1
        },
        "realmId": {
          "type": "string",
          "minLength": 1
        },
        "error": {
          "type": "string"
        },
        "error_description": {
          "type": "string"
        }
      },
      "required": [
        "code",
        "state",
        "realmId"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "delete-_api_v1_quickbooks_oauth_disconnect",
    "method": "delete",
    "path": "/api/v1/quickbooks/oauth/disconnect",
    "displayName": "Disconnect QuickBooks OAuth",
    "summary": "Disconnect QuickBooks OAuth",
    "description": "Revokes/disconnects QuickBooks tenant credentials and returns 204. Both /api/v1/integrations/quickbooks/* and /api/v1/quickbooks/* map to the same ApiQuickBooksController method (disconnectOAuth). This family is a path alias that binds controller methods directly (for example `export const GET = controller.getAccounts()`) and relies on controller-level error handling.",
    "tags": [
      "QuickBooks v1"
    ],
    "approvalRequired": false,
    "parameters": []
  },
  {
    "id": "post-_api_v1_quickbooks_oauth_initiate",
    "method": "post",
    "path": "/api/v1/quickbooks/oauth/initiate",
    "displayName": "Initiate QuickBooks OAuth flow",
    "summary": "Initiate QuickBooks OAuth flow",
    "description": "Generates authorization URL for QuickBooks OAuth with tenant-scoped state. Both /api/v1/integrations/quickbooks/* and /api/v1/quickbooks/* map to the same ApiQuickBooksController method (initiateOAuth). This family is a path alias that binds controller methods directly (for example `export const GET = controller.getAccounts()`) and relies on controller-level error handling.",
    "tags": [
      "QuickBooks v1"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "state": {
          "type": "string",
          "minLength": 1
        },
        "redirect_uri": {
          "type": "string",
          "format": "uri"
        },
        "scope": {
          "type": "string"
        }
      },
      "required": [
        "state"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_quickbooks_paymentmethods",
    "method": "get",
    "path": "/api/v1/quickbooks/payment-methods",
    "displayName": "List QuickBooks payment methods",
    "summary": "List QuickBooks payment methods",
    "description": "Returns payment methods; current implementation returns sample stub rows. Both /api/v1/integrations/quickbooks/* and /api/v1/quickbooks/* map to the same ApiQuickBooksController method (getPaymentMethods). This family is a path alias that binds controller methods directly (for example `export const GET = controller.getAccounts()`) and relies on controller-level error handling.",
    "tags": [
      "QuickBooks v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "page",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "limit",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "active",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ]
        }
      },
      {
        "name": "search",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "entity_type",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "force_refresh",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ]
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "post-_api_v1_quickbooks_payments_sync",
    "method": "post",
    "path": "/api/v1/quickbooks/payments/sync",
    "displayName": "Sync payments",
    "summary": "Sync payments",
    "description": "Synchronizes payment records between Alga and QuickBooks. Both /api/v1/integrations/quickbooks/* and /api/v1/quickbooks/* map to the same ApiQuickBooksController method (syncPayments). This family is a path alias that binds controller methods directly (for example `export const GET = controller.getAccounts()`) and relies on controller-level error handling.",
    "tags": [
      "QuickBooks v1"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "payment_id": {
          "type": "string",
          "format": "uuid"
        },
        "invoice_id": {
          "type": "string",
          "format": "uuid"
        },
        "date_range": {
          "type": "object",
          "properties": {
            "start_date": {
              "type": "string"
            },
            "end_date": {
              "type": "string"
            }
          },
          "required": [
            "start_date",
            "end_date"
          ]
        },
        "sync_type": {
          "type": "string",
          "enum": [
            "create",
            "update",
            "bidirectional"
          ]
        },
        "include_unapplied": {
          "type": "boolean"
        }
      }
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "post-_api_v1_quickbooks_sync_bulk",
    "method": "post",
    "path": "/api/v1/quickbooks/sync/bulk",
    "displayName": "Run bulk QuickBooks sync",
    "summary": "Run bulk QuickBooks sync",
    "description": "Starts multi-operation bulk sync and returns accepted job payload. Both /api/v1/integrations/quickbooks/* and /api/v1/quickbooks/* map to the same ApiQuickBooksController method (bulkSync). This family is a path alias that binds controller methods directly (for example `export const GET = controller.getAccounts()`) and relies on controller-level error handling.",
    "tags": [
      "QuickBooks v1"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "operations": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "operation_type": {
                "type": "string",
                "enum": [
                  "customer_sync",
                  "invoice_export",
                  "invoice_import",
                  "payment_sync",
                  "item_sync",
                  "tax_sync",
                  "full_sync",
                  "test_connection"
                ]
              },
              "entity_ids": {
                "type": "array",
                "items": {
                  "type": "string",
                  "format": "uuid"
                }
              },
              "qbo_entity_ids": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "date_range": {
                "type": "object",
                "properties": {
                  "start_date": {
                    "type": "string"
                  },
                  "end_date": {
                    "type": "string"
                  }
                },
                "required": [
                  "start_date",
                  "end_date"
                ]
              },
              "parameters": {
                "type": "object",
                "additionalProperties": {}
              }
            },
            "required": [
              "operation_type"
            ]
          },
          "minItems": 1,
          "maxItems": 10
        },
        "execution_mode": {
          "type": "string",
          "enum": [
            "sequential",
            "parallel"
          ]
        },
        "stop_on_error": {
          "type": "boolean"
        },
        "notification_email": {
          "type": "string",
          "format": "email"
        }
      },
      "required": [
        "operations"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "post-_api_v1_quickbooks_sync_full",
    "method": "post",
    "path": "/api/v1/quickbooks/sync/full",
    "displayName": "Run full QuickBooks sync",
    "summary": "Run full QuickBooks sync",
    "description": "Starts full synchronization workflow and returns accepted job payload. Both /api/v1/integrations/quickbooks/* and /api/v1/quickbooks/* map to the same ApiQuickBooksController method (fullSync). This family is a path alias that binds controller methods directly (for example `export const GET = controller.getAccounts()`) and relies on controller-level error handling.",
    "tags": [
      "QuickBooks v1"
    ],
    "approvalRequired": false,
    "parameters": [],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_quickbooks_sync_history",
    "method": "get",
    "path": "/api/v1/quickbooks/sync/history",
    "displayName": "List sync history",
    "summary": "List sync history",
    "description": "Returns paginated synchronization history with status/type/date filters. Both /api/v1/integrations/quickbooks/* and /api/v1/quickbooks/* map to the same ApiQuickBooksController method (getSyncHistory). This family is a path alias that binds controller methods directly (for example `export const GET = controller.getAccounts()`) and relies on controller-level error handling.",
    "tags": [
      "QuickBooks v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "page",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "limit",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "status",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "pending",
            "in_progress",
            "completed",
            "failed",
            "cancelled",
            "partial"
          ]
        }
      },
      {
        "name": "operation_type",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "customer_sync",
            "invoice_export",
            "invoice_import",
            "payment_sync",
            "item_sync",
            "tax_sync",
            "full_sync",
            "test_connection"
          ]
        }
      },
      {
        "name": "date_from",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "date_to",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "type": "array",
          "items": {
            "type": "object",
            "additionalProperties": {}
          }
        },
        "pagination": {
          "type": "object",
          "properties": {
            "page": {
              "type": "integer"
            },
            "limit": {
              "type": "integer"
            },
            "total": {
              "type": "integer"
            },
            "totalPages": {
              "type": "integer"
            },
            "hasNext": {
              "type": "boolean"
            },
            "hasPrev": {
              "type": "boolean"
            }
          },
          "required": [
            "page",
            "limit",
            "total",
            "totalPages",
            "hasNext",
            "hasPrev"
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data",
        "pagination"
      ]
    }
  },
  {
    "id": "get-_api_v1_quickbooks_sync_status",
    "method": "get",
    "path": "/api/v1/quickbooks/sync/status",
    "displayName": "Get current sync status",
    "summary": "Get current sync status",
    "description": "Returns current sync status summary (currently stub status payload). Both /api/v1/integrations/quickbooks/* and /api/v1/quickbooks/* map to the same ApiQuickBooksController method (getSyncStatus). This family is a path alias that binds controller methods directly (for example `export const GET = controller.getAccounts()`) and relies on controller-level error handling.",
    "tags": [
      "QuickBooks v1"
    ],
    "approvalRequired": false,
    "parameters": [],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_quickbooks_sync_status_sync_id",
    "method": "get",
    "path": "/api/v1/quickbooks/sync/status/{sync_id}",
    "displayName": "Get sync status by id",
    "summary": "Get sync status by id",
    "description": "Returns detailed status for one sync operation id. Both /api/v1/integrations/quickbooks/* and /api/v1/quickbooks/* map to the same ApiQuickBooksController method (getSyncStatusById). This family is a path alias that binds controller methods directly (for example `export const GET = controller.getAccounts()`) and relies on controller-level error handling.",
    "tags": [
      "QuickBooks v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "sync_id",
        "in": "path",
        "required": true,
        "description": "Sync operation identifier extracted from path segment sync_id.",
        "schema": {
          "type": "string",
          "description": "Sync operation identifier extracted from path segment sync_id."
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "post-_api_v1_quickbooks_sync_sync_id_cancel",
    "method": "post",
    "path": "/api/v1/quickbooks/sync/{sync_id}/cancel",
    "displayName": "Cancel sync operation",
    "summary": "Cancel sync operation",
    "description": "Cancel endpoint currently returns 204 stub response (service TODO). Both /api/v1/integrations/quickbooks/* and /api/v1/quickbooks/* map to the same ApiQuickBooksController method (cancelSync). This family is a path alias that binds controller methods directly (for example `export const GET = controller.getAccounts()`) and relies on controller-level error handling.",
    "tags": [
      "QuickBooks v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "sync_id",
        "in": "path",
        "required": true,
        "description": "Sync operation identifier extracted from path segment sync_id.",
        "schema": {
          "type": "string",
          "description": "Sync operation identifier extracted from path segment sync_id."
        }
      }
    ]
  },
  {
    "id": "post-_api_v1_quickbooks_sync_sync_id_retry",
    "method": "post",
    "path": "/api/v1/quickbooks/sync/{sync_id}/retry",
    "displayName": "Retry sync operation",
    "summary": "Retry sync operation",
    "description": "Retries a failed sync and returns synthetic new retry sync id. Both /api/v1/integrations/quickbooks/* and /api/v1/quickbooks/* map to the same ApiQuickBooksController method (retrySync). This family is a path alias that binds controller methods directly (for example `export const GET = controller.getAccounts()`) and relies on controller-level error handling.",
    "tags": [
      "QuickBooks v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "sync_id",
        "in": "path",
        "required": true,
        "description": "Sync operation identifier extracted from path segment sync_id.",
        "schema": {
          "type": "string",
          "description": "Sync operation identifier extracted from path segment sync_id."
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_quickbooks_taxcodes",
    "method": "get",
    "path": "/api/v1/quickbooks/tax-codes",
    "displayName": "List QuickBooks tax codes",
    "summary": "List QuickBooks tax codes",
    "description": "Returns tax code list; current implementation is a stub empty array. Both /api/v1/integrations/quickbooks/* and /api/v1/quickbooks/* map to the same ApiQuickBooksController method (getTaxCodes). This family is a path alias that binds controller methods directly (for example `export const GET = controller.getAccounts()`) and relies on controller-level error handling.",
    "tags": [
      "QuickBooks v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "page",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "limit",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "active",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ]
        }
      },
      {
        "name": "search",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "entity_type",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "force_refresh",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ]
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_quickbooks_taxcodes_mappings",
    "method": "get",
    "path": "/api/v1/quickbooks/tax-codes/mappings",
    "displayName": "List tax mappings",
    "summary": "List tax mappings",
    "description": "Returns paginated tax mapping configuration; current implementation is stubbed. Both /api/v1/integrations/quickbooks/* and /api/v1/quickbooks/* map to the same ApiQuickBooksController method (getTaxMappings). This family is a path alias that binds controller methods directly (for example `export const GET = controller.getAccounts()`) and relies on controller-level error handling.",
    "tags": [
      "QuickBooks v1"
    ],
    "approvalRequired": false,
    "parameters": [],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "type": "array",
          "items": {
            "type": "object",
            "additionalProperties": {}
          }
        },
        "pagination": {
          "type": "object",
          "properties": {
            "page": {
              "type": "integer"
            },
            "limit": {
              "type": "integer"
            },
            "total": {
              "type": "integer"
            },
            "totalPages": {
              "type": "integer"
            },
            "hasNext": {
              "type": "boolean"
            },
            "hasPrev": {
              "type": "boolean"
            }
          },
          "required": [
            "page",
            "limit",
            "total",
            "totalPages",
            "hasNext",
            "hasPrev"
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data",
        "pagination"
      ]
    }
  },
  {
    "id": "put-_api_v1_quickbooks_taxcodes_mappings",
    "method": "put",
    "path": "/api/v1/quickbooks/tax-codes/mappings",
    "displayName": "Configure tax mappings",
    "summary": "Configure tax mappings",
    "description": "Stores/updates mapping from Alga tax regions to QuickBooks tax codes. Both /api/v1/integrations/quickbooks/* and /api/v1/quickbooks/* map to the same ApiQuickBooksController method (configureTaxMappings). This family is a path alias that binds controller methods directly (for example `export const GET = controller.getAccounts()`) and relies on controller-level error handling.",
    "tags": [
      "QuickBooks v1"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "mappings": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "alga_tax_region": {
                "type": "string"
              },
              "qbo_tax_code_id": {
                "type": "string"
              },
              "is_default": {
                "type": "boolean"
              }
            },
            "required": [
              "alga_tax_region",
              "qbo_tax_code_id"
            ]
          },
          "minItems": 1
        },
        "replace_existing": {
          "type": "boolean"
        }
      },
      "required": [
        "mappings"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_quickbooks_terms",
    "method": "get",
    "path": "/api/v1/quickbooks/terms",
    "displayName": "List QuickBooks terms",
    "summary": "List QuickBooks terms",
    "description": "Returns payment terms catalog; current implementation returns sample stub rows. Both /api/v1/integrations/quickbooks/* and /api/v1/quickbooks/* map to the same ApiQuickBooksController method (getTerms). This family is a path alias that binds controller methods directly (for example `export const GET = controller.getAccounts()`) and relies on controller-level error handling.",
    "tags": [
      "QuickBooks v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "page",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "limit",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "active",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ]
        }
      },
      {
        "name": "search",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "entity_type",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "force_refresh",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ]
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_boards",
    "method": "get",
    "path": "/api/v1/boards",
    "displayName": "List Boards",
    "summary": "Fetch ticket boards",
    "description": "Returns paginated board records for the current tenant. Use this to discover valid board_id values before creating tickets or statuses. Each board has its own set of statuses, categories, and priorities.",
    "tags": [
      "Boards"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "search",
        "in": "query",
        "required": false,
        "description": "Case-insensitive search on board name or description.",
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "include_inactive",
        "in": "query",
        "required": false,
        "description": "When true, include inactive boards (excluded by default).",
        "schema": {
          "type": "boolean"
        }
      },
      {
        "name": "limit",
        "in": "query",
        "required": false,
        "description": "Number of records per page (default 25, max 100).",
        "schema": {
          "type": "integer",
          "minimum": 1,
          "maximum": 100
        }
      },
      {
        "name": "page",
        "in": "query",
        "required": false,
        "description": "Pagination page number starting at 1.",
        "schema": {
          "type": "integer",
          "minimum": 1
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "type": "array",
          "items": {
            "$ref": "#/components/schemas/BoardApiResponse"
          }
        }
      },
      "required": [
        "data"
      ]
    },
    "examples": [
      {
        "name": "List active boards",
        "request": {
          "query": {
            "limit": 10
          }
        },
        "notes": "Use the board_id from the response when creating tickets or querying statuses. The first active board is a safe default if the user does not specify a board."
      }
    ]
  },
  {
    "id": "post-_api_v1_boards",
    "method": "post",
    "path": "/api/v1/boards",
    "displayName": "Create Board",
    "summary": "Create a new ticket board",
    "description": "Creates a new board. After creating a board, create at least one status for it via POST /api/v1/statuses so tickets can be assigned to the board.",
    "tags": [
      "Boards"
    ],
    "approvalRequired": true,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "board_name": {
          "type": "string",
          "description": "Board display name."
        },
        "description": {
          "type": "string",
          "description": "Optional board description."
        },
        "is_default": {
          "type": "boolean",
          "description": "Whether this is the default board."
        },
        "is_inactive": {
          "type": "boolean",
          "description": "Whether the board is inactive."
        },
        "category_type": {
          "type": "string",
          "enum": [
            "custom",
            "itil"
          ],
          "description": "Category classification type."
        },
        "priority_type": {
          "type": "string",
          "enum": [
            "custom",
            "itil"
          ],
          "description": "Priority classification type."
        }
      },
      "required": [
        "board_name"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "$ref": "#/components/schemas/BoardApiResponse"
        }
      },
      "required": [
        "data"
      ]
    },
    "examples": [
      {
        "name": "Create a new board",
        "request": {
          "body": {
            "board_name": "Support",
            "description": "General support board"
          }
        },
        "notes": "After creating, add statuses via POST /api/v1/statuses with the new board_id and status_type 'ticket'."
      }
    ]
  },
  {
    "id": "get-_api_v1_boards_id",
    "method": "get",
    "path": "/api/v1/boards/{id}",
    "displayName": "Get Board",
    "summary": "Get board by ID",
    "description": "Returns a single board record by its UUID.",
    "tags": [
      "Boards"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Board identifier.",
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "$ref": "#/components/schemas/BoardApiResponse"
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "put-_api_v1_boards_id",
    "method": "put",
    "path": "/api/v1/boards/{id}",
    "displayName": "Update Board",
    "summary": "Update a board",
    "description": "Updates an existing board. All fields are optional — only send the fields you want to change.",
    "tags": [
      "Boards"
    ],
    "approvalRequired": true,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Board identifier.",
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "board_name": {
          "type": "string",
          "minLength": 1,
          "maxLength": 255
        },
        "description": {
          "type": "string",
          "maxLength": 1000
        },
        "is_default": {
          "type": "boolean"
        },
        "is_inactive": {
          "type": "boolean"
        },
        "category_type": {
          "type": "string",
          "enum": [
            "custom",
            "itil"
          ]
        },
        "priority_type": {
          "type": "string",
          "enum": [
            "custom",
            "itil"
          ]
        },
        "default_assigned_to": {
          "type": [
            "string",
            "null"
          ],
          "format": "uuid"
        },
        "display_itil_impact": {
          "type": "boolean"
        },
        "display_itil_urgency": {
          "type": "boolean"
        },
        "enable_live_ticket_timer": {
          "type": "boolean"
        }
      },
      "description": "Payload for updating a board. All fields are optional."
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "$ref": "#/components/schemas/BoardApiResponse"
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "delete-_api_v1_boards_id",
    "method": "delete",
    "path": "/api/v1/boards/{id}",
    "displayName": "Delete board",
    "summary": "Delete board",
    "description": "Deletes a board by its UUID. This will fail if the board has associated tickets.",
    "tags": [
      "Boards"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Board UUID.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Board UUID."
        }
      }
    ]
  },
  {
    "id": "get-_api_v1_statuses",
    "method": "get",
    "path": "/api/v1/statuses",
    "displayName": "List Statuses",
    "summary": "Fetch statuses",
    "description": "Returns paginated status records. For ticket statuses, always filter by board_id to get statuses that belong to a specific board. Use this to resolve a valid status_id before creating or updating tickets.",
    "tags": [
      "Statuses"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "type",
        "in": "query",
        "required": false,
        "description": "Filter by status type: ticket, project, project_task, or interaction.",
        "schema": {
          "type": "string",
          "enum": [
            "ticket",
            "project",
            "project_task",
            "interaction"
          ]
        }
      },
      {
        "name": "board_id",
        "in": "query",
        "required": false,
        "description": "Required when type=ticket. Filter statuses belonging to a specific board.",
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      },
      {
        "name": "search",
        "in": "query",
        "required": false,
        "description": "Case-insensitive search on status name.",
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "limit",
        "in": "query",
        "required": false,
        "description": "Number of records per page (default 25, max 100).",
        "schema": {
          "type": "integer",
          "minimum": 1,
          "maximum": 100
        }
      },
      {
        "name": "page",
        "in": "query",
        "required": false,
        "description": "Pagination page number starting at 1.",
        "schema": {
          "type": "integer",
          "minimum": 1
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "type": "array",
          "items": {
            "$ref": "#/components/schemas/StatusApiResponse"
          }
        }
      },
      "required": [
        "data"
      ]
    },
    "examples": [
      {
        "name": "List ticket statuses for a board",
        "request": {
          "query": {
            "type": "ticket",
            "board_id": "11111111-1111-1111-1111-111111111111",
            "limit": 25
          }
        },
        "notes": "Always pair type=ticket with board_id. Use the status_id from results when creating tickets — the status_id must belong to the same board_id used on the ticket."
      }
    ]
  },
  {
    "id": "post-_api_v1_statuses",
    "method": "post",
    "path": "/api/v1/statuses",
    "displayName": "Create Status",
    "summary": "Create a new status",
    "description": "Creates a new status. For ticket statuses, board_id is required. The status_type must be one of: ticket, project, project_task, interaction.",
    "tags": [
      "Statuses"
    ],
    "approvalRequired": true,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "name": {
          "type": "string",
          "description": "Status display name."
        },
        "status_type": {
          "type": "string",
          "enum": [
            "ticket",
            "project",
            "project_task",
            "interaction"
          ],
          "description": "Type of entity this status applies to."
        },
        "board_id": {
          "type": "string",
          "format": "uuid",
          "description": "Required for ticket statuses. The board this status belongs to."
        },
        "is_closed": {
          "type": "boolean",
          "description": "Whether this status represents a closed state."
        },
        "is_default": {
          "type": "boolean",
          "description": "Whether this is the default status for the board."
        },
        "order_number": {
          "type": "integer",
          "description": "Display order position."
        },
        "color": {
          "type": "string",
          "description": "Hex color code (e.g. #3B82F6)."
        },
        "icon": {
          "type": "string",
          "description": "Lucide icon name (e.g. Clipboard, PlayCircle)."
        }
      },
      "required": [
        "name",
        "status_type"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "$ref": "#/components/schemas/StatusApiResponse"
        }
      },
      "required": [
        "data"
      ]
    },
    "examples": [
      {
        "name": "Create a ticket status for a board",
        "request": {
          "body": {
            "name": "In Progress",
            "status_type": "ticket",
            "board_id": "11111111-1111-1111-1111-111111111111",
            "is_closed": false,
            "color": "#3B82F6"
          }
        },
        "notes": "Use GET /api/v1/boards first to resolve the board_id. The board_id is required for ticket statuses."
      }
    ]
  },
  {
    "id": "get-_api_v1_statuses_id",
    "method": "get",
    "path": "/api/v1/statuses/{id}",
    "displayName": "Get status by ID",
    "summary": "Get status by ID",
    "description": "Returns a single status by its UUID.",
    "tags": [
      "Statuses"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Status UUID.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Status UUID."
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "$ref": "#/components/schemas/StatusApiResponse"
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "put-_api_v1_statuses_id",
    "method": "put",
    "path": "/api/v1/statuses/{id}",
    "displayName": "Update Status",
    "summary": "Update a status",
    "description": "Updates an existing status. All fields are optional — only send the fields you want to change. Cannot change status_type or board_id after creation.",
    "tags": [
      "Statuses"
    ],
    "approvalRequired": true,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Status identifier.",
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "name": {
          "type": "string",
          "minLength": 1,
          "maxLength": 255
        },
        "is_closed": {
          "type": "boolean"
        },
        "is_default": {
          "type": "boolean"
        },
        "order_number": {
          "type": "integer",
          "minimum": 0
        },
        "color": {
          "type": "string",
          "pattern": "^#[0-9A-Fa-f]{6}$"
        },
        "icon": {
          "type": "string",
          "maxLength": 50
        }
      },
      "description": "Payload for updating a status. All fields are optional."
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "$ref": "#/components/schemas/StatusApiResponse"
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "delete-_api_v1_statuses_id",
    "method": "delete",
    "path": "/api/v1/statuses/{id}",
    "displayName": "Delete status",
    "summary": "Delete status",
    "description": "Deletes a status by its UUID. Cannot delete the last default status for a board.",
    "tags": [
      "Statuses"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Status UUID.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Status UUID."
        }
      }
    ]
  },
  {
    "id": "get-_api_v1_search",
    "method": "get",
    "path": "/api/v1/search",
    "displayName": "Unified full-text search",
    "summary": "Unified full-text search",
    "description": "Full-text search across all indexed business records (tickets, clients, contacts, projects, assets, invoices, contracts, documents, knowledge-base articles, and more) backed by the shared app_search_index. Results are tenant-scoped and filtered by the API key user's permissions: a coarse per-type permission gate plus a per-row access-control check, so only records the user could see in-app are returned. No dedicated search permission is required — any valid API key may call this endpoint. Client-portal API keys are automatically scoped to their own client.",
    "tags": [
      "Search"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "query",
        "in": "query",
        "required": true,
        "description": "Full-text query. A concise expression of likely record words, identifiers, names, or quoted phrases — not a full sentence. Supports OR for alternatives (e.g. \"laptop OR workstation\").",
        "schema": {
          "type": "string",
          "minLength": 1,
          "maxLength": 200,
          "description": "Full-text query. A concise expression of likely record words, identifiers, names, or quoted phrases — not a full sentence. Supports OR for alternatives (e.g. \"laptop OR workstation\")."
        }
      },
      {
        "name": "types",
        "in": "query",
        "required": false,
        "description": "Comma-separated list of object types to restrict the search (e.g. \"ticket,project\"). Omit to search every type the API key's user is permitted to read. Allowed values: client, contact, user, ticket, ticket_comment, project, project_phase, project_task, project_task_comment, asset, invoice, invoice_item, invoice_annotation, contract, client_contract, document, kb_article, service_catalog, service_request_submission, service_request_definition, workflow_task, interaction, schedule_entry, time_entry, board, category, tag, status.",
        "schema": {
          "type": "string",
          "description": "Comma-separated list of object types to restrict the search (e.g. \"ticket,project\"). Omit to search every type the API key's user is permitted to read. Allowed values: client, contact, user, ticket, ticket_comment, project, project_phase, project_task, project_task_comment, asset, invoice, invoice_item, invoice_annotation, contract, client_contract, document, kb_article, service_catalog, service_request_submission, service_request_definition, workflow_task, interaction, schedule_entry, time_entry, board, category, tag, status."
        }
      },
      {
        "name": "limit",
        "in": "query",
        "required": false,
        "description": "Maximum number of results to return. Defaults to 30; capped at 100.",
        "schema": {
          "type": "integer",
          "minimum": 1,
          "maximum": 100,
          "description": "Maximum number of results to return. Defaults to 30; capped at 100."
        }
      },
      {
        "name": "cursor",
        "in": "query",
        "required": false,
        "description": "Opaque pagination cursor copied from a prior response's nextCursor.",
        "schema": {
          "type": "string",
          "description": "Opaque pagination cursor copied from a prior response's nextCursor."
        }
      },
      {
        "name": "sort",
        "in": "query",
        "required": false,
        "description": "Result ordering. \"relevance\" (default) ranks by full-text score; \"recent\" orders by last update.",
        "schema": {
          "type": "string",
          "enum": [
            "relevance",
            "recent"
          ],
          "description": "Result ordering. \"relevance\" (default) ranks by full-text score; \"recent\" orders by last update."
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "allOf": [
            {
              "$ref": "#/components/schemas/SearchResultData"
            },
            {
              "description": "Search payload returned by createSuccessResponse."
            }
          ]
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_categories_service",
    "method": "get",
    "path": "/api/v1/categories/service",
    "displayName": "List service categories",
    "summary": "List service categories",
    "description": "Returns a paginated list of service categories within the current tenant.",
    "tags": [
      "Service Categories"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "search",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "is_active",
        "in": "query",
        "required": false,
        "schema": {
          "type": "boolean"
        }
      },
      {
        "name": "page",
        "in": "query",
        "required": false,
        "schema": {
          "type": "integer",
          "minimum": 1
        }
      },
      {
        "name": "limit",
        "in": "query",
        "required": false,
        "schema": {
          "type": "integer",
          "minimum": 1,
          "maximum": 100
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "type": "array",
          "items": {
            "$ref": "#/components/schemas/ServiceCategory"
          }
        },
        "pagination": {
          "type": "object",
          "properties": {
            "page": {
              "type": "integer"
            },
            "limit": {
              "type": "integer"
            },
            "total": {
              "type": "integer"
            },
            "totalPages": {
              "type": "integer"
            },
            "hasNext": {
              "type": "boolean"
            },
            "hasPrev": {
              "type": "boolean"
            }
          },
          "required": [
            "page",
            "limit",
            "total",
            "totalPages",
            "hasNext",
            "hasPrev"
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data",
        "pagination"
      ]
    },
    "playbooks": [
      "service-categories/list-basic"
    ],
    "examples": [
      {
        "name": "List active categories",
        "request": {
          "query": {
            "is_active": true
          }
        }
      }
    ]
  },
  {
    "id": "post-_api_v1_categories_service",
    "method": "post",
    "path": "/api/v1/categories/service",
    "displayName": "Create service category",
    "summary": "Create service category",
    "description": "Creates a new service category. Do not call this while creating tickets unless the user explicitly asks to manage categories.",
    "tags": [
      "Service Categories"
    ],
    "approvalRequired": true,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "category_name": {
          "type": "string",
          "minLength": 1,
          "maxLength": 255
        },
        "description": {
          "type": "string",
          "maxLength": 1000
        },
        "is_active": {
          "type": "boolean"
        }
      },
      "required": [
        "category_name"
      ],
      "description": "Payload for creating a service category."
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "$ref": "#/components/schemas/ServiceCategory"
        }
      },
      "required": [
        "data"
      ]
    },
    "playbooks": [
      "service-categories/create-basic"
    ],
    "examples": [
      {
        "name": "Create a new service category",
        "request": {
          "body": {
            "category_name": "Remote Support",
            "description": "Standard remote troubleshooting",
            "is_active": true
          }
        }
      }
    ]
  },
  {
    "id": "get-_api_v1_categories_service_id",
    "method": "get",
    "path": "/api/v1/categories/service/{id}",
    "displayName": "Get service category",
    "summary": "Get service category",
    "description": "Returns one service category by category_id for the authenticated tenant. Requires billing_settings:read permission.",
    "tags": [
      "Service Categories"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Category UUID from service_categories.category_id or categories.category_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Category UUID from service_categories.category_id or categories.category_id."
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "$ref": "#/components/schemas/ServiceCategory"
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "put-_api_v1_categories_service_id",
    "method": "put",
    "path": "/api/v1/categories/service/{id}",
    "displayName": "Update service category",
    "summary": "Update service category",
    "description": "Updates one service category by category_id. Requires billing_settings:update permission.",
    "tags": [
      "Service Categories"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Category UUID from service_categories.category_id or categories.category_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Category UUID from service_categories.category_id or categories.category_id."
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "category_name": {
          "type": "string",
          "minLength": 1,
          "maxLength": 255
        },
        "description": {
          "type": "string",
          "maxLength": 1000
        },
        "is_active": {
          "type": "boolean"
        }
      },
      "required": [
        "category_name"
      ],
      "description": "Payload for creating a service category."
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "$ref": "#/components/schemas/ServiceCategory"
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "delete-_api_v1_categories_service_id",
    "method": "delete",
    "path": "/api/v1/categories/service/{id}",
    "displayName": "Delete service category",
    "summary": "Delete service category",
    "description": "Deletes one service category by category_id. Requires billing_settings:delete permission.",
    "tags": [
      "Service Categories"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Category UUID from service_categories.category_id or categories.category_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Category UUID from service_categories.category_id or categories.category_id."
        }
      }
    ]
  },
  {
    "id": "get-_api_v1_categories_ticket",
    "method": "get",
    "path": "/api/v1/categories/ticket",
    "displayName": "List Ticket Categories",
    "summary": "Fetch ticket categories",
    "description": "Provides the category catalog used when assigning category_id or subcategory_id to a ticket.",
    "tags": [
      "Ticket Categories"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "board_id",
        "in": "query",
        "required": false,
        "description": "Filter categories that belong to a specific ticket board.",
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      },
      {
        "name": "is_active",
        "in": "query",
        "required": false,
        "description": "Toggle to include inactive categories.",
        "schema": {
          "type": "boolean"
        }
      },
      {
        "name": "limit",
        "in": "query",
        "required": false,
        "description": "Number of categories per page (default 25, max 100).",
        "schema": {
          "type": "integer",
          "minimum": 1,
          "maximum": 100
        }
      },
      {
        "name": "page",
        "in": "query",
        "required": false,
        "description": "Pagination page number.",
        "schema": {
          "type": "integer",
          "minimum": 1
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "type": "array",
          "items": {
            "$ref": "#/components/schemas/TicketCategory"
          }
        },
        "pagination": {
          "type": "object",
          "properties": {
            "page": {
              "type": "integer"
            },
            "limit": {
              "type": "integer"
            },
            "total": {
              "type": "integer"
            },
            "totalPages": {
              "type": "integer"
            },
            "hasNext": {
              "type": "boolean"
            },
            "hasPrev": {
              "type": "boolean"
            }
          },
          "required": [
            "page",
            "limit",
            "total",
            "totalPages",
            "hasNext",
            "hasPrev"
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data",
        "pagination"
      ]
    },
    "examples": [
      {
        "name": "Categories for a board",
        "request": {
          "query": {
            "board_id": "11111111-1111-1111-1111-111111111111",
            "limit": 10
          }
        },
        "notes": "Pair this with the board_id you plan to use on the ticket so category selections stay consistent."
      }
    ]
  },
  {
    "id": "post-_api_v1_categories_ticket",
    "method": "post",
    "path": "/api/v1/categories/ticket",
    "displayName": "Create ticket category",
    "summary": "Create ticket category",
    "description": "Creates a ticket category row for one board. Requires ticket_settings:create permission.",
    "tags": [
      "Ticket Categories"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "category_name": {
          "type": "string",
          "minLength": 1,
          "maxLength": 255
        },
        "board_id": {
          "type": "string",
          "format": "uuid"
        },
        "parent_category": {
          "type": "string",
          "format": "uuid"
        }
      },
      "required": [
        "category_name",
        "board_id"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "$ref": "#/components/schemas/TicketCategory"
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_categories_ticket_id",
    "method": "get",
    "path": "/api/v1/categories/ticket/{id}",
    "displayName": "Get ticket category",
    "summary": "Get ticket category",
    "description": "Returns one ticket category by category_id. Requires ticket_settings:read permission.",
    "tags": [
      "Ticket Categories"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Category UUID from service_categories.category_id or categories.category_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Category UUID from service_categories.category_id or categories.category_id."
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "$ref": "#/components/schemas/TicketCategory"
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "put-_api_v1_categories_ticket_id",
    "method": "put",
    "path": "/api/v1/categories/ticket/{id}",
    "displayName": "Update ticket category",
    "summary": "Update ticket category",
    "description": "Updates one ticket category by category_id. Requires ticket_settings:update permission.",
    "tags": [
      "Ticket Categories"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Category UUID from service_categories.category_id or categories.category_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Category UUID from service_categories.category_id or categories.category_id."
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "category_name": {
          "type": "string",
          "minLength": 1,
          "maxLength": 255
        },
        "board_id": {
          "type": "string",
          "format": "uuid"
        },
        "parent_category": {
          "type": "string",
          "format": "uuid"
        }
      }
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "$ref": "#/components/schemas/TicketCategory"
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "delete-_api_v1_categories_ticket_id",
    "method": "delete",
    "path": "/api/v1/categories/ticket/{id}",
    "displayName": "Delete ticket category",
    "summary": "Delete ticket category",
    "description": "Deletes one ticket category by category_id. Requires ticket_settings:delete permission.",
    "tags": [
      "Ticket Categories"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Category UUID from service_categories.category_id or categories.category_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Category UUID from service_categories.category_id or categories.category_id."
        }
      }
    ]
  },
  {
    "id": "get-_api_v1_categories_ticket_tree",
    "method": "get",
    "path": "/api/v1/categories/ticket/tree",
    "displayName": "Get ticket category tree (implicit board id)",
    "summary": "Get ticket category tree (implicit board id)",
    "description": "Calls getCategoryTree and derives boardId from the last URL path segment. For this path without a board parameter, the current implementation passes literal `tree` as boardId to CategoryService.getCategoryTree.",
    "tags": [
      "Ticket Categories"
    ],
    "approvalRequired": false,
    "parameters": [],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "type": "object",
          "properties": {
            "tree": {
              "type": "array",
              "items": {},
              "description": "Hierarchical category tree nodes from CategoryService.getCategoryTree."
            },
            "total_categories": {
              "type": "integer",
              "minimum": 0
            }
          },
          "required": [
            "tree",
            "total_categories"
          ]
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_categories_ticket_tree_boardid",
    "method": "get",
    "path": "/api/v1/categories/ticket/tree/{boardId}",
    "displayName": "Get ticket category tree by board",
    "summary": "Get ticket category tree by board",
    "description": "Returns hierarchical ticket categories for a board route. Current controller still derives board id from the last path segment instead of reading req.params directly; this works for this route because the last segment is boardId.",
    "tags": [
      "Ticket Categories"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "boardId",
        "in": "path",
        "required": true,
        "description": "Board UUID used by ticket category tree queries.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Board UUID used by ticket category tree queries."
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "type": "object",
          "properties": {
            "tree": {
              "type": "array",
              "items": {},
              "description": "Hierarchical category tree nodes from CategoryService.getCategoryTree."
            },
            "total_categories": {
              "type": "integer",
              "minimum": 0
            }
          },
          "required": [
            "tree",
            "total_categories"
          ]
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "post-_api_v1_categories_ticket_move",
    "method": "post",
    "path": "/api/v1/categories/ticket/move",
    "displayName": "Move ticket category in hierarchy",
    "summary": "Move ticket category in hierarchy",
    "description": "Moves a ticket category under a new parent. Requires ticket_settings:update permission.",
    "tags": [
      "Ticket Categories"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "category_id": {
          "type": "string",
          "format": "uuid"
        },
        "new_parent_id": {
          "type": [
            "string",
            "null"
          ],
          "format": "uuid"
        },
        "position": {
          "type": "integer",
          "minimum": 0
        }
      },
      "required": [
        "category_id"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "$ref": "#/components/schemas/TicketCategory"
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_categories_search",
    "method": "get",
    "path": "/api/v1/categories/search",
    "displayName": "Search categories",
    "summary": "Search categories",
    "description": "Searches categories across service/ticket types. Permission resource is chosen dynamically from category_type (defaults to ticket_settings when omitted).",
    "tags": [
      "Categories"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "search_term",
        "in": "query",
        "required": true,
        "schema": {
          "type": "string",
          "minLength": 1
        }
      },
      {
        "name": "category_type",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "service",
            "ticket"
          ]
        }
      },
      {
        "name": "board_id",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      },
      {
        "name": "include_inactive",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ]
        }
      },
      {
        "name": "limit",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "offset",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "type": "array",
          "items": {
            "type": "object",
            "additionalProperties": {}
          }
        },
        "pagination": {
          "type": "object",
          "additionalProperties": {}
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data",
        "pagination"
      ]
    }
  },
  {
    "id": "get-_api_v1_categories_analytics",
    "method": "get",
    "path": "/api/v1/categories/analytics",
    "displayName": "Get category analytics",
    "summary": "Get category analytics",
    "description": "Returns category analytics with generation timestamp. Permission resource is chosen dynamically from category_type (defaults to ticket_settings when omitted).",
    "tags": [
      "Categories"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "category_type",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "service",
            "ticket"
          ]
        }
      },
      {
        "name": "board_id",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      },
      {
        "name": "date_from",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "format": "date-time"
        }
      },
      {
        "name": "date_to",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "format": "date-time"
        }
      },
      {
        "name": "include_usage",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ]
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "type": "object",
          "properties": {
            "analytics": {
              "type": "object",
              "additionalProperties": {},
              "description": "Aggregated category analytics from CategoryService.getCategoryAnalytics."
            },
            "generated_at": {
              "type": "string",
              "format": "date-time"
            }
          },
          "required": [
            "analytics",
            "generated_at"
          ]
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "post-_api_v1_categories_bulk_delete",
    "method": "post",
    "path": "/api/v1/categories/bulk/delete",
    "displayName": "Bulk delete categories",
    "summary": "Bulk delete categories",
    "description": "Deletes multiple category ids. Permission resource is chosen dynamically from category_type; response includes success/failed counts and per-item errors.",
    "tags": [
      "Categories"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "category_ids": {
          "type": "array",
          "items": {
            "type": "string",
            "format": "uuid"
          },
          "minItems": 1,
          "maxItems": 50
        },
        "category_type": {
          "type": "string",
          "enum": [
            "service",
            "ticket"
          ]
        },
        "force": {
          "anyOf": [
            {
              "type": "string",
              "enum": [
                "true",
                "false"
              ]
            },
            {
              "type": "boolean"
            }
          ],
          "description": "Optional force flag; schema accepts both boolean and string boolean values."
        }
      },
      "required": [
        "category_ids",
        "category_type"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "type": "object",
          "properties": {
            "message": {
              "type": "string"
            },
            "success": {
              "type": "integer",
              "minimum": 0
            },
            "failed": {
              "type": "integer",
              "minimum": 0
            },
            "errors": {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          },
          "required": [
            "message",
            "success",
            "failed"
          ]
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_services",
    "method": "get",
    "path": "/api/v1/services",
    "displayName": "List services",
    "summary": "List services",
    "description": "Returns service catalog entries where item_kind is service. Use this endpoint to inspect existing service catalog records and to gather prerequisite IDs such as custom_service_type_id and category_id before creating a new service.",
    "tags": [
      "Services",
      "Service Catalog"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "page",
        "in": "query",
        "required": false,
        "schema": {
          "type": "integer",
          "minimum": 1,
          "default": 1
        }
      },
      {
        "name": "limit",
        "in": "query",
        "required": false,
        "schema": {
          "type": "integer",
          "minimum": 1,
          "maximum": 100,
          "default": 25
        }
      },
      {
        "name": "sort",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "service_name",
            "billing_method",
            "default_rate"
          ],
          "default": "service_name"
        }
      },
      {
        "name": "order",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "asc",
            "desc"
          ],
          "default": "asc"
        }
      },
      {
        "name": "search",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "item_kind",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "service",
            "product",
            "any"
          ]
        }
      },
      {
        "name": "is_active",
        "in": "query",
        "required": false,
        "schema": {
          "anyOf": [
            {
              "type": "string",
              "enum": [
                "true"
              ]
            },
            {
              "type": "string",
              "enum": [
                "false"
              ]
            }
          ]
        }
      },
      {
        "name": "billing_method",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "fixed",
            "hourly",
            "usage"
          ]
        }
      },
      {
        "name": "category_id",
        "in": "query",
        "required": false,
        "schema": {
          "anyOf": [
            {
              "type": "string",
              "format": "uuid"
            },
            {
              "type": "string",
              "enum": [
                "null"
              ]
            }
          ]
        }
      },
      {
        "name": "custom_service_type_id",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "type": "array",
          "items": {
            "$ref": "#/components/schemas/ServiceCatalogEntry"
          }
        },
        "pagination": {
          "type": "object",
          "properties": {
            "page": {
              "type": "integer"
            },
            "limit": {
              "type": "integer"
            },
            "total": {
              "type": "integer"
            },
            "totalPages": {
              "type": "integer"
            },
            "hasNext": {
              "type": "boolean"
            },
            "hasPrev": {
              "type": "boolean"
            }
          },
          "required": [
            "page",
            "limit",
            "total",
            "totalPages",
            "hasNext",
            "hasPrev"
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data",
        "pagination"
      ]
    }
  },
  {
    "id": "post-_api_v1_services",
    "method": "post",
    "path": "/api/v1/services",
    "displayName": "Create service",
    "summary": "Create service",
    "description": "Creates a new service catalog entry. Resolve custom_service_type_id with GET /api/v1/service-types and category_id with GET /api/v1/categories/service before calling this endpoint. Use this endpoint for fixed, hourly, or usage-based service offerings.",
    "tags": [
      "Services",
      "Service Catalog"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "service_name": {
          "type": "string",
          "minLength": 1,
          "maxLength": 255
        },
        "custom_service_type_id": {
          "type": "string",
          "format": "uuid"
        },
        "billing_method": {
          "type": "string",
          "enum": [
            "fixed",
            "hourly",
            "usage"
          ]
        },
        "default_rate": {
          "type": "number",
          "minimum": 0
        },
        "unit_of_measure": {
          "type": "string",
          "minLength": 1,
          "maxLength": 128
        },
        "category_id": {
          "anyOf": [
            {
              "type": "string",
              "format": "uuid"
            },
            {
              "type": "null"
            },
            {
              "type": "null"
            }
          ]
        },
        "tax_rate_id": {
          "anyOf": [
            {
              "type": "string",
              "format": "uuid"
            },
            {
              "type": "null"
            },
            {
              "type": "null"
            }
          ]
        },
        "description": {
          "anyOf": [
            {
              "type": "string",
              "maxLength": 2048
            },
            {
              "type": "null"
            },
            {
              "type": "null"
            }
          ]
        }
      },
      "required": [
        "service_name",
        "custom_service_type_id",
        "billing_method",
        "default_rate",
        "unit_of_measure"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "$ref": "#/components/schemas/ServiceCatalogEntry"
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_services_id",
    "method": "get",
    "path": "/api/v1/services/{id}",
    "displayName": "Get service",
    "summary": "Get service",
    "description": "Returns a single service catalog entry by UUID.",
    "tags": [
      "Services",
      "Service Catalog"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Service UUID.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Service UUID."
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "$ref": "#/components/schemas/ServiceCatalogEntry"
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "put-_api_v1_services_id",
    "method": "put",
    "path": "/api/v1/services/{id}",
    "displayName": "Update service",
    "summary": "Update service",
    "description": "Updates a service catalog entry by UUID.",
    "tags": [
      "Services",
      "Service Catalog"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Service UUID.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Service UUID."
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "service_name": {
          "type": "string",
          "minLength": 1,
          "maxLength": 255
        },
        "custom_service_type_id": {
          "type": "string",
          "format": "uuid"
        },
        "billing_method": {
          "type": "string",
          "enum": [
            "fixed",
            "hourly",
            "usage"
          ]
        },
        "default_rate": {
          "type": "number",
          "minimum": 0
        },
        "unit_of_measure": {
          "type": "string",
          "minLength": 1,
          "maxLength": 128
        },
        "category_id": {
          "anyOf": [
            {
              "type": "string",
              "format": "uuid"
            },
            {
              "type": "null"
            },
            {
              "type": "null"
            }
          ]
        },
        "tax_rate_id": {
          "anyOf": [
            {
              "type": "string",
              "format": "uuid"
            },
            {
              "type": "null"
            },
            {
              "type": "null"
            }
          ]
        },
        "description": {
          "anyOf": [
            {
              "type": "string",
              "maxLength": 2048
            },
            {
              "type": "null"
            },
            {
              "type": "null"
            }
          ]
        }
      }
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "$ref": "#/components/schemas/ServiceCatalogEntry"
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "delete-_api_v1_services_id",
    "method": "delete",
    "path": "/api/v1/services/{id}",
    "displayName": "Delete service",
    "summary": "Delete service",
    "description": "Deletes a service catalog entry by UUID.",
    "tags": [
      "Services",
      "Service Catalog"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Service UUID.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Service UUID."
        }
      }
    ]
  },
  {
    "id": "get-_api_v1_products",
    "method": "get",
    "path": "/api/v1/products",
    "displayName": "List products",
    "summary": "List products",
    "description": "Returns product catalog entries where item_kind is product. Use this endpoint to inspect existing product catalog records and to gather prerequisite IDs such as custom_service_type_id and category_id before creating a new product.",
    "tags": [
      "Products",
      "Service Catalog"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "page",
        "in": "query",
        "required": false,
        "schema": {
          "type": "integer",
          "minimum": 1,
          "default": 1
        }
      },
      {
        "name": "limit",
        "in": "query",
        "required": false,
        "schema": {
          "type": "integer",
          "minimum": 1,
          "maximum": 100,
          "default": 25
        }
      },
      {
        "name": "sort",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "service_name",
            "default_rate"
          ],
          "default": "service_name"
        }
      },
      {
        "name": "order",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "asc",
            "desc"
          ],
          "default": "asc"
        }
      },
      {
        "name": "search",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "is_active",
        "in": "query",
        "required": false,
        "schema": {
          "anyOf": [
            {
              "type": "string",
              "enum": [
                "true"
              ]
            },
            {
              "type": "string",
              "enum": [
                "false"
              ]
            }
          ]
        }
      },
      {
        "name": "category_id",
        "in": "query",
        "required": false,
        "schema": {
          "anyOf": [
            {
              "type": "string",
              "format": "uuid"
            },
            {
              "type": "string",
              "enum": [
                "null"
              ]
            }
          ]
        }
      },
      {
        "name": "is_license",
        "in": "query",
        "required": false,
        "schema": {
          "anyOf": [
            {
              "type": "string",
              "enum": [
                "true"
              ]
            },
            {
              "type": "string",
              "enum": [
                "false"
              ]
            }
          ]
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "type": "array",
          "items": {
            "$ref": "#/components/schemas/ProductCatalogEntry"
          }
        },
        "pagination": {
          "type": "object",
          "properties": {
            "page": {
              "type": "integer"
            },
            "limit": {
              "type": "integer"
            },
            "total": {
              "type": "integer"
            },
            "totalPages": {
              "type": "integer"
            },
            "hasNext": {
              "type": "boolean"
            },
            "hasPrev": {
              "type": "boolean"
            }
          },
          "required": [
            "page",
            "limit",
            "total",
            "totalPages",
            "hasNext",
            "hasPrev"
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data",
        "pagination"
      ]
    }
  },
  {
    "id": "post-_api_v1_products",
    "method": "post",
    "path": "/api/v1/products",
    "displayName": "Create product",
    "summary": "Create product",
    "description": "Creates a new product catalog entry. Resolve custom_service_type_id with GET /api/v1/service-types and category_id with GET /api/v1/categories/service before calling this endpoint. Products are catalog entries with item_kind product and always use billing_method usage.",
    "tags": [
      "Products",
      "Service Catalog"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "service_name": {
          "type": "string",
          "minLength": 1,
          "maxLength": 255
        },
        "custom_service_type_id": {
          "type": "string",
          "format": "uuid"
        },
        "billing_method": {
          "type": "string",
          "enum": [
            "usage"
          ],
          "default": "usage"
        },
        "default_rate": {
          "type": "number",
          "minimum": 0,
          "default": 0
        },
        "currency_code": {
          "type": "string",
          "minLength": 3,
          "maxLength": 3,
          "default": "USD"
        },
        "unit_of_measure": {
          "type": "string",
          "minLength": 1,
          "maxLength": 128
        },
        "category_id": {
          "anyOf": [
            {
              "type": "string",
              "format": "uuid"
            },
            {
              "type": "null"
            },
            {
              "type": "null"
            }
          ]
        },
        "tax_rate_id": {
          "anyOf": [
            {
              "type": "string",
              "format": "uuid"
            },
            {
              "type": "null"
            },
            {
              "type": "null"
            }
          ]
        },
        "description": {
          "anyOf": [
            {
              "type": "string",
              "maxLength": 2048
            },
            {
              "type": "null"
            },
            {
              "type": "null"
            }
          ]
        },
        "sku": {
          "anyOf": [
            {
              "type": "string",
              "maxLength": 128
            },
            {
              "type": "null"
            },
            {
              "type": "null"
            }
          ]
        },
        "cost": {
          "anyOf": [
            {
              "type": "number",
              "minimum": 0
            },
            {
              "type": "null"
            },
            {
              "type": "null"
            }
          ]
        },
        "cost_currency": {
          "anyOf": [
            {
              "type": "string",
              "minLength": 3,
              "maxLength": 3
            },
            {
              "type": "null"
            },
            {
              "type": "null"
            }
          ],
          "default": "USD"
        },
        "vendor": {
          "anyOf": [
            {
              "type": "string",
              "maxLength": 255
            },
            {
              "type": "null"
            },
            {
              "type": "null"
            }
          ]
        },
        "manufacturer": {
          "anyOf": [
            {
              "type": "string",
              "maxLength": 255
            },
            {
              "type": "null"
            },
            {
              "type": "null"
            }
          ]
        },
        "product_category": {
          "anyOf": [
            {
              "type": "string",
              "maxLength": 255
            },
            {
              "type": "null"
            },
            {
              "type": "null"
            }
          ]
        },
        "is_license": {
          "type": "boolean",
          "default": false
        },
        "license_term": {
          "anyOf": [
            {
              "type": "string",
              "maxLength": 64
            },
            {
              "type": "null"
            },
            {
              "type": "null"
            }
          ]
        },
        "license_billing_cadence": {
          "anyOf": [
            {
              "type": "string",
              "maxLength": 64
            },
            {
              "type": "null"
            },
            {
              "type": "null"
            }
          ]
        },
        "is_active": {
          "type": "boolean",
          "default": true
        },
        "prices": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "currency_code": {
                "type": "string",
                "minLength": 3,
                "maxLength": 3
              },
              "rate": {
                "type": "number",
                "minimum": 0
              }
            },
            "required": [
              "currency_code",
              "rate"
            ]
          }
        }
      },
      "required": [
        "service_name",
        "custom_service_type_id",
        "unit_of_measure"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "$ref": "#/components/schemas/ProductCatalogEntry"
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_products_id",
    "method": "get",
    "path": "/api/v1/products/{id}",
    "displayName": "Get product",
    "summary": "Get product",
    "description": "Returns a single product catalog entry by UUID.",
    "tags": [
      "Products",
      "Service Catalog"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Product UUID.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Product UUID."
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "$ref": "#/components/schemas/ProductCatalogEntry"
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "put-_api_v1_products_id",
    "method": "put",
    "path": "/api/v1/products/{id}",
    "displayName": "Update product",
    "summary": "Update product",
    "description": "Updates a product catalog entry by UUID.",
    "tags": [
      "Products",
      "Service Catalog"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Product UUID.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Product UUID."
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "service_name": {
          "type": "string",
          "minLength": 1,
          "maxLength": 255
        },
        "custom_service_type_id": {
          "type": "string",
          "format": "uuid"
        },
        "billing_method": {
          "type": "string",
          "enum": [
            "usage"
          ],
          "default": "usage"
        },
        "default_rate": {
          "type": "number",
          "minimum": 0,
          "default": 0
        },
        "currency_code": {
          "type": "string",
          "minLength": 3,
          "maxLength": 3,
          "default": "USD"
        },
        "unit_of_measure": {
          "type": "string",
          "minLength": 1,
          "maxLength": 128
        },
        "category_id": {
          "anyOf": [
            {
              "type": "string",
              "format": "uuid"
            },
            {
              "type": "null"
            },
            {
              "type": "null"
            }
          ]
        },
        "tax_rate_id": {
          "anyOf": [
            {
              "type": "string",
              "format": "uuid"
            },
            {
              "type": "null"
            },
            {
              "type": "null"
            }
          ]
        },
        "description": {
          "anyOf": [
            {
              "type": "string",
              "maxLength": 2048
            },
            {
              "type": "null"
            },
            {
              "type": "null"
            }
          ]
        },
        "sku": {
          "anyOf": [
            {
              "type": "string",
              "maxLength": 128
            },
            {
              "type": "null"
            },
            {
              "type": "null"
            }
          ]
        },
        "cost": {
          "anyOf": [
            {
              "type": "number",
              "minimum": 0
            },
            {
              "type": "null"
            },
            {
              "type": "null"
            }
          ]
        },
        "cost_currency": {
          "anyOf": [
            {
              "type": "string",
              "minLength": 3,
              "maxLength": 3
            },
            {
              "type": "null"
            },
            {
              "type": "null"
            }
          ],
          "default": "USD"
        },
        "vendor": {
          "anyOf": [
            {
              "type": "string",
              "maxLength": 255
            },
            {
              "type": "null"
            },
            {
              "type": "null"
            }
          ]
        },
        "manufacturer": {
          "anyOf": [
            {
              "type": "string",
              "maxLength": 255
            },
            {
              "type": "null"
            },
            {
              "type": "null"
            }
          ]
        },
        "product_category": {
          "anyOf": [
            {
              "type": "string",
              "maxLength": 255
            },
            {
              "type": "null"
            },
            {
              "type": "null"
            }
          ]
        },
        "is_license": {
          "type": "boolean",
          "default": false
        },
        "license_term": {
          "anyOf": [
            {
              "type": "string",
              "maxLength": 64
            },
            {
              "type": "null"
            },
            {
              "type": "null"
            }
          ]
        },
        "license_billing_cadence": {
          "anyOf": [
            {
              "type": "string",
              "maxLength": 64
            },
            {
              "type": "null"
            },
            {
              "type": "null"
            }
          ]
        },
        "is_active": {
          "type": "boolean",
          "default": true
        },
        "prices": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "currency_code": {
                "type": "string",
                "minLength": 3,
                "maxLength": 3
              },
              "rate": {
                "type": "number",
                "minimum": 0
              }
            },
            "required": [
              "currency_code",
              "rate"
            ]
          }
        }
      }
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "$ref": "#/components/schemas/ProductCatalogEntry"
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "delete-_api_v1_products_id",
    "method": "delete",
    "path": "/api/v1/products/{id}",
    "displayName": "Delete product",
    "summary": "Delete product",
    "description": "Deletes a product catalog entry by UUID.",
    "tags": [
      "Products",
      "Service Catalog"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Product UUID.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Product UUID."
        }
      }
    ]
  },
  {
    "id": "get-_api_v1_servicetypes",
    "method": "get",
    "path": "/api/v1/service-types",
    "displayName": "List service types",
    "summary": "List service types",
    "description": "Returns tenant service types. Use this endpoint to resolve custom_service_type_id before creating or updating services and products in the service catalog.",
    "tags": [
      "Service Types",
      "Service Catalog"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "search",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "is_active",
        "in": "query",
        "required": false,
        "schema": {
          "type": "boolean"
        }
      },
      {
        "name": "page",
        "in": "query",
        "required": false,
        "schema": {
          "type": "integer",
          "minimum": 1
        }
      },
      {
        "name": "limit",
        "in": "query",
        "required": false,
        "schema": {
          "type": "integer",
          "minimum": 1,
          "maximum": 100
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "type": "array",
          "items": {
            "$ref": "#/components/schemas/ServiceTypeResource"
          }
        },
        "pagination": {
          "type": "object",
          "properties": {
            "page": {
              "type": "integer"
            },
            "limit": {
              "type": "integer"
            },
            "total": {
              "type": "integer"
            },
            "totalPages": {
              "type": "integer"
            },
            "hasNext": {
              "type": "boolean"
            },
            "hasPrev": {
              "type": "boolean"
            }
          },
          "required": [
            "page",
            "limit",
            "total",
            "totalPages",
            "hasNext",
            "hasPrev"
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data",
        "pagination"
      ]
    }
  },
  {
    "id": "get-_api_v1_servicetypes_id",
    "method": "get",
    "path": "/api/v1/service-types/{id}",
    "displayName": "Get service type",
    "summary": "Get service type",
    "description": "Returns a single tenant service type by UUID.",
    "tags": [
      "Service Types",
      "Service Catalog"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Service type UUID.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Service type UUID."
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "$ref": "#/components/schemas/ServiceTypeResource"
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_webhooks",
    "method": "get",
    "path": "/api/v1/webhooks",
    "displayName": "List webhooks",
    "summary": "List webhooks",
    "description": "Lists tenant webhooks with pagination and filter query fields.",
    "tags": [
      "Webhooks"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "page",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "limit",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "sort",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "order",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "asc",
            "desc"
          ]
        }
      },
      {
        "name": "name",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "url",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "event_type",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "is_active",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ]
        }
      },
      {
        "name": "is_test_mode",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ]
        }
      },
      {
        "name": "payload_format",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "json",
            "xml",
            "form_data",
            "custom"
          ]
        }
      },
      {
        "name": "has_failures",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ]
        }
      },
      {
        "name": "last_delivery_from",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "last_delivery_to",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "delivery_rate_min",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "delivery_rate_max",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "query",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "type": "array",
          "items": {
            "$ref": "#/components/schemas/WebhookRecordV1"
          }
        },
        "pagination": {
          "type": "object",
          "properties": {
            "page": {
              "type": "integer"
            },
            "limit": {
              "type": "integer"
            },
            "total": {
              "type": "integer"
            },
            "totalPages": {
              "type": "integer"
            },
            "hasNext": {
              "type": "boolean"
            },
            "hasPrev": {
              "type": "boolean"
            }
          },
          "required": [
            "page",
            "limit",
            "total",
            "totalPages",
            "hasNext",
            "hasPrev"
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data",
        "pagination"
      ]
    }
  },
  {
    "id": "post-_api_v1_webhooks",
    "method": "post",
    "path": "/api/v1/webhooks",
    "displayName": "Create webhook",
    "summary": "Create webhook",
    "description": "Creates a webhook configuration. Supports per-entity payload_fields allowlists; an undefined or null map yields the full payload.",
    "tags": [
      "Webhooks"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "name": {
          "type": "string",
          "minLength": 1
        },
        "description": {
          "type": "string"
        },
        "url": {
          "type": "string",
          "format": "uri"
        },
        "method": {
          "type": "string",
          "enum": [
            "GET",
            "POST",
            "PUT",
            "PATCH",
            "DELETE"
          ]
        },
        "event_types": {
          "type": "array",
          "items": {
            "$ref": "#/components/schemas/WebhookEventTypeV1"
          },
          "minItems": 1
        },
        "security": {
          "type": "object",
          "additionalProperties": {}
        },
        "payload_format": {
          "type": "string",
          "enum": [
            "json",
            "xml",
            "form_data",
            "custom"
          ]
        },
        "content_type": {
          "type": "string"
        },
        "custom_headers": {
          "type": "object",
          "additionalProperties": {
            "type": "string"
          }
        },
        "event_filter": {
          "type": "object",
          "additionalProperties": {}
        },
        "payload_fields": {
          "type": [
            "object",
            "null"
          ],
          "properties": {
            "ticket": {
              "type": [
                "array",
                "null"
              ],
              "items": {
                "type": "string",
                "enum": [
                  "ticket_number",
                  "title",
                  "url",
                  "status_id",
                  "status_name",
                  "is_closed",
                  "previous_status_id",
                  "previous_status_name",
                  "priority_id",
                  "priority_name",
                  "client_id",
                  "client_name",
                  "contact_name_id",
                  "contact_name",
                  "contact_email",
                  "assigned_to",
                  "assigned_to_name",
                  "assigned_team_id",
                  "board_id",
                  "board_name",
                  "category_id",
                  "subcategory_id",
                  "entered_at",
                  "updated_at",
                  "closed_at",
                  "due_date",
                  "tags",
                  "comment",
                  "changes",
                  "comments"
                ]
              }
            },
            "project": {
              "type": [
                "array",
                "null"
              ],
              "items": {
                "type": "string",
                "enum": [
                  "project_name",
                  "wbs_code",
                  "description",
                  "status_id",
                  "status_name",
                  "is_closed",
                  "previous_status_id",
                  "previous_status_name",
                  "client_id",
                  "client_name",
                  "contact_name_id",
                  "contact_name",
                  "contact_email",
                  "assigned_to",
                  "assigned_to_name",
                  "start_date",
                  "end_date",
                  "budgeted_hours",
                  "url",
                  "changes",
                  "phases",
                  "task_counts",
                  "task_id",
                  "phase_id",
                  "phase_name",
                  "task_name",
                  "estimated_hours",
                  "actual_hours",
                  "due_date",
                  "priority_id",
                  "priority_name",
                  "tags"
                ]
              }
            }
          },
          "description": "Per-entity payload allowlist. null/{} = full payload everywhere. { ticket: null } = full ticket payload. { ticket: [] } = required-only. { ticket: [a,b] } = explicit allowlist plus required keys. Unknown entities and fields are rejected by WEBHOOK_PAYLOAD_FIELDS_BY_ENTITY in lib/webhooks/payloadFields. Supported fields: ticket: ticket_number, title, url, status_id, status_name, is_closed, previous_status_id, previous_status_name, priority_id, priority_name, client_id, client_name, contact_name_id, contact_name, contact_email, assigned_to, assigned_to_name, assigned_team_id, board_id, board_name, category_id, subcategory_id, entered_at, updated_at, closed_at, due_date, tags, comment, changes, comments; project: project_name, wbs_code, description, status_id, status_name, is_closed, previous_status_id, previous_status_name, client_id, client_name, contact_name_id, contact_name, contact_email, assigned_to, assigned_to_name, start_date, end_date, budgeted_hours, url, changes, phases, task_counts, task_id, phase_id, phase_name, task_name, estimated_hours, actual_hours, due_date, priority_id, priority_name, tags."
        },
        "payload_transformation": {
          "type": "object",
          "additionalProperties": {}
        },
        "retry_config": {
          "type": "object",
          "additionalProperties": {}
        },
        "is_active": {
          "type": "boolean"
        },
        "is_test_mode": {
          "type": "boolean"
        },
        "verify_ssl": {
          "type": "boolean"
        },
        "secret_token": {
          "type": "string"
        },
        "rate_limit": {
          "type": "object",
          "additionalProperties": {}
        },
        "metadata": {
          "type": "object",
          "additionalProperties": {}
        },
        "tags": {
          "type": "array",
          "items": {
            "type": "string"
          }
        }
      },
      "required": [
        "name",
        "url",
        "event_types"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "$ref": "#/components/schemas/WebhookRecordV1"
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_webhooks_analytics",
    "method": "get",
    "path": "/api/v1/webhooks/analytics",
    "displayName": "Get system webhook analytics",
    "summary": "Get system webhook analytics",
    "description": "Returns aggregated webhook delivery analytics for the tenant over a date window.",
    "tags": [
      "Webhooks"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "webhook_id",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      },
      {
        "name": "date_from",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "format": "date-time"
        }
      },
      {
        "name": "date_to",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "format": "date-time"
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "$ref": "#/components/schemas/WebhookAnalyticsResponseV1"
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_webhooks_events",
    "method": "get",
    "path": "/api/v1/webhooks/events",
    "displayName": "List available webhook events",
    "summary": "List available webhook events",
    "description": "Returns the supported webhook event types from webhookEventTypeSchema (ticket.*, project.*, invoice.*, etc.).",
    "tags": [
      "Webhooks"
    ],
    "approvalRequired": false,
    "parameters": [],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "$ref": "#/components/schemas/WebhookEventListV1"
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_webhooks_templates",
    "method": "get",
    "path": "/api/v1/webhooks/templates",
    "displayName": "List webhook templates",
    "summary": "List webhook templates",
    "description": "Returns webhook templates visible to the tenant (own + system templates).",
    "tags": [
      "Webhooks"
    ],
    "approvalRequired": false,
    "parameters": [],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "type": "array",
          "items": {
            "$ref": "#/components/schemas/WebhookTemplateRecordV1"
          }
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "post-_api_v1_webhooks_templates",
    "method": "post",
    "path": "/api/v1/webhooks/templates",
    "displayName": "Create webhook template",
    "summary": "Create webhook template",
    "description": "Creates a reusable webhook template. Requires system_settings RBAC.",
    "tags": [
      "Webhooks"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "name": {
          "type": "string"
        },
        "description": {
          "type": "string"
        },
        "category": {
          "type": "string"
        },
        "default_config": {
          "type": "object",
          "additionalProperties": {}
        },
        "required_fields": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "supported_events": {
          "type": "array",
          "items": {
            "$ref": "#/components/schemas/WebhookEventTypeV1"
          }
        },
        "is_system_template": {
          "type": "boolean"
        }
      },
      "required": [
        "name",
        "category",
        "default_config"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "$ref": "#/components/schemas/WebhookTemplateRecordV1"
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_webhooks_templates_id",
    "method": "get",
    "path": "/api/v1/webhooks/templates/{id}",
    "displayName": "Get webhook template detail (webhook getById wiring)",
    "summary": "Get webhook template detail (webhook getById wiring)",
    "description": "Template detail route delegates to ApiWebhookController.getById() and looks up rows from the webhooks table by the URL id, not webhook_templates. Calling with a true template_id will return 404.",
    "tags": [
      "Webhooks"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Webhook UUID from webhooks.webhook_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Webhook UUID from webhooks.webhook_id."
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "$ref": "#/components/schemas/WebhookRecordV1"
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "put-_api_v1_webhooks_templates_id",
    "method": "put",
    "path": "/api/v1/webhooks/templates/{id}",
    "displayName": "Update webhook template (webhook update wiring)",
    "summary": "Update webhook template (webhook update wiring)",
    "description": "Template update route delegates to ApiWebhookController.update() and operates on webhooks rows, not webhook_templates.",
    "tags": [
      "Webhooks"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Webhook UUID from webhooks.webhook_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Webhook UUID from webhooks.webhook_id."
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "name": {
          "type": "string",
          "minLength": 1
        },
        "description": {
          "type": "string"
        },
        "url": {
          "type": "string",
          "format": "uri"
        },
        "method": {
          "type": "string",
          "enum": [
            "GET",
            "POST",
            "PUT",
            "PATCH",
            "DELETE"
          ]
        },
        "event_types": {
          "type": "array",
          "items": {
            "$ref": "#/components/schemas/WebhookEventTypeV1"
          },
          "minItems": 1
        },
        "security": {
          "type": "object",
          "additionalProperties": {}
        },
        "payload_format": {
          "type": "string",
          "enum": [
            "json",
            "xml",
            "form_data",
            "custom"
          ]
        },
        "content_type": {
          "type": "string"
        },
        "custom_headers": {
          "type": "object",
          "additionalProperties": {
            "type": "string"
          }
        },
        "event_filter": {
          "type": "object",
          "additionalProperties": {}
        },
        "payload_fields": {
          "type": [
            "object",
            "null"
          ],
          "properties": {
            "ticket": {
              "type": [
                "array",
                "null"
              ],
              "items": {
                "type": "string",
                "enum": [
                  "ticket_number",
                  "title",
                  "url",
                  "status_id",
                  "status_name",
                  "is_closed",
                  "previous_status_id",
                  "previous_status_name",
                  "priority_id",
                  "priority_name",
                  "client_id",
                  "client_name",
                  "contact_name_id",
                  "contact_name",
                  "contact_email",
                  "assigned_to",
                  "assigned_to_name",
                  "assigned_team_id",
                  "board_id",
                  "board_name",
                  "category_id",
                  "subcategory_id",
                  "entered_at",
                  "updated_at",
                  "closed_at",
                  "due_date",
                  "tags",
                  "comment",
                  "changes",
                  "comments"
                ]
              }
            },
            "project": {
              "type": [
                "array",
                "null"
              ],
              "items": {
                "type": "string",
                "enum": [
                  "project_name",
                  "wbs_code",
                  "description",
                  "status_id",
                  "status_name",
                  "is_closed",
                  "previous_status_id",
                  "previous_status_name",
                  "client_id",
                  "client_name",
                  "contact_name_id",
                  "contact_name",
                  "contact_email",
                  "assigned_to",
                  "assigned_to_name",
                  "start_date",
                  "end_date",
                  "budgeted_hours",
                  "url",
                  "changes",
                  "phases",
                  "task_counts",
                  "task_id",
                  "phase_id",
                  "phase_name",
                  "task_name",
                  "estimated_hours",
                  "actual_hours",
                  "due_date",
                  "priority_id",
                  "priority_name",
                  "tags"
                ]
              }
            }
          },
          "description": "Per-entity payload allowlist. null/{} = full payload everywhere. { ticket: null } = full ticket payload. { ticket: [] } = required-only. { ticket: [a,b] } = explicit allowlist plus required keys. Unknown entities and fields are rejected by WEBHOOK_PAYLOAD_FIELDS_BY_ENTITY in lib/webhooks/payloadFields. Supported fields: ticket: ticket_number, title, url, status_id, status_name, is_closed, previous_status_id, previous_status_name, priority_id, priority_name, client_id, client_name, contact_name_id, contact_name, contact_email, assigned_to, assigned_to_name, assigned_team_id, board_id, board_name, category_id, subcategory_id, entered_at, updated_at, closed_at, due_date, tags, comment, changes, comments; project: project_name, wbs_code, description, status_id, status_name, is_closed, previous_status_id, previous_status_name, client_id, client_name, contact_name_id, contact_name, contact_email, assigned_to, assigned_to_name, start_date, end_date, budgeted_hours, url, changes, phases, task_counts, task_id, phase_id, phase_name, task_name, estimated_hours, actual_hours, due_date, priority_id, priority_name, tags."
        },
        "payload_transformation": {
          "type": "object",
          "additionalProperties": {}
        },
        "retry_config": {
          "type": "object",
          "additionalProperties": {}
        },
        "is_active": {
          "type": "boolean"
        },
        "is_test_mode": {
          "type": "boolean"
        },
        "verify_ssl": {
          "type": "boolean"
        },
        "secret_token": {
          "type": "string"
        },
        "rate_limit": {
          "type": "object",
          "additionalProperties": {}
        },
        "metadata": {
          "type": "object",
          "additionalProperties": {}
        },
        "tags": {
          "type": "array",
          "items": {
            "type": "string"
          }
        }
      },
      "required": [
        "name",
        "url",
        "event_types"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "$ref": "#/components/schemas/WebhookRecordV1"
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "delete-_api_v1_webhooks_templates_id",
    "method": "delete",
    "path": "/api/v1/webhooks/templates/{id}",
    "displayName": "Delete webhook template (webhook delete wiring)",
    "summary": "Delete webhook template (webhook delete wiring)",
    "description": "Template delete route delegates to ApiWebhookController.delete() and removes a webhooks row, not a webhook_templates row.",
    "tags": [
      "Webhooks"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Webhook UUID from webhooks.webhook_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Webhook UUID from webhooks.webhook_id."
        }
      }
    ]
  },
  {
    "id": "post-_api_v1_webhooks_templates_id_create",
    "method": "post",
    "path": "/api/v1/webhooks/templates/{id}/create",
    "displayName": "Create webhook from template",
    "summary": "Create webhook from template",
    "description": "Instantiates a webhook configuration from a template, merging caller-supplied overrides.",
    "tags": [
      "Webhooks"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Webhook UUID from webhooks.webhook_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Webhook UUID from webhooks.webhook_id."
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "name": {
          "type": "string",
          "minLength": 1
        },
        "url": {
          "type": "string",
          "format": "uri"
        },
        "custom_config": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "name",
        "url"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "$ref": "#/components/schemas/WebhookRecordV1"
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "post-_api_v1_webhooks_test",
    "method": "post",
    "path": "/api/v1/webhooks/test",
    "displayName": "Test webhook configuration",
    "summary": "Test webhook configuration",
    "description": "Sends a one-off test delivery. Pass webhook_id to reuse stored configuration, or override_url/test_payload for ad-hoc testing.",
    "tags": [
      "Webhooks"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "webhook_id": {
          "type": "string",
          "format": "uuid"
        },
        "test_event_type": {
          "$ref": "#/components/schemas/WebhookEventTypeV1"
        },
        "test_payload": {
          "type": "object",
          "additionalProperties": {}
        },
        "override_url": {
          "type": "string",
          "format": "uri"
        }
      },
      "required": [
        "test_event_type"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "$ref": "#/components/schemas/WebhookTestResultV1"
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "post-_api_v1_webhooks_verify",
    "method": "post",
    "path": "/api/v1/webhooks/verify",
    "displayName": "Verify webhook signature",
    "summary": "Verify webhook signature",
    "description": "Verifies an X-Alga-Signature header value against a stored signing secret. Returns { valid: true } only for sha256 with a matching v1 signature.",
    "tags": [
      "Webhooks"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "algorithm": {
          "type": "string",
          "enum": [
            "sha1",
            "sha256",
            "sha512"
          ],
          "description": "Only sha256 is currently honored; other values yield valid=false."
        },
        "signature": {
          "type": "string",
          "description": "Either the raw v1 signature, or the canonical \"t=<unix>,v1=<sig>\" header value. When raw and a timestamp is supplied, the controller assembles the canonical form before verifying."
        },
        "timestamp": {
          "type": "number",
          "description": "Unix-seconds timestamp paired with a raw v1 signature."
        },
        "body": {
          "type": "string",
          "description": "Exact request body bytes to verify against."
        },
        "webhook_id": {
          "type": "string",
          "format": "uuid",
          "description": "Resolves the signing secret from webhooks.signing_secret_vault_path."
        },
        "secret_vault_path": {
          "type": "string",
          "description": "Vault key (basename of secret_vault_path) used when no webhook_id is supplied. webhook_id or secret_vault_path is required."
        }
      },
      "required": [
        "algorithm",
        "signature",
        "body"
      ],
      "description": "Verification request: webhook_id OR secret_vault_path is required."
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "$ref": "#/components/schemas/WebhookSignatureValidationV1"
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_webhooks_id",
    "method": "get",
    "path": "/api/v1/webhooks/{id}",
    "displayName": "Get webhook",
    "summary": "Get webhook",
    "description": "Returns a single webhook by id.",
    "tags": [
      "Webhooks"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Webhook UUID from webhooks.webhook_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Webhook UUID from webhooks.webhook_id."
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "$ref": "#/components/schemas/WebhookRecordV1"
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "put-_api_v1_webhooks_id",
    "method": "put",
    "path": "/api/v1/webhooks/{id}",
    "displayName": "Update webhook",
    "summary": "Update webhook",
    "description": "Updates a webhook by id. Body accepts the same fields as create, all optional.",
    "tags": [
      "Webhooks"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Webhook UUID from webhooks.webhook_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Webhook UUID from webhooks.webhook_id."
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "name": {
          "type": "string",
          "minLength": 1
        },
        "description": {
          "type": "string"
        },
        "url": {
          "type": "string",
          "format": "uri"
        },
        "method": {
          "type": "string",
          "enum": [
            "GET",
            "POST",
            "PUT",
            "PATCH",
            "DELETE"
          ]
        },
        "event_types": {
          "type": "array",
          "items": {
            "$ref": "#/components/schemas/WebhookEventTypeV1"
          },
          "minItems": 1
        },
        "security": {
          "type": "object",
          "additionalProperties": {}
        },
        "payload_format": {
          "type": "string",
          "enum": [
            "json",
            "xml",
            "form_data",
            "custom"
          ]
        },
        "content_type": {
          "type": "string"
        },
        "custom_headers": {
          "type": "object",
          "additionalProperties": {
            "type": "string"
          }
        },
        "event_filter": {
          "type": "object",
          "additionalProperties": {}
        },
        "payload_fields": {
          "type": [
            "object",
            "null"
          ],
          "properties": {
            "ticket": {
              "type": [
                "array",
                "null"
              ],
              "items": {
                "type": "string",
                "enum": [
                  "ticket_number",
                  "title",
                  "url",
                  "status_id",
                  "status_name",
                  "is_closed",
                  "previous_status_id",
                  "previous_status_name",
                  "priority_id",
                  "priority_name",
                  "client_id",
                  "client_name",
                  "contact_name_id",
                  "contact_name",
                  "contact_email",
                  "assigned_to",
                  "assigned_to_name",
                  "assigned_team_id",
                  "board_id",
                  "board_name",
                  "category_id",
                  "subcategory_id",
                  "entered_at",
                  "updated_at",
                  "closed_at",
                  "due_date",
                  "tags",
                  "comment",
                  "changes",
                  "comments"
                ]
              }
            },
            "project": {
              "type": [
                "array",
                "null"
              ],
              "items": {
                "type": "string",
                "enum": [
                  "project_name",
                  "wbs_code",
                  "description",
                  "status_id",
                  "status_name",
                  "is_closed",
                  "previous_status_id",
                  "previous_status_name",
                  "client_id",
                  "client_name",
                  "contact_name_id",
                  "contact_name",
                  "contact_email",
                  "assigned_to",
                  "assigned_to_name",
                  "start_date",
                  "end_date",
                  "budgeted_hours",
                  "url",
                  "changes",
                  "phases",
                  "task_counts",
                  "task_id",
                  "phase_id",
                  "phase_name",
                  "task_name",
                  "estimated_hours",
                  "actual_hours",
                  "due_date",
                  "priority_id",
                  "priority_name",
                  "tags"
                ]
              }
            }
          },
          "description": "Per-entity payload allowlist. null/{} = full payload everywhere. { ticket: null } = full ticket payload. { ticket: [] } = required-only. { ticket: [a,b] } = explicit allowlist plus required keys. Unknown entities and fields are rejected by WEBHOOK_PAYLOAD_FIELDS_BY_ENTITY in lib/webhooks/payloadFields. Supported fields: ticket: ticket_number, title, url, status_id, status_name, is_closed, previous_status_id, previous_status_name, priority_id, priority_name, client_id, client_name, contact_name_id, contact_name, contact_email, assigned_to, assigned_to_name, assigned_team_id, board_id, board_name, category_id, subcategory_id, entered_at, updated_at, closed_at, due_date, tags, comment, changes, comments; project: project_name, wbs_code, description, status_id, status_name, is_closed, previous_status_id, previous_status_name, client_id, client_name, contact_name_id, contact_name, contact_email, assigned_to, assigned_to_name, start_date, end_date, budgeted_hours, url, changes, phases, task_counts, task_id, phase_id, phase_name, task_name, estimated_hours, actual_hours, due_date, priority_id, priority_name, tags."
        },
        "payload_transformation": {
          "type": "object",
          "additionalProperties": {}
        },
        "retry_config": {
          "type": "object",
          "additionalProperties": {}
        },
        "is_active": {
          "type": "boolean"
        },
        "is_test_mode": {
          "type": "boolean"
        },
        "verify_ssl": {
          "type": "boolean"
        },
        "secret_token": {
          "type": "string"
        },
        "rate_limit": {
          "type": "object",
          "additionalProperties": {}
        },
        "metadata": {
          "type": "object",
          "additionalProperties": {}
        },
        "tags": {
          "type": "array",
          "items": {
            "type": "string"
          }
        }
      },
      "required": [
        "name",
        "url",
        "event_types"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "$ref": "#/components/schemas/WebhookRecordV1"
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "delete-_api_v1_webhooks_id",
    "method": "delete",
    "path": "/api/v1/webhooks/{id}",
    "displayName": "Delete webhook",
    "summary": "Delete webhook",
    "description": "Deletes a webhook by id.",
    "tags": [
      "Webhooks"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Webhook UUID from webhooks.webhook_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Webhook UUID from webhooks.webhook_id."
        }
      }
    ]
  },
  {
    "id": "get-_api_v1_webhooks_id_analytics",
    "method": "get",
    "path": "/api/v1/webhooks/{id}/analytics",
    "displayName": "Get webhook analytics",
    "summary": "Get webhook analytics",
    "description": "Returns delivery analytics for a single webhook over a date window.",
    "tags": [
      "Webhooks"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Webhook UUID from webhooks.webhook_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Webhook UUID from webhooks.webhook_id."
        }
      },
      {
        "name": "webhook_id",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      },
      {
        "name": "date_from",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "format": "date-time"
        }
      },
      {
        "name": "date_to",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "format": "date-time"
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "$ref": "#/components/schemas/WebhookAnalyticsResponseV1"
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_webhooks_id_deliveries",
    "method": "get",
    "path": "/api/v1/webhooks/{id}/deliveries",
    "displayName": "List webhook deliveries",
    "summary": "List webhook deliveries",
    "description": "Returns paginated delivery history for a webhook id, optionally filtered by status and date window.",
    "tags": [
      "Webhooks"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Webhook UUID from webhooks.webhook_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Webhook UUID from webhooks.webhook_id."
        }
      },
      {
        "name": "page",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "limit",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "status",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "pending",
            "delivered",
            "failed",
            "retrying",
            "abandoned"
          ]
        }
      },
      {
        "name": "from_date",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "format": "date-time"
        }
      },
      {
        "name": "to_date",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "format": "date-time"
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "type": "array",
          "items": {
            "$ref": "#/components/schemas/WebhookDeliveryRecordV1"
          }
        },
        "pagination": {
          "type": "object",
          "properties": {
            "page": {
              "type": "integer"
            },
            "limit": {
              "type": "integer"
            },
            "total": {
              "type": "integer"
            },
            "totalPages": {
              "type": "integer"
            },
            "hasNext": {
              "type": "boolean"
            },
            "hasPrev": {
              "type": "boolean"
            }
          },
          "required": [
            "page",
            "limit",
            "total",
            "totalPages",
            "hasNext",
            "hasPrev"
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data",
        "pagination"
      ]
    }
  },
  {
    "id": "get-_api_v1_webhooks_id_deliveries_delivery_id",
    "method": "get",
    "path": "/api/v1/webhooks/{id}/deliveries/{delivery_id}",
    "displayName": "Get delivery detail",
    "summary": "Get delivery detail",
    "description": "Returns a single delivery record (request/response payloads, status, retry pointer).",
    "tags": [
      "Webhooks"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Webhook UUID from webhooks.webhook_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Webhook UUID from webhooks.webhook_id."
        }
      },
      {
        "name": "delivery_id",
        "in": "path",
        "required": true,
        "description": "Delivery UUID from webhook_deliveries.delivery_id (URL-derived).",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Delivery UUID from webhook_deliveries.delivery_id (URL-derived)."
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "$ref": "#/components/schemas/WebhookDeliveryRecordV1"
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "post-_api_v1_webhooks_id_deliveries_delivery_id_retry",
    "method": "post",
    "path": "/api/v1/webhooks/{id}/deliveries/{delivery_id}/retry",
    "displayName": "Retry delivery",
    "summary": "Retry delivery",
    "description": "Re-sends a previously failed delivery and records a new attempt on the same delivery row.",
    "tags": [
      "Webhooks"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Webhook UUID from webhooks.webhook_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Webhook UUID from webhooks.webhook_id."
        }
      },
      {
        "name": "delivery_id",
        "in": "path",
        "required": true,
        "description": "Delivery UUID from webhook_deliveries.delivery_id (URL-derived).",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Delivery UUID from webhook_deliveries.delivery_id (URL-derived)."
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "$ref": "#/components/schemas/WebhookDeliveryRecordV1"
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_webhooks_id_health",
    "method": "get",
    "path": "/api/v1/webhooks/{id}/health",
    "displayName": "Get webhook health",
    "summary": "Get webhook health",
    "description": "Derives status (healthy | failing | disabled), success_rate, and last delivery timestamps from the webhook stats counters.",
    "tags": [
      "Webhooks"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Webhook UUID from webhooks.webhook_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Webhook UUID from webhooks.webhook_id."
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "$ref": "#/components/schemas/WebhookHealthV1"
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "post-_api_v1_webhooks_id_secret_rotate",
    "method": "post",
    "path": "/api/v1/webhooks/{id}/secret/rotate",
    "displayName": "Rotate webhook secret",
    "summary": "Rotate webhook secret",
    "description": "Generates a new 32-byte base64url signing secret, persists it via webhookModel.update, and returns the secret in the response. The secret is only available at rotation time.",
    "tags": [
      "Webhooks"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Webhook UUID from webhooks.webhook_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Webhook UUID from webhooks.webhook_id."
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "$ref": "#/components/schemas/WebhookSecretRotationV1"
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_webhooks_id_subscriptions",
    "method": "get",
    "path": "/api/v1/webhooks/{id}/subscriptions",
    "displayName": "List webhook event subscriptions",
    "summary": "List webhook event subscriptions",
    "description": "Returns the event types the webhook is subscribed to. Subscriptions are stored on the webhooks row (event_types column), not in a separate subscription table.",
    "tags": [
      "Webhooks"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Webhook UUID from webhooks.webhook_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Webhook UUID from webhooks.webhook_id."
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "$ref": "#/components/schemas/WebhookSubscriptionsResponseV1"
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "post-_api_v1_webhooks_id_test",
    "method": "post",
    "path": "/api/v1/webhooks/{id}/test",
    "displayName": "Test webhook by id",
    "summary": "Test webhook by id",
    "description": "Sends a signed test delivery to the webhook URL using the stored signing secret and records the attempt in webhook_deliveries with is_test=true.",
    "tags": [
      "Webhooks"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Webhook UUID from webhooks.webhook_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Webhook UUID from webhooks.webhook_id."
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "webhook_id": {
          "type": "string",
          "format": "uuid"
        },
        "test_event_type": {
          "$ref": "#/components/schemas/WebhookEventTypeV1"
        },
        "test_payload": {
          "type": "object",
          "additionalProperties": {}
        },
        "override_url": {
          "type": "string",
          "format": "uri"
        }
      },
      "required": [
        "test_event_type"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "$ref": "#/components/schemas/WebhookTestResultV1"
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_workflows",
    "method": "get",
    "path": "/api/v1/workflows",
    "displayName": "List workflows (route inventory only)",
    "summary": "List workflows (route inventory only)",
    "description": "This operation is currently present only in generated route inventory. No corresponding Next.js handler exists under server/src/app/api/v1/workflows in this worktree. Runtime behavior is middleware-dependent: missing/invalid x-api-key can return 401 before routing; with middleware requirements satisfied, Next.js returns not-found for the absent handler. Existing workflow APIs in this codebase are implemented under /api/workflow-definitions, /api/workflow-runs, and /api/workflow/events rather than /api/v1/workflows paths.",
    "tags": [
      "Workflows v1"
    ],
    "approvalRequired": false,
    "parameters": []
  },
  {
    "id": "post-_api_v1_workflows",
    "method": "post",
    "path": "/api/v1/workflows",
    "displayName": "Create workflow (route inventory only)",
    "summary": "Create workflow (route inventory only)",
    "description": "This operation is currently present only in generated route inventory. No corresponding Next.js handler exists under server/src/app/api/v1/workflows in this worktree. Runtime behavior is middleware-dependent: missing/invalid x-api-key can return 401 before routing; with middleware requirements satisfied, Next.js returns not-found for the absent handler. Existing workflow APIs in this codebase are implemented under /api/workflow-definitions, /api/workflow-runs, and /api/workflow/events rather than /api/v1/workflows paths.",
    "tags": [
      "Workflows v1"
    ],
    "approvalRequired": false,
    "parameters": []
  },
  {
    "id": "get-_api_v1_workflows_analytics",
    "method": "get",
    "path": "/api/v1/workflows/analytics",
    "displayName": "Get workflow analytics (route inventory only)",
    "summary": "Get workflow analytics (route inventory only)",
    "description": "This operation is currently present only in generated route inventory. No corresponding Next.js handler exists under server/src/app/api/v1/workflows in this worktree. Runtime behavior is middleware-dependent: missing/invalid x-api-key can return 401 before routing; with middleware requirements satisfied, Next.js returns not-found for the absent handler. Existing workflow APIs in this codebase are implemented under /api/workflow-definitions, /api/workflow-runs, and /api/workflow/events rather than /api/v1/workflows paths.",
    "tags": [
      "Workflows v1"
    ],
    "approvalRequired": false,
    "parameters": []
  },
  {
    "id": "get-_api_v1_workflows_events",
    "method": "get",
    "path": "/api/v1/workflows/events",
    "displayName": "List workflow events (route inventory only)",
    "summary": "List workflow events (route inventory only)",
    "description": "This operation is currently present only in generated route inventory. No corresponding Next.js handler exists under server/src/app/api/v1/workflows in this worktree. Runtime behavior is middleware-dependent: missing/invalid x-api-key can return 401 before routing; with middleware requirements satisfied, Next.js returns not-found for the absent handler. Existing workflow APIs in this codebase are implemented under /api/workflow-definitions, /api/workflow-runs, and /api/workflow/events rather than /api/v1/workflows paths.",
    "tags": [
      "Workflows v1"
    ],
    "approvalRequired": false,
    "parameters": []
  },
  {
    "id": "post-_api_v1_workflows_events",
    "method": "post",
    "path": "/api/v1/workflows/events",
    "displayName": "Create workflow event (route inventory only)",
    "summary": "Create workflow event (route inventory only)",
    "description": "This operation is currently present only in generated route inventory. No corresponding Next.js handler exists under server/src/app/api/v1/workflows in this worktree. Runtime behavior is middleware-dependent: missing/invalid x-api-key can return 401 before routing; with middleware requirements satisfied, Next.js returns not-found for the absent handler. Existing workflow APIs in this codebase are implemented under /api/workflow-definitions, /api/workflow-runs, and /api/workflow/events rather than /api/v1/workflows paths.",
    "tags": [
      "Workflows v1"
    ],
    "approvalRequired": false,
    "parameters": []
  },
  {
    "id": "get-_api_v1_workflows_events_id",
    "method": "get",
    "path": "/api/v1/workflows/events/{id}",
    "displayName": "Get workflow event by id (route inventory only)",
    "summary": "Get workflow event by id (route inventory only)",
    "description": "This operation is currently present only in generated route inventory. No corresponding Next.js handler exists under server/src/app/api/v1/workflows in this worktree. Runtime behavior is middleware-dependent: missing/invalid x-api-key can return 401 before routing; with middleware requirements satisfied, Next.js returns not-found for the absent handler. Existing workflow APIs in this codebase are implemented under /api/workflow-definitions, /api/workflow-runs, and /api/workflow/events rather than /api/v1/workflows paths.",
    "tags": [
      "Workflows v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Resource identifier.",
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      }
    ]
  },
  {
    "id": "get-_api_v1_workflows_executions",
    "method": "get",
    "path": "/api/v1/workflows/executions",
    "displayName": "List workflow executions (route inventory only)",
    "summary": "List workflow executions (route inventory only)",
    "description": "This operation is currently present only in generated route inventory. No corresponding Next.js handler exists under server/src/app/api/v1/workflows in this worktree. Runtime behavior is middleware-dependent: missing/invalid x-api-key can return 401 before routing; with middleware requirements satisfied, Next.js returns not-found for the absent handler. Existing workflow APIs in this codebase are implemented under /api/workflow-definitions, /api/workflow-runs, and /api/workflow/events rather than /api/v1/workflows paths.",
    "tags": [
      "Workflows v1"
    ],
    "approvalRequired": false,
    "parameters": []
  },
  {
    "id": "post-_api_v1_workflows_executions",
    "method": "post",
    "path": "/api/v1/workflows/executions",
    "displayName": "Create workflow execution (route inventory only)",
    "summary": "Create workflow execution (route inventory only)",
    "description": "This operation is currently present only in generated route inventory. No corresponding Next.js handler exists under server/src/app/api/v1/workflows in this worktree. Runtime behavior is middleware-dependent: missing/invalid x-api-key can return 401 before routing; with middleware requirements satisfied, Next.js returns not-found for the absent handler. Existing workflow APIs in this codebase are implemented under /api/workflow-definitions, /api/workflow-runs, and /api/workflow/events rather than /api/v1/workflows paths.",
    "tags": [
      "Workflows v1"
    ],
    "approvalRequired": false,
    "parameters": []
  },
  {
    "id": "post-_api_v1_workflows_executions_bulk",
    "method": "post",
    "path": "/api/v1/workflows/executions/bulk",
    "displayName": "Bulk create workflow executions (route inventory only)",
    "summary": "Bulk create workflow executions (route inventory only)",
    "description": "This operation is currently present only in generated route inventory. No corresponding Next.js handler exists under server/src/app/api/v1/workflows in this worktree. Runtime behavior is middleware-dependent: missing/invalid x-api-key can return 401 before routing; with middleware requirements satisfied, Next.js returns not-found for the absent handler. Existing workflow APIs in this codebase are implemented under /api/workflow-definitions, /api/workflow-runs, and /api/workflow/events rather than /api/v1/workflows paths.",
    "tags": [
      "Workflows v1"
    ],
    "approvalRequired": false,
    "parameters": []
  },
  {
    "id": "post-_api_v1_workflows_executions_bulkaction",
    "method": "post",
    "path": "/api/v1/workflows/executions/bulk-action",
    "displayName": "Bulk action workflow executions (route inventory only)",
    "summary": "Bulk action workflow executions (route inventory only)",
    "description": "This operation is currently present only in generated route inventory. No corresponding Next.js handler exists under server/src/app/api/v1/workflows in this worktree. Runtime behavior is middleware-dependent: missing/invalid x-api-key can return 401 before routing; with middleware requirements satisfied, Next.js returns not-found for the absent handler. Existing workflow APIs in this codebase are implemented under /api/workflow-definitions, /api/workflow-runs, and /api/workflow/events rather than /api/v1/workflows paths.",
    "tags": [
      "Workflows v1"
    ],
    "approvalRequired": false,
    "parameters": []
  },
  {
    "id": "get-_api_v1_workflows_executions_id",
    "method": "get",
    "path": "/api/v1/workflows/executions/{id}",
    "displayName": "Get workflow execution by id (route inventory only)",
    "summary": "Get workflow execution by id (route inventory only)",
    "description": "This operation is currently present only in generated route inventory. No corresponding Next.js handler exists under server/src/app/api/v1/workflows in this worktree. Runtime behavior is middleware-dependent: missing/invalid x-api-key can return 401 before routing; with middleware requirements satisfied, Next.js returns not-found for the absent handler. Existing workflow APIs in this codebase are implemented under /api/workflow-definitions, /api/workflow-runs, and /api/workflow/events rather than /api/v1/workflows paths.",
    "tags": [
      "Workflows v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Resource identifier.",
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      }
    ]
  },
  {
    "id": "put-_api_v1_workflows_executions_id",
    "method": "put",
    "path": "/api/v1/workflows/executions/{id}",
    "displayName": "Update workflow execution (route inventory only)",
    "summary": "Update workflow execution (route inventory only)",
    "description": "This operation is currently present only in generated route inventory. No corresponding Next.js handler exists under server/src/app/api/v1/workflows in this worktree. Runtime behavior is middleware-dependent: missing/invalid x-api-key can return 401 before routing; with middleware requirements satisfied, Next.js returns not-found for the absent handler. Existing workflow APIs in this codebase are implemented under /api/workflow-definitions, /api/workflow-runs, and /api/workflow/events rather than /api/v1/workflows paths.",
    "tags": [
      "Workflows v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Resource identifier.",
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      }
    ]
  },
  {
    "id": "post-_api_v1_workflows_executions_id_cancel",
    "method": "post",
    "path": "/api/v1/workflows/executions/{id}/cancel",
    "displayName": "Cancel workflow execution (route inventory only)",
    "summary": "Cancel workflow execution (route inventory only)",
    "description": "This operation is currently present only in generated route inventory. No corresponding Next.js handler exists under server/src/app/api/v1/workflows in this worktree. Runtime behavior is middleware-dependent: missing/invalid x-api-key can return 401 before routing; with middleware requirements satisfied, Next.js returns not-found for the absent handler. Existing workflow APIs in this codebase are implemented under /api/workflow-definitions, /api/workflow-runs, and /api/workflow/events rather than /api/v1/workflows paths.",
    "tags": [
      "Workflows v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Resource identifier.",
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      }
    ]
  },
  {
    "id": "post-_api_v1_workflows_executions_id_pause",
    "method": "post",
    "path": "/api/v1/workflows/executions/{id}/pause",
    "displayName": "Pause workflow execution (route inventory only)",
    "summary": "Pause workflow execution (route inventory only)",
    "description": "This operation is currently present only in generated route inventory. No corresponding Next.js handler exists under server/src/app/api/v1/workflows in this worktree. Runtime behavior is middleware-dependent: missing/invalid x-api-key can return 401 before routing; with middleware requirements satisfied, Next.js returns not-found for the absent handler. Existing workflow APIs in this codebase are implemented under /api/workflow-definitions, /api/workflow-runs, and /api/workflow/events rather than /api/v1/workflows paths.",
    "tags": [
      "Workflows v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Resource identifier.",
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      }
    ]
  },
  {
    "id": "post-_api_v1_workflows_executions_id_restart",
    "method": "post",
    "path": "/api/v1/workflows/executions/{id}/restart",
    "displayName": "Restart workflow execution (route inventory only)",
    "summary": "Restart workflow execution (route inventory only)",
    "description": "This operation is currently present only in generated route inventory. No corresponding Next.js handler exists under server/src/app/api/v1/workflows in this worktree. Runtime behavior is middleware-dependent: missing/invalid x-api-key can return 401 before routing; with middleware requirements satisfied, Next.js returns not-found for the absent handler. Existing workflow APIs in this codebase are implemented under /api/workflow-definitions, /api/workflow-runs, and /api/workflow/events rather than /api/v1/workflows paths.",
    "tags": [
      "Workflows v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Resource identifier.",
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      }
    ]
  },
  {
    "id": "post-_api_v1_workflows_executions_id_resume",
    "method": "post",
    "path": "/api/v1/workflows/executions/{id}/resume",
    "displayName": "Resume workflow execution (route inventory only)",
    "summary": "Resume workflow execution (route inventory only)",
    "description": "This operation is currently present only in generated route inventory. No corresponding Next.js handler exists under server/src/app/api/v1/workflows in this worktree. Runtime behavior is middleware-dependent: missing/invalid x-api-key can return 401 before routing; with middleware requirements satisfied, Next.js returns not-found for the absent handler. Existing workflow APIs in this codebase are implemented under /api/workflow-definitions, /api/workflow-runs, and /api/workflow/events rather than /api/v1/workflows paths.",
    "tags": [
      "Workflows v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Resource identifier.",
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      }
    ]
  },
  {
    "id": "get-_api_v1_workflows_export",
    "method": "get",
    "path": "/api/v1/workflows/export",
    "displayName": "Export workflows (route inventory only)",
    "summary": "Export workflows (route inventory only)",
    "description": "This operation is currently present only in generated route inventory. No corresponding Next.js handler exists under server/src/app/api/v1/workflows in this worktree. Runtime behavior is middleware-dependent: missing/invalid x-api-key can return 401 before routing; with middleware requirements satisfied, Next.js returns not-found for the absent handler. Existing workflow APIs in this codebase are implemented under /api/workflow-definitions, /api/workflow-runs, and /api/workflow/events rather than /api/v1/workflows paths.",
    "tags": [
      "Workflows v1"
    ],
    "approvalRequired": false,
    "parameters": []
  },
  {
    "id": "post-_api_v1_workflows_import",
    "method": "post",
    "path": "/api/v1/workflows/import",
    "displayName": "Import workflows (route inventory only)",
    "summary": "Import workflows (route inventory only)",
    "description": "This operation is currently present only in generated route inventory. No corresponding Next.js handler exists under server/src/app/api/v1/workflows in this worktree. Runtime behavior is middleware-dependent: missing/invalid x-api-key can return 401 before routing; with middleware requirements satisfied, Next.js returns not-found for the absent handler. Existing workflow APIs in this codebase are implemented under /api/workflow-definitions, /api/workflow-runs, and /api/workflow/events rather than /api/v1/workflows paths.",
    "tags": [
      "Workflows v1"
    ],
    "approvalRequired": false,
    "parameters": []
  },
  {
    "id": "get-_api_v1_workflows_search",
    "method": "get",
    "path": "/api/v1/workflows/search",
    "displayName": "Search workflows (route inventory only)",
    "summary": "Search workflows (route inventory only)",
    "description": "This operation is currently present only in generated route inventory. No corresponding Next.js handler exists under server/src/app/api/v1/workflows in this worktree. Runtime behavior is middleware-dependent: missing/invalid x-api-key can return 401 before routing; with middleware requirements satisfied, Next.js returns not-found for the absent handler. Existing workflow APIs in this codebase are implemented under /api/workflow-definitions, /api/workflow-runs, and /api/workflow/events rather than /api/v1/workflows paths.",
    "tags": [
      "Workflows v1"
    ],
    "approvalRequired": false,
    "parameters": []
  },
  {
    "id": "get-_api_v1_workflows_tasks",
    "method": "get",
    "path": "/api/v1/workflows/tasks",
    "displayName": "List workflow tasks (route inventory only)",
    "summary": "List workflow tasks (route inventory only)",
    "description": "This operation is currently present only in generated route inventory. No corresponding Next.js handler exists under server/src/app/api/v1/workflows in this worktree. Runtime behavior is middleware-dependent: missing/invalid x-api-key can return 401 before routing; with middleware requirements satisfied, Next.js returns not-found for the absent handler. Existing workflow APIs in this codebase are implemented under /api/workflow-definitions, /api/workflow-runs, and /api/workflow/events rather than /api/v1/workflows paths.",
    "tags": [
      "Workflows v1"
    ],
    "approvalRequired": false,
    "parameters": []
  },
  {
    "id": "post-_api_v1_workflows_tasks",
    "method": "post",
    "path": "/api/v1/workflows/tasks",
    "displayName": "Create workflow task (route inventory only)",
    "summary": "Create workflow task (route inventory only)",
    "description": "This operation is currently present only in generated route inventory. No corresponding Next.js handler exists under server/src/app/api/v1/workflows in this worktree. Runtime behavior is middleware-dependent: missing/invalid x-api-key can return 401 before routing; with middleware requirements satisfied, Next.js returns not-found for the absent handler. Existing workflow APIs in this codebase are implemented under /api/workflow-definitions, /api/workflow-runs, and /api/workflow/events rather than /api/v1/workflows paths.",
    "tags": [
      "Workflows v1"
    ],
    "approvalRequired": false,
    "parameters": []
  },
  {
    "id": "post-_api_v1_workflows_tasks_bulkassign",
    "method": "post",
    "path": "/api/v1/workflows/tasks/bulk-assign",
    "displayName": "Bulk assign workflow tasks (route inventory only)",
    "summary": "Bulk assign workflow tasks (route inventory only)",
    "description": "This operation is currently present only in generated route inventory. No corresponding Next.js handler exists under server/src/app/api/v1/workflows in this worktree. Runtime behavior is middleware-dependent: missing/invalid x-api-key can return 401 before routing; with middleware requirements satisfied, Next.js returns not-found for the absent handler. Existing workflow APIs in this codebase are implemented under /api/workflow-definitions, /api/workflow-runs, and /api/workflow/events rather than /api/v1/workflows paths.",
    "tags": [
      "Workflows v1"
    ],
    "approvalRequired": false,
    "parameters": []
  },
  {
    "id": "get-_api_v1_workflows_tasks_id",
    "method": "get",
    "path": "/api/v1/workflows/tasks/{id}",
    "displayName": "Get workflow task by id (route inventory only)",
    "summary": "Get workflow task by id (route inventory only)",
    "description": "This operation is currently present only in generated route inventory. No corresponding Next.js handler exists under server/src/app/api/v1/workflows in this worktree. Runtime behavior is middleware-dependent: missing/invalid x-api-key can return 401 before routing; with middleware requirements satisfied, Next.js returns not-found for the absent handler. Existing workflow APIs in this codebase are implemented under /api/workflow-definitions, /api/workflow-runs, and /api/workflow/events rather than /api/v1/workflows paths.",
    "tags": [
      "Workflows v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Resource identifier.",
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      }
    ]
  },
  {
    "id": "put-_api_v1_workflows_tasks_id",
    "method": "put",
    "path": "/api/v1/workflows/tasks/{id}",
    "displayName": "Update workflow task (route inventory only)",
    "summary": "Update workflow task (route inventory only)",
    "description": "This operation is currently present only in generated route inventory. No corresponding Next.js handler exists under server/src/app/api/v1/workflows in this worktree. Runtime behavior is middleware-dependent: missing/invalid x-api-key can return 401 before routing; with middleware requirements satisfied, Next.js returns not-found for the absent handler. Existing workflow APIs in this codebase are implemented under /api/workflow-definitions, /api/workflow-runs, and /api/workflow/events rather than /api/v1/workflows paths.",
    "tags": [
      "Workflows v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Resource identifier.",
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      }
    ]
  },
  {
    "id": "post-_api_v1_workflows_tasks_id_claim",
    "method": "post",
    "path": "/api/v1/workflows/tasks/{id}/claim",
    "displayName": "Claim workflow task (route inventory only)",
    "summary": "Claim workflow task (route inventory only)",
    "description": "This operation is currently present only in generated route inventory. No corresponding Next.js handler exists under server/src/app/api/v1/workflows in this worktree. Runtime behavior is middleware-dependent: missing/invalid x-api-key can return 401 before routing; with middleware requirements satisfied, Next.js returns not-found for the absent handler. Existing workflow APIs in this codebase are implemented under /api/workflow-definitions, /api/workflow-runs, and /api/workflow/events rather than /api/v1/workflows paths.",
    "tags": [
      "Workflows v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Resource identifier.",
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      }
    ]
  },
  {
    "id": "post-_api_v1_workflows_tasks_id_complete",
    "method": "post",
    "path": "/api/v1/workflows/tasks/{id}/complete",
    "displayName": "Complete workflow task (route inventory only)",
    "summary": "Complete workflow task (route inventory only)",
    "description": "This operation is currently present only in generated route inventory. No corresponding Next.js handler exists under server/src/app/api/v1/workflows in this worktree. Runtime behavior is middleware-dependent: missing/invalid x-api-key can return 401 before routing; with middleware requirements satisfied, Next.js returns not-found for the absent handler. Existing workflow APIs in this codebase are implemented under /api/workflow-definitions, /api/workflow-runs, and /api/workflow/events rather than /api/v1/workflows paths.",
    "tags": [
      "Workflows v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Resource identifier.",
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      }
    ]
  },
  {
    "id": "get-_api_v1_workflows_templates",
    "method": "get",
    "path": "/api/v1/workflows/templates",
    "displayName": "List workflow templates (route inventory only)",
    "summary": "List workflow templates (route inventory only)",
    "description": "This operation is currently present only in generated route inventory. No corresponding Next.js handler exists under server/src/app/api/v1/workflows in this worktree. Runtime behavior is middleware-dependent: missing/invalid x-api-key can return 401 before routing; with middleware requirements satisfied, Next.js returns not-found for the absent handler. Existing workflow APIs in this codebase are implemented under /api/workflow-definitions, /api/workflow-runs, and /api/workflow/events rather than /api/v1/workflows paths.",
    "tags": [
      "Workflows v1"
    ],
    "approvalRequired": false,
    "parameters": []
  },
  {
    "id": "post-_api_v1_workflows_templates",
    "method": "post",
    "path": "/api/v1/workflows/templates",
    "displayName": "Create workflow template (route inventory only)",
    "summary": "Create workflow template (route inventory only)",
    "description": "This operation is currently present only in generated route inventory. No corresponding Next.js handler exists under server/src/app/api/v1/workflows in this worktree. Runtime behavior is middleware-dependent: missing/invalid x-api-key can return 401 before routing; with middleware requirements satisfied, Next.js returns not-found for the absent handler. Existing workflow APIs in this codebase are implemented under /api/workflow-definitions, /api/workflow-runs, and /api/workflow/events rather than /api/v1/workflows paths.",
    "tags": [
      "Workflows v1"
    ],
    "approvalRequired": false,
    "parameters": []
  },
  {
    "id": "get-_api_v1_workflows_templates_id",
    "method": "get",
    "path": "/api/v1/workflows/templates/{id}",
    "displayName": "Get workflow template by id (route inventory only)",
    "summary": "Get workflow template by id (route inventory only)",
    "description": "This operation is currently present only in generated route inventory. No corresponding Next.js handler exists under server/src/app/api/v1/workflows in this worktree. Runtime behavior is middleware-dependent: missing/invalid x-api-key can return 401 before routing; with middleware requirements satisfied, Next.js returns not-found for the absent handler. Existing workflow APIs in this codebase are implemented under /api/workflow-definitions, /api/workflow-runs, and /api/workflow/events rather than /api/v1/workflows paths.",
    "tags": [
      "Workflows v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Resource identifier.",
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      }
    ]
  },
  {
    "id": "put-_api_v1_workflows_templates_id",
    "method": "put",
    "path": "/api/v1/workflows/templates/{id}",
    "displayName": "Update workflow template (route inventory only)",
    "summary": "Update workflow template (route inventory only)",
    "description": "This operation is currently present only in generated route inventory. No corresponding Next.js handler exists under server/src/app/api/v1/workflows in this worktree. Runtime behavior is middleware-dependent: missing/invalid x-api-key can return 401 before routing; with middleware requirements satisfied, Next.js returns not-found for the absent handler. Existing workflow APIs in this codebase are implemented under /api/workflow-definitions, /api/workflow-runs, and /api/workflow/events rather than /api/v1/workflows paths.",
    "tags": [
      "Workflows v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Resource identifier.",
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      }
    ]
  },
  {
    "id": "delete-_api_v1_workflows_templates_id",
    "method": "delete",
    "path": "/api/v1/workflows/templates/{id}",
    "displayName": "Delete workflow template (route inventory only)",
    "summary": "Delete workflow template (route inventory only)",
    "description": "This operation is currently present only in generated route inventory. No corresponding Next.js handler exists under server/src/app/api/v1/workflows in this worktree. Runtime behavior is middleware-dependent: missing/invalid x-api-key can return 401 before routing; with middleware requirements satisfied, Next.js returns not-found for the absent handler. Existing workflow APIs in this codebase are implemented under /api/workflow-definitions, /api/workflow-runs, and /api/workflow/events rather than /api/v1/workflows paths.",
    "tags": [
      "Workflows v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Resource identifier.",
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      }
    ]
  },
  {
    "id": "get-_api_v1_workflows_id",
    "method": "get",
    "path": "/api/v1/workflows/{id}",
    "displayName": "Get workflow by id (route inventory only)",
    "summary": "Get workflow by id (route inventory only)",
    "description": "This operation is currently present only in generated route inventory. No corresponding Next.js handler exists under server/src/app/api/v1/workflows in this worktree. Runtime behavior is middleware-dependent: missing/invalid x-api-key can return 401 before routing; with middleware requirements satisfied, Next.js returns not-found for the absent handler. Existing workflow APIs in this codebase are implemented under /api/workflow-definitions, /api/workflow-runs, and /api/workflow/events rather than /api/v1/workflows paths.",
    "tags": [
      "Workflows v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Resource identifier.",
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      }
    ]
  },
  {
    "id": "put-_api_v1_workflows_id",
    "method": "put",
    "path": "/api/v1/workflows/{id}",
    "displayName": "Update workflow (route inventory only)",
    "summary": "Update workflow (route inventory only)",
    "description": "This operation is currently present only in generated route inventory. No corresponding Next.js handler exists under server/src/app/api/v1/workflows in this worktree. Runtime behavior is middleware-dependent: missing/invalid x-api-key can return 401 before routing; with middleware requirements satisfied, Next.js returns not-found for the absent handler. Existing workflow APIs in this codebase are implemented under /api/workflow-definitions, /api/workflow-runs, and /api/workflow/events rather than /api/v1/workflows paths.",
    "tags": [
      "Workflows v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Resource identifier.",
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      }
    ]
  },
  {
    "id": "delete-_api_v1_workflows_id",
    "method": "delete",
    "path": "/api/v1/workflows/{id}",
    "displayName": "Delete workflow by id (route inventory only)",
    "summary": "Delete workflow by id (route inventory only)",
    "description": "This operation is currently present only in generated route inventory. No corresponding Next.js handler exists under server/src/app/api/v1/workflows in this worktree. Runtime behavior is middleware-dependent: missing/invalid x-api-key can return 401 before routing; with middleware requirements satisfied, Next.js returns not-found for the absent handler. Existing workflow APIs in this codebase are implemented under /api/workflow-definitions, /api/workflow-runs, and /api/workflow/events rather than /api/v1/workflows paths.",
    "tags": [
      "Workflows v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Resource identifier.",
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      }
    ]
  },
  {
    "id": "get-_api_v1_projects_id_taskstatusmappings",
    "method": "get",
    "path": "/api/v1/projects/{id}/task-status-mappings",
    "displayName": "List project task status mappings",
    "summary": "List project task status mappings",
    "description": "Returns the task status mappings configured for the specified project. Use this endpoint to translate a human-readable status label such as \"In Progress\" into a project_status_mapping_id UUID before updating a task.",
    "tags": [
      "Projects"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Project UUID.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Project UUID."
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "type": "array",
          "items": {
            "$ref": "#/components/schemas/ProjectTaskStatusMappingApiResponse"
          }
        }
      },
      "required": [
        "data"
      ]
    },
    "playbooks": [
      "Call this before updating a project task when the user names a status like \"In Progress\" instead of providing a project_status_mapping_id.",
      "Match against custom_name, status_name, or name, then use the returned project_status_mapping_id UUID in PUT /api/v1/projects/tasks/{taskId}."
    ],
    "examples": [
      {
        "name": "List task statuses for the active project",
        "request": {
          "params": {
            "id": "11111111-1111-1111-1111-111111111111"
          }
        },
        "notes": "Use the returned mappings to resolve the user’s requested status label to a project_status_mapping_id."
      }
    ]
  },
  {
    "id": "get-_api_v1_projects_id_tasks",
    "method": "get",
    "path": "/api/v1/projects/{id}/tasks",
    "displayName": "List project tasks",
    "summary": "List project tasks",
    "description": "Returns all tasks for the specified project UUID. Use this endpoint to identify a task by task_name before fetching or updating it.",
    "tags": [
      "Projects"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Project UUID.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Project UUID."
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "type": "array",
          "items": {
            "$ref": "#/components/schemas/ProjectTaskApiResponse"
          }
        }
      },
      "required": [
        "data"
      ]
    },
    "playbooks": [
      "When the user says \"this project\" and the current app context includes an active project record, use that project UUID for {id}.",
      "Use this endpoint to find the target task by task_name within a known project before calling the single-task or update endpoint."
    ],
    "examples": [
      {
        "name": "List tasks for the active project",
        "request": {
          "params": {
            "id": "11111111-1111-1111-1111-111111111111"
          }
        },
        "notes": "Use the active project UUID from app context when the user refers to \"this project\"."
      }
    ]
  },
  {
    "id": "get-_api_v1_projects_id_phases_phaseid_tasks",
    "method": "get",
    "path": "/api/v1/projects/{id}/phases/{phaseId}/tasks",
    "displayName": "List project phase tasks",
    "summary": "List project phase tasks",
    "description": "Returns all tasks for the specified project phase. Both id and phaseId must be UUID path parameters.",
    "tags": [
      "Projects"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Project UUID.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Project UUID."
        }
      },
      {
        "name": "phaseId",
        "in": "path",
        "required": true,
        "description": "Project phase UUID.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Project phase UUID."
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "type": "array",
          "items": {
            "$ref": "#/components/schemas/ProjectTaskApiResponse"
          }
        }
      },
      "required": [
        "data"
      ]
    },
    "playbooks": [
      "Call this only when you already know both the project UUID and phase UUID.",
      "Do not send placeholder strings for id or phaseId. Both path parameters must be UUIDs."
    ]
  },
  {
    "id": "post-_api_v1_projects_id_phases_phaseid_tasks",
    "method": "post",
    "path": "/api/v1/projects/{id}/phases/{phaseId}/tasks",
    "displayName": "Create project phase task",
    "summary": "Create project phase task",
    "description": "Creates a new task in the specified project phase. Resolve phaseId from the project phases and project_status_mapping_id from the project task status mappings before calling this endpoint.",
    "tags": [
      "Projects"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Project UUID.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Project UUID."
        }
      },
      {
        "name": "phaseId",
        "in": "path",
        "required": true,
        "description": "Project phase UUID.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Project phase UUID."
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "task_name": {
          "type": "string",
          "minLength": 1,
          "maxLength": 255
        },
        "description": {
          "type": "string"
        },
        "assigned_to": {
          "type": "string",
          "format": "uuid"
        },
        "estimated_hours": {
          "type": "number",
          "minimum": 0
        },
        "due_date": {
          "type": "string",
          "format": "date-time"
        },
        "priority_id": {
          "type": "string",
          "format": "uuid"
        },
        "task_type_key": {
          "type": "string",
          "default": "general"
        },
        "project_status_mapping_id": {
          "type": "string",
          "format": "uuid"
        },
        "wbs_code": {
          "type": "string"
        },
        "tags": {
          "type": "array",
          "items": {
            "type": "string"
          }
        }
      },
      "required": [
        "task_name",
        "project_status_mapping_id"
      ],
      "description": "Payload for creating a project task within a phase. Provide project_status_mapping_id as a UUID from the project task status mappings endpoint. The phaseId path parameter selects which phase will receive the task."
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "$ref": "#/components/schemas/ProjectTaskApiResponse"
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_projects_tasks_taskid",
    "method": "get",
    "path": "/api/v1/projects/tasks/{taskId}",
    "displayName": "Get project task",
    "summary": "Get project task",
    "description": "Returns a single project task by its task UUID.",
    "tags": [
      "Projects"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "taskId",
        "in": "path",
        "required": true,
        "description": "Project task UUID.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Project task UUID."
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "$ref": "#/components/schemas/ProjectTaskApiResponse"
        }
      },
      "required": [
        "data"
      ]
    },
    "playbooks": [
      "Use this endpoint only after you have already identified the concrete taskId UUID.",
      "Do not call it with a task name or an unresolved {taskId} placeholder."
    ],
    "examples": [
      {
        "name": "Fetch one project task",
        "request": {
          "params": {
            "taskId": "22222222-2222-2222-2222-222222222222"
          }
        },
        "notes": "The taskId path parameter must be a UUID from a prior API response or active UI context."
      }
    ]
  },
  {
    "id": "put-_api_v1_projects_tasks_taskid",
    "method": "put",
    "path": "/api/v1/projects/tasks/{taskId}",
    "displayName": "Update project task",
    "summary": "Update project task",
    "description": "Updates a project task by task UUID. Use project_status_mapping_id when changing task status, and only send fields defined in the request schema.",
    "tags": [
      "Projects"
    ],
    "approvalRequired": true,
    "parameters": [
      {
        "name": "taskId",
        "in": "path",
        "required": true,
        "description": "Project task UUID.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Project task UUID."
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "task_name": {
          "type": "string",
          "minLength": 1,
          "maxLength": 255
        },
        "description": {
          "type": "string"
        },
        "assigned_to": {
          "type": "string",
          "format": "uuid"
        },
        "estimated_hours": {
          "type": "number",
          "minimum": 0
        },
        "due_date": {
          "type": "string",
          "format": "date-time"
        },
        "priority_id": {
          "type": "string",
          "format": "uuid"
        },
        "task_type_key": {
          "type": "string",
          "default": "general"
        },
        "project_status_mapping_id": {
          "type": "string",
          "format": "uuid"
        },
        "wbs_code": {
          "type": "string"
        },
        "tags": {
          "type": "array",
          "items": {
            "type": "string"
          }
        }
      },
      "description": "Payload for updating a project task. To change task status, send project_status_mapping_id as a UUID. This endpoint does not accept project_id, phase_id, or human-readable status names."
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "$ref": "#/components/schemas/ProjectTaskApiResponse"
        }
      },
      "required": [
        "data"
      ]
    },
    "playbooks": [
      "If the user specifies a status label instead of a UUID, first call GET /api/v1/projects/{id}/task-status-mappings to resolve the correct project_status_mapping_id for that project.",
      "To change task status, send project_status_mapping_id as a UUID. Do not send a plain status label like \"In Progress\" in the request body.",
      "This public API does not accept project_id or phase_id in the update payload, so do not use it for moving a task to a different project or phase."
    ],
    "examples": [
      {
        "name": "Update a project task status mapping",
        "request": {
          "params": {
            "taskId": "22222222-2222-2222-2222-222222222222"
          },
          "body": {
            "project_status_mapping_id": "33333333-3333-3333-3333-333333333333"
          }
        },
        "notes": "Only use a concrete project_status_mapping_id UUID that you already obtained from authoritative context."
      }
    ]
  },
  {
    "id": "delete-_api_v1_projects_tasks_taskid",
    "method": "delete",
    "path": "/api/v1/projects/tasks/{taskId}",
    "displayName": "Delete project task",
    "summary": "Delete project task",
    "description": "Permanently deletes a project task by task UUID. The controller resolves the task's parent project through project_tasks.phase_id and project_phases.project_id, checks project:delete permission, and verifies row-level read access to that project before deleting the task. Returns 204 No Content on success.",
    "tags": [
      "Projects"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "taskId",
        "in": "path",
        "required": true,
        "description": "Project task UUID.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Project task UUID."
        }
      }
    ]
  },
  {
    "id": "get-_api_v1_projects",
    "method": "get",
    "path": "/api/v1/projects",
    "displayName": "List projects",
    "summary": "List projects",
    "description": "Lists projects using ApiProjectController.list() with authorization-aware pagination.",
    "tags": [
      "Work Management v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "page",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "limit",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "sort",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "order",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "asc",
            "desc"
          ]
        }
      },
      {
        "name": "fields",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "search",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "query",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "type": "array",
          "items": {
            "type": "object",
            "additionalProperties": {}
          }
        },
        "pagination": {
          "type": "object",
          "properties": {
            "page": {
              "type": "integer"
            },
            "limit": {
              "type": "integer"
            },
            "total": {
              "type": "integer"
            },
            "totalPages": {
              "type": "integer"
            },
            "hasNext": {
              "type": "boolean"
            },
            "hasPrev": {
              "type": "boolean"
            }
          },
          "required": [
            "page",
            "limit",
            "total",
            "totalPages",
            "hasNext",
            "hasPrev"
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data",
        "pagination"
      ]
    },
    "playbooks": [
      "projects/list-basic"
    ],
    "examples": [
      {
        "name": "List active projects",
        "request": {
          "query": {
            "is_inactive": false,
            "limit": 10
          }
        },
        "notes": "Returns the first 10 active projects ordered by creation date."
      }
    ]
  },
  {
    "id": "post-_api_v1_projects",
    "method": "post",
    "path": "/api/v1/projects",
    "displayName": "Create project",
    "summary": "Create project",
    "description": "Creates a project via ApiProjectController.create().",
    "tags": [
      "Work Management v1"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "project_name": {
          "type": "string"
        },
        "status": {
          "type": "string"
        },
        "start_date": {
          "type": "string"
        },
        "end_date": {
          "type": "string"
        },
        "assigned_to": {
          "type": "string",
          "format": "uuid"
        },
        "assigned_team_id": {
          "type": "string",
          "format": "uuid"
        },
        "client_id": {
          "type": "string",
          "format": "uuid"
        }
      },
      "required": [
        "project_name"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "put-_api_v1_projects_bulkassign",
    "method": "put",
    "path": "/api/v1/projects/bulk-assign",
    "displayName": "Bulk assign projects",
    "summary": "Bulk assign projects",
    "description": "Bulk assignment operation via ApiProjectController.bulkAssign().",
    "tags": [
      "Work Management v1"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "additionalProperties": {},
      "description": "Controller/service-specific payload; see source route/controller for exact required shape."
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "put-_api_v1_projects_bulkstatus",
    "method": "put",
    "path": "/api/v1/projects/bulk-status",
    "displayName": "Bulk update project status",
    "summary": "Bulk update project status",
    "description": "Bulk status update operation via ApiProjectController.bulkStatusUpdate().",
    "tags": [
      "Work Management v1"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "additionalProperties": {},
      "description": "Controller/service-specific payload; see source route/controller for exact required shape."
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "put-_api_v1_projects_bulkupdate",
    "method": "put",
    "path": "/api/v1/projects/bulk-update",
    "displayName": "Bulk update projects",
    "summary": "Bulk update projects",
    "description": "Bulk update operation via ApiProjectController.bulkUpdate().",
    "tags": [
      "Work Management v1"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "additionalProperties": {},
      "description": "Controller/service-specific payload; see source route/controller for exact required shape."
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_projects_export",
    "method": "get",
    "path": "/api/v1/projects/export",
    "displayName": "Export projects",
    "summary": "Export projects",
    "description": "Exports projects via ApiProjectController.export().",
    "tags": [
      "Work Management v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "page",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "limit",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "sort",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "order",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "asc",
            "desc"
          ]
        }
      },
      {
        "name": "fields",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "search",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "query",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "type": "array",
          "items": {
            "type": "object",
            "additionalProperties": {}
          }
        },
        "pagination": {
          "type": "object",
          "properties": {
            "page": {
              "type": "integer"
            },
            "limit": {
              "type": "integer"
            },
            "total": {
              "type": "integer"
            },
            "totalPages": {
              "type": "integer"
            },
            "hasNext": {
              "type": "boolean"
            },
            "hasPrev": {
              "type": "boolean"
            }
          },
          "required": [
            "page",
            "limit",
            "total",
            "totalPages",
            "hasNext",
            "hasPrev"
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data",
        "pagination"
      ]
    }
  },
  {
    "id": "get-_api_v1_projects_search",
    "method": "get",
    "path": "/api/v1/projects/search",
    "displayName": "Search projects",
    "summary": "Search projects",
    "description": "Searches projects via ApiProjectController.search().",
    "tags": [
      "Work Management v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "page",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "limit",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "sort",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "order",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "asc",
            "desc"
          ]
        }
      },
      {
        "name": "fields",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "search",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "query",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "type": "array",
          "items": {
            "type": "object",
            "additionalProperties": {}
          }
        },
        "pagination": {
          "type": "object",
          "properties": {
            "page": {
              "type": "integer"
            },
            "limit": {
              "type": "integer"
            },
            "total": {
              "type": "integer"
            },
            "totalPages": {
              "type": "integer"
            },
            "hasNext": {
              "type": "boolean"
            },
            "hasPrev": {
              "type": "boolean"
            }
          },
          "required": [
            "page",
            "limit",
            "total",
            "totalPages",
            "hasNext",
            "hasPrev"
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data",
        "pagination"
      ]
    }
  },
  {
    "id": "get-_api_v1_projects_stats",
    "method": "get",
    "path": "/api/v1/projects/stats",
    "displayName": "Get project stats",
    "summary": "Get project stats",
    "description": "Returns project aggregate statistics for authorized projects.",
    "tags": [
      "Work Management v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "page",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "limit",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "sort",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "order",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "asc",
            "desc"
          ]
        }
      },
      {
        "name": "fields",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "search",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "query",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "type": "array",
          "items": {
            "type": "object",
            "additionalProperties": {}
          }
        },
        "pagination": {
          "type": "object",
          "properties": {
            "page": {
              "type": "integer"
            },
            "limit": {
              "type": "integer"
            },
            "total": {
              "type": "integer"
            },
            "totalPages": {
              "type": "integer"
            },
            "hasNext": {
              "type": "boolean"
            },
            "hasPrev": {
              "type": "boolean"
            }
          },
          "required": [
            "page",
            "limit",
            "total",
            "totalPages",
            "hasNext",
            "hasPrev"
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data",
        "pagination"
      ]
    }
  },
  {
    "id": "get-_api_v1_projects_tasks_taskid_checklist",
    "method": "get",
    "path": "/api/v1/projects/tasks/{taskId}/checklist",
    "displayName": "List task checklist items",
    "summary": "List task checklist items",
    "description": "Reads checklist items for project task UUID through ApiProjectController.getTaskChecklist().",
    "tags": [
      "Work Management v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "taskId",
        "in": "path",
        "required": true,
        "description": "Project task UUID from project_tasks.task_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Project task UUID from project_tasks.task_id."
        }
      },
      {
        "name": "page",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "limit",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "sort",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "order",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "asc",
            "desc"
          ]
        }
      },
      {
        "name": "fields",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "search",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "query",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "type": "array",
          "items": {
            "type": "object",
            "additionalProperties": {}
          }
        },
        "pagination": {
          "type": "object",
          "properties": {
            "page": {
              "type": "integer"
            },
            "limit": {
              "type": "integer"
            },
            "total": {
              "type": "integer"
            },
            "totalPages": {
              "type": "integer"
            },
            "hasNext": {
              "type": "boolean"
            },
            "hasPrev": {
              "type": "boolean"
            }
          },
          "required": [
            "page",
            "limit",
            "total",
            "totalPages",
            "hasNext",
            "hasPrev"
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data",
        "pagination"
      ]
    }
  },
  {
    "id": "post-_api_v1_projects_tasks_taskid_checklist",
    "method": "post",
    "path": "/api/v1/projects/tasks/{taskId}/checklist",
    "displayName": "Create task checklist item",
    "summary": "Create task checklist item",
    "description": "Creates checklist item for project task UUID via ApiProjectController.createChecklistItem().",
    "tags": [
      "Work Management v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "taskId",
        "in": "path",
        "required": true,
        "description": "Project task UUID from project_tasks.task_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Project task UUID from project_tasks.task_id."
        }
      },
      {
        "name": "page",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "limit",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "sort",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "order",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "asc",
            "desc"
          ]
        }
      },
      {
        "name": "fields",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "search",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "query",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "additionalProperties": {},
      "description": "Controller/service-specific payload; see source route/controller for exact required shape."
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_projects_id",
    "method": "get",
    "path": "/api/v1/projects/{id}",
    "displayName": "Get project",
    "summary": "Get project",
    "description": "Returns one project by project UUID.",
    "tags": [
      "Work Management v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "UUID path identifier from underlying resource tables.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "UUID path identifier from underlying resource tables."
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "put-_api_v1_projects_id",
    "method": "put",
    "path": "/api/v1/projects/{id}",
    "displayName": "Update project",
    "summary": "Update project",
    "description": "Updates project by project UUID.",
    "tags": [
      "Work Management v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "UUID path identifier from underlying resource tables.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "UUID path identifier from underlying resource tables."
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "additionalProperties": {},
      "description": "Controller/service-specific payload; see source route/controller for exact required shape."
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "delete-_api_v1_projects_id",
    "method": "delete",
    "path": "/api/v1/projects/{id}",
    "displayName": "Delete project",
    "summary": "Delete project",
    "description": "Deletes project by project UUID.",
    "tags": [
      "Work Management v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "UUID path identifier from underlying resource tables.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "UUID path identifier from underlying resource tables."
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_projects_id_phases",
    "method": "get",
    "path": "/api/v1/projects/{id}/phases",
    "displayName": "List project phases",
    "summary": "List project phases",
    "description": "Lists phases for project UUID.",
    "tags": [
      "Work Management v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "UUID path identifier from underlying resource tables.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "UUID path identifier from underlying resource tables."
        }
      },
      {
        "name": "page",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "limit",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "sort",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "order",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "asc",
            "desc"
          ]
        }
      },
      {
        "name": "fields",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "search",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "query",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "type": "array",
          "items": {
            "type": "object",
            "additionalProperties": {}
          }
        },
        "pagination": {
          "type": "object",
          "properties": {
            "page": {
              "type": "integer"
            },
            "limit": {
              "type": "integer"
            },
            "total": {
              "type": "integer"
            },
            "totalPages": {
              "type": "integer"
            },
            "hasNext": {
              "type": "boolean"
            },
            "hasPrev": {
              "type": "boolean"
            }
          },
          "required": [
            "page",
            "limit",
            "total",
            "totalPages",
            "hasNext",
            "hasPrev"
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data",
        "pagination"
      ]
    }
  },
  {
    "id": "post-_api_v1_projects_id_phases",
    "method": "post",
    "path": "/api/v1/projects/{id}/phases",
    "displayName": "Create project phase",
    "summary": "Create project phase",
    "description": "Creates a project phase under project UUID.",
    "tags": [
      "Work Management v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "UUID path identifier from underlying resource tables.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "UUID path identifier from underlying resource tables."
        }
      },
      {
        "name": "page",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "limit",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "sort",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "order",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "asc",
            "desc"
          ]
        }
      },
      {
        "name": "fields",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "search",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "query",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "additionalProperties": {},
      "description": "Controller/service-specific payload; see source route/controller for exact required shape."
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "put-_api_v1_projects_id_phases_phaseid",
    "method": "put",
    "path": "/api/v1/projects/{id}/phases/{phaseId}",
    "displayName": "Update project phase",
    "summary": "Update project phase",
    "description": "Updates phase UUID under project UUID.",
    "tags": [
      "Work Management v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Project UUID from projects.project_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Project UUID from projects.project_id."
        }
      },
      {
        "name": "phaseId",
        "in": "path",
        "required": true,
        "description": "Project phase UUID from project_phases.phase_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Project phase UUID from project_phases.phase_id."
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "additionalProperties": {},
      "description": "Controller/service-specific payload; see source route/controller for exact required shape."
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "delete-_api_v1_projects_id_phases_phaseid",
    "method": "delete",
    "path": "/api/v1/projects/{id}/phases/{phaseId}",
    "displayName": "Delete project phase",
    "summary": "Delete project phase",
    "description": "Deletes phase UUID under project UUID.",
    "tags": [
      "Work Management v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Project UUID from projects.project_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Project UUID from projects.project_id."
        }
      },
      {
        "name": "phaseId",
        "in": "path",
        "required": true,
        "description": "Project phase UUID from project_phases.phase_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Project phase UUID from project_phases.phase_id."
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_projects_id_tickets",
    "method": "get",
    "path": "/api/v1/projects/{id}/tickets",
    "displayName": "List project tickets",
    "summary": "List project tickets",
    "description": "Lists tickets linked to project UUID.",
    "tags": [
      "Work Management v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "UUID path identifier from underlying resource tables.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "UUID path identifier from underlying resource tables."
        }
      },
      {
        "name": "page",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "limit",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "sort",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "order",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "asc",
            "desc"
          ]
        }
      },
      {
        "name": "fields",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "search",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "query",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "type": "array",
          "items": {
            "type": "object",
            "additionalProperties": {}
          }
        },
        "pagination": {
          "type": "object",
          "properties": {
            "page": {
              "type": "integer"
            },
            "limit": {
              "type": "integer"
            },
            "total": {
              "type": "integer"
            },
            "totalPages": {
              "type": "integer"
            },
            "hasNext": {
              "type": "boolean"
            },
            "hasPrev": {
              "type": "boolean"
            }
          },
          "required": [
            "page",
            "limit",
            "total",
            "totalPages",
            "hasNext",
            "hasPrev"
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data",
        "pagination"
      ]
    }
  },
  {
    "id": "get-_api_v1_schedules",
    "method": "get",
    "path": "/api/v1/schedules",
    "displayName": "List schedule entries",
    "summary": "List schedule entries",
    "description": "Lists schedule entries via ApiTimeSheetController.listScheduleEntries().",
    "tags": [
      "Work Management v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "page",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "limit",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "sort",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "order",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "asc",
            "desc"
          ]
        }
      },
      {
        "name": "fields",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "search",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "query",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "type": "array",
          "items": {
            "type": "object",
            "additionalProperties": {}
          }
        },
        "pagination": {
          "type": "object",
          "properties": {
            "page": {
              "type": "integer"
            },
            "limit": {
              "type": "integer"
            },
            "total": {
              "type": "integer"
            },
            "totalPages": {
              "type": "integer"
            },
            "hasNext": {
              "type": "boolean"
            },
            "hasPrev": {
              "type": "boolean"
            }
          },
          "required": [
            "page",
            "limit",
            "total",
            "totalPages",
            "hasNext",
            "hasPrev"
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data",
        "pagination"
      ]
    }
  },
  {
    "id": "post-_api_v1_schedules",
    "method": "post",
    "path": "/api/v1/schedules",
    "displayName": "Create schedule entry",
    "summary": "Create schedule entry",
    "description": "Creates schedule entry via ApiTimeSheetController.createScheduleEntry().",
    "tags": [
      "Work Management v1"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "additionalProperties": {},
      "description": "Controller/service-specific payload; see source route/controller for exact required shape."
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_schedules_search",
    "method": "get",
    "path": "/api/v1/schedules/search",
    "displayName": "Search schedules",
    "summary": "Search schedules",
    "description": "Current route delegates to ApiTimeSheetController.list() (time sheet list path), not schedule-specific search.",
    "tags": [
      "Work Management v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "page",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "limit",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "sort",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "order",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "asc",
            "desc"
          ]
        }
      },
      {
        "name": "fields",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "search",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "query",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "type": "array",
          "items": {
            "type": "object",
            "additionalProperties": {}
          }
        },
        "pagination": {
          "type": "object",
          "properties": {
            "page": {
              "type": "integer"
            },
            "limit": {
              "type": "integer"
            },
            "total": {
              "type": "integer"
            },
            "totalPages": {
              "type": "integer"
            },
            "hasNext": {
              "type": "boolean"
            },
            "hasPrev": {
              "type": "boolean"
            }
          },
          "required": [
            "page",
            "limit",
            "total",
            "totalPages",
            "hasNext",
            "hasPrev"
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data",
        "pagination"
      ]
    }
  },
  {
    "id": "get-_api_v1_schedules_id",
    "method": "get",
    "path": "/api/v1/schedules/{id}",
    "displayName": "Get schedule entry",
    "summary": "Get schedule entry",
    "description": "Current route delegates to ApiTimeSheetController.getById() (time sheet read path), not schedule-specific getter.",
    "tags": [
      "Work Management v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "UUID path identifier from underlying resource tables.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "UUID path identifier from underlying resource tables."
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "put-_api_v1_schedules_id",
    "method": "put",
    "path": "/api/v1/schedules/{id}",
    "displayName": "Update schedule entry",
    "summary": "Update schedule entry",
    "description": "Updates schedule entry via ApiTimeSheetController.updateScheduleEntry().",
    "tags": [
      "Work Management v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "UUID path identifier from underlying resource tables.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "UUID path identifier from underlying resource tables."
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "additionalProperties": {},
      "description": "Controller/service-specific payload; see source route/controller for exact required shape."
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "delete-_api_v1_schedules_id",
    "method": "delete",
    "path": "/api/v1/schedules/{id}",
    "displayName": "Delete schedule entry",
    "summary": "Delete schedule entry",
    "description": "Deletes schedule entry via ApiTimeSheetController.deleteScheduleEntry().",
    "tags": [
      "Work Management v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "UUID path identifier from underlying resource tables.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "UUID path identifier from underlying resource tables."
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "additionalProperties": {},
      "description": "Controller/service-specific payload; see source route/controller for exact required shape."
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_schedules_id_conflicts",
    "method": "get",
    "path": "/api/v1/schedules/{id}/conflicts",
    "displayName": "Get schedule conflicts",
    "summary": "Get schedule conflicts",
    "description": "Current route delegates to ApiTimeSheetController.list() rather than conflict-specific schedule logic.",
    "tags": [
      "Work Management v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "UUID path identifier from underlying resource tables.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "UUID path identifier from underlying resource tables."
        }
      },
      {
        "name": "page",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "limit",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "sort",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "order",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "asc",
            "desc"
          ]
        }
      },
      {
        "name": "fields",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "search",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "query",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_tags",
    "method": "get",
    "path": "/api/v1/tags",
    "displayName": "List Tags",
    "summary": "Fetch tag catalog",
    "description": "Returns tags configured for the tenant. Reuse these when populating the tags array for a ticket.",
    "tags": [
      "Work Management v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "entity_type",
        "in": "query",
        "required": false,
        "description": "Limit results to tags used for a specific entity type (e.g., ticket).",
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "limit",
        "in": "query",
        "required": false,
        "description": "Number of tags per page (default 25, max 200).",
        "schema": {
          "type": "integer",
          "minimum": 1,
          "maximum": 200
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "type": "array",
          "items": {
            "type": "object",
            "additionalProperties": {}
          }
        },
        "pagination": {
          "type": "object",
          "properties": {
            "page": {
              "type": "integer"
            },
            "limit": {
              "type": "integer"
            },
            "total": {
              "type": "integer"
            },
            "totalPages": {
              "type": "integer"
            },
            "hasNext": {
              "type": "boolean"
            },
            "hasPrev": {
              "type": "boolean"
            }
          },
          "required": [
            "page",
            "limit",
            "total",
            "totalPages",
            "hasNext",
            "hasPrev"
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data",
        "pagination"
      ]
    },
    "examples": [
      {
        "name": "Retrieve ticket tags",
        "request": {
          "query": {
            "entity_type": "ticket",
            "limit": 25
          }
        },
        "notes": "Use existing tag names whenever possible rather than inventing new ones."
      }
    ]
  },
  {
    "id": "post-_api_v1_tags",
    "method": "post",
    "path": "/api/v1/tags",
    "displayName": "Create tag",
    "summary": "Create tag",
    "description": "Creates a tag via ApiTagController.create().",
    "tags": [
      "Work Management v1"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "tag_text": {
          "type": "string"
        },
        "text": {
          "type": "string"
        },
        "color": {
          "type": "string"
        },
        "background_color": {
          "type": "string"
        }
      },
      "required": [
        "tag_text"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_tags_analytics",
    "method": "get",
    "path": "/api/v1/tags/analytics",
    "displayName": "Get tag analytics",
    "summary": "Get tag analytics",
    "description": "Returns tag analytics aggregation payload.",
    "tags": [
      "Work Management v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "page",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "limit",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "sort",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "order",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "asc",
            "desc"
          ]
        }
      },
      {
        "name": "fields",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "search",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "query",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "post-_api_v1_tags_bulk",
    "method": "post",
    "path": "/api/v1/tags/bulk",
    "displayName": "Bulk create tags",
    "summary": "Bulk create tags",
    "description": "Bulk create tag operation.",
    "tags": [
      "Work Management v1"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "additionalProperties": {},
      "description": "Controller/service-specific payload; see source route/controller for exact required shape."
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "delete-_api_v1_tags_bulk",
    "method": "delete",
    "path": "/api/v1/tags/bulk",
    "displayName": "Bulk delete tags",
    "summary": "Bulk delete tags",
    "description": "Bulk delete tag operation.",
    "tags": [
      "Work Management v1"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "additionalProperties": {},
      "description": "Controller/service-specific payload; see source route/controller for exact required shape."
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "post-_api_v1_tags_bulk_merge",
    "method": "post",
    "path": "/api/v1/tags/bulk/merge",
    "displayName": "Bulk merge tags",
    "summary": "Bulk merge tags",
    "description": "Bulk merge tags into target tag.",
    "tags": [
      "Work Management v1"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "additionalProperties": {},
      "description": "Controller/service-specific payload; see source route/controller for exact required shape."
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "post-_api_v1_tags_bulk_tag",
    "method": "post",
    "path": "/api/v1/tags/bulk/tag",
    "displayName": "Bulk tag entities",
    "summary": "Bulk tag entities",
    "description": "Bulk add tags to entities.",
    "tags": [
      "Work Management v1"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "additionalProperties": {},
      "description": "Controller/service-specific payload; see source route/controller for exact required shape."
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "delete-_api_v1_tags_bulk_untag",
    "method": "delete",
    "path": "/api/v1/tags/bulk/untag",
    "displayName": "Bulk untag entities",
    "summary": "Bulk untag entities",
    "description": "Bulk remove tags from entities.",
    "tags": [
      "Work Management v1"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "additionalProperties": {},
      "description": "Controller/service-specific payload; see source route/controller for exact required shape."
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "delete-_api_v1_tags_bytext",
    "method": "delete",
    "path": "/api/v1/tags/by-text",
    "displayName": "Delete tags by text",
    "summary": "Delete tags by text",
    "description": "Deletes tags matching text criteria.",
    "tags": [
      "Work Management v1"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "additionalProperties": {},
      "description": "Controller/service-specific payload; see source route/controller for exact required shape."
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_tags_cloud",
    "method": "get",
    "path": "/api/v1/tags/cloud",
    "displayName": "Get tag cloud",
    "summary": "Get tag cloud",
    "description": "Returns weighted tag cloud data.",
    "tags": [
      "Work Management v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "page",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "limit",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "sort",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "order",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "asc",
            "desc"
          ]
        }
      },
      {
        "name": "fields",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "search",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "query",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "type": "array",
          "items": {
            "type": "object",
            "additionalProperties": {}
          }
        },
        "pagination": {
          "type": "object",
          "properties": {
            "page": {
              "type": "integer"
            },
            "limit": {
              "type": "integer"
            },
            "total": {
              "type": "integer"
            },
            "totalPages": {
              "type": "integer"
            },
            "hasNext": {
              "type": "boolean"
            },
            "hasPrev": {
              "type": "boolean"
            }
          },
          "required": [
            "page",
            "limit",
            "total",
            "totalPages",
            "hasNext",
            "hasPrev"
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data",
        "pagination"
      ]
    }
  },
  {
    "id": "get-_api_v1_tags_entity_entitytype_entityid",
    "method": "get",
    "path": "/api/v1/tags/entity/{entityType}/{entityId}",
    "displayName": "List tags for entity",
    "summary": "List tags for entity",
    "description": "Lists tags attached to entity route params.",
    "tags": [
      "Work Management v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "entityType",
        "in": "path",
        "required": true,
        "description": "Tagged entity type from route segment.",
        "schema": {
          "type": "string",
          "description": "Tagged entity type from route segment."
        }
      },
      {
        "name": "entityId",
        "in": "path",
        "required": true,
        "description": "Tagged entity id from route segment.",
        "schema": {
          "type": "string",
          "description": "Tagged entity id from route segment."
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "post-_api_v1_tags_entity_entitytype_entityid",
    "method": "post",
    "path": "/api/v1/tags/entity/{entityType}/{entityId}",
    "displayName": "Attach tags to entity",
    "summary": "Attach tags to entity",
    "description": "Adds tags to entity route params/body.",
    "tags": [
      "Work Management v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "entityType",
        "in": "path",
        "required": true,
        "description": "Tagged entity type from route segment.",
        "schema": {
          "type": "string",
          "description": "Tagged entity type from route segment."
        }
      },
      {
        "name": "entityId",
        "in": "path",
        "required": true,
        "description": "Tagged entity id from route segment.",
        "schema": {
          "type": "string",
          "description": "Tagged entity id from route segment."
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "additionalProperties": {},
      "description": "Controller/service-specific payload; see source route/controller for exact required shape."
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "delete-_api_v1_tags_entity_entitytype_entityid",
    "method": "delete",
    "path": "/api/v1/tags/entity/{entityType}/{entityId}",
    "displayName": "Remove tags from entity",
    "summary": "Remove tags from entity",
    "description": "Removes tag set from entity route params/body.",
    "tags": [
      "Work Management v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "entityType",
        "in": "path",
        "required": true,
        "description": "Tagged entity type from route segment.",
        "schema": {
          "type": "string",
          "description": "Tagged entity type from route segment."
        }
      },
      {
        "name": "entityId",
        "in": "path",
        "required": true,
        "description": "Tagged entity id from route segment.",
        "schema": {
          "type": "string",
          "description": "Tagged entity id from route segment."
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "additionalProperties": {},
      "description": "Controller/service-specific payload; see source route/controller for exact required shape."
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_tags_search",
    "method": "get",
    "path": "/api/v1/tags/search",
    "displayName": "Search tags",
    "summary": "Search tags",
    "description": "Searches tags via ApiTagController.search().",
    "tags": [
      "Work Management v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "page",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "limit",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "sort",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "order",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "asc",
            "desc"
          ]
        }
      },
      {
        "name": "fields",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "search",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "query",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "type": "array",
          "items": {
            "type": "object",
            "additionalProperties": {}
          }
        },
        "pagination": {
          "type": "object",
          "properties": {
            "page": {
              "type": "integer"
            },
            "limit": {
              "type": "integer"
            },
            "total": {
              "type": "integer"
            },
            "totalPages": {
              "type": "integer"
            },
            "hasNext": {
              "type": "boolean"
            },
            "hasPrev": {
              "type": "boolean"
            }
          },
          "required": [
            "page",
            "limit",
            "total",
            "totalPages",
            "hasNext",
            "hasPrev"
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data",
        "pagination"
      ]
    }
  },
  {
    "id": "get-_api_v1_tags_id",
    "method": "get",
    "path": "/api/v1/tags/{id}",
    "displayName": "Get tag",
    "summary": "Get tag",
    "description": "Gets tag UUID.",
    "tags": [
      "Work Management v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "UUID path identifier from underlying resource tables.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "UUID path identifier from underlying resource tables."
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "put-_api_v1_tags_id",
    "method": "put",
    "path": "/api/v1/tags/{id}",
    "displayName": "Update tag",
    "summary": "Update tag",
    "description": "Updates tag UUID.",
    "tags": [
      "Work Management v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "UUID path identifier from underlying resource tables.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "UUID path identifier from underlying resource tables."
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "additionalProperties": {},
      "description": "Controller/service-specific payload; see source route/controller for exact required shape."
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "delete-_api_v1_tags_id",
    "method": "delete",
    "path": "/api/v1/tags/{id}",
    "displayName": "Delete tag",
    "summary": "Delete tag",
    "description": "Deletes tag UUID.",
    "tags": [
      "Work Management v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "UUID path identifier from underlying resource tables.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "UUID path identifier from underlying resource tables."
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "additionalProperties": {},
      "description": "Controller/service-specific payload; see source route/controller for exact required shape."
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "put-_api_v1_tags_id_colors",
    "method": "put",
    "path": "/api/v1/tags/{id}/colors",
    "displayName": "Update tag colors",
    "summary": "Update tag colors",
    "description": "Updates tag color attributes.",
    "tags": [
      "Work Management v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "UUID path identifier from underlying resource tables.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "UUID path identifier from underlying resource tables."
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "additionalProperties": {},
      "description": "Controller/service-specific payload; see source route/controller for exact required shape."
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "put-_api_v1_tags_id_text",
    "method": "put",
    "path": "/api/v1/tags/{id}/text",
    "displayName": "Update tag text",
    "summary": "Update tag text",
    "description": "Updates tag display text.",
    "tags": [
      "Work Management v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "UUID path identifier from underlying resource tables.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "UUID path identifier from underlying resource tables."
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "additionalProperties": {},
      "description": "Controller/service-specific payload; see source route/controller for exact required shape."
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_tickets",
    "method": "get",
    "path": "/api/v1/tickets",
    "displayName": "List Tickets",
    "summary": "List tickets",
    "description": "Returns a paginated list of tickets for the current tenant. Supports filtering by board, status, priority, client, assignee, category, open/closed/overdue flags, and entered/closed date ranges — see the parameters list for all available filters. For aggregate counts (e.g. how many tickets are open or high priority), prefer GET /api/v1/tickets/stats or set limit=1 and read pagination.total from the response. Use GET /api/v1/boards, GET /api/v1/statuses, and GET /api/v1/priorities for lookup data instead of sampling tickets. If you send the fields query parameter, use only these exact field names: ticket_id, ticket_number, title, status_id, status_name, status_is_closed, priority_name, assigned_to_name, client_name, contact_name, updated_at, entered_at, closed_at, tags, or mobile_list. Do not invent aliases such as id, subject, status, priority, client, created_at, or description.",
    "tags": [
      "Work Management v1"
    ],
    "rbacResource": "ticket",
    "approvalRequired": false,
    "parameters": [
      {
        "name": "page",
        "in": "query",
        "required": false,
        "description": "Pagination page number (default 1).",
        "schema": {
          "type": "integer",
          "minimum": 1
        }
      },
      {
        "name": "limit",
        "in": "query",
        "required": false,
        "description": "Number of tickets per page (max 100, default 25). Set limit=1 when you only need pagination.total for an aggregate count.",
        "schema": {
          "type": "integer",
          "minimum": 1,
          "maximum": 100
        }
      },
      {
        "name": "board_id",
        "in": "query",
        "required": false,
        "description": "Filter to a specific board.",
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      },
      {
        "name": "board_name",
        "in": "query",
        "required": false,
        "description": "Filter by board display name (case-sensitive exact match). Prefer board_id when you already have a UUID.",
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "status_id",
        "in": "query",
        "required": false,
        "description": "Filter by a single ticket status UUID.",
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      },
      {
        "name": "status_ids",
        "in": "query",
        "required": false,
        "description": "Filter by multiple status UUIDs as a comma-separated list (for example status_ids=uuid1,uuid2). Useful for matching several open or closed statuses at once.",
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "status_name",
        "in": "query",
        "required": false,
        "description": "Filter by status display name (case-sensitive exact match). Prefer status_id/status_ids when you already have UUIDs.",
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "priority_id",
        "in": "query",
        "required": false,
        "description": "Filter by ticket priority UUID. Call GET /api/v1/priorities to discover priority UUIDs.",
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      },
      {
        "name": "priority_name",
        "in": "query",
        "required": false,
        "description": "Filter by priority display name (case-sensitive exact match). Use this when the user asks for tickets of a specific priority like \"High\", \"Highest\", \"Medium\", or \"Low\" and you do not want to look up a UUID first.",
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "category_id",
        "in": "query",
        "required": false,
        "description": "Filter by ticket category UUID.",
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      },
      {
        "name": "subcategory_id",
        "in": "query",
        "required": false,
        "description": "Filter by ticket subcategory UUID.",
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      },
      {
        "name": "category_name",
        "in": "query",
        "required": false,
        "description": "Filter by category display name (case-sensitive exact match).",
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "client_id",
        "in": "query",
        "required": false,
        "description": "Filter by client identifier.",
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      },
      {
        "name": "client_name",
        "in": "query",
        "required": false,
        "description": "Filter by client display name (case-sensitive exact match). Prefer client_id when you already have a UUID.",
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "location_id",
        "in": "query",
        "required": false,
        "description": "Filter by client location UUID.",
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      },
      {
        "name": "contact_name_id",
        "in": "query",
        "required": false,
        "description": "Filter by primary contact UUID on the ticket.",
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      },
      {
        "name": "contact_name",
        "in": "query",
        "required": false,
        "description": "Filter by contact display name (case-sensitive exact match).",
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "assigned_to",
        "in": "query",
        "required": false,
        "description": "Filter tickets assigned to a specific technician (user UUID).",
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      },
      {
        "name": "entered_by",
        "in": "query",
        "required": false,
        "description": "Filter tickets created by a specific user UUID.",
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      },
      {
        "name": "title",
        "in": "query",
        "required": false,
        "description": "Filter by ticket title (substring match).",
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "ticket_number",
        "in": "query",
        "required": false,
        "description": "Filter by ticket number (for example alga0001748).",
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "is_open",
        "in": "query",
        "required": false,
        "description": "When true, only open tickets are returned.",
        "schema": {
          "type": "boolean"
        }
      },
      {
        "name": "is_closed",
        "in": "query",
        "required": false,
        "description": "When true, only closed tickets are returned.",
        "schema": {
          "type": "boolean"
        }
      },
      {
        "name": "has_assignment",
        "in": "query",
        "required": false,
        "description": "When true, only tickets that have an assignee are returned; when false, only unassigned tickets.",
        "schema": {
          "type": "boolean"
        }
      },
      {
        "name": "entered_from",
        "in": "query",
        "required": false,
        "description": "Lower bound on entered_at as an ISO-8601 datetime (inclusive).",
        "schema": {
          "type": "string",
          "format": "date-time"
        }
      },
      {
        "name": "entered_to",
        "in": "query",
        "required": false,
        "description": "Upper bound on entered_at as an ISO-8601 datetime (inclusive).",
        "schema": {
          "type": "string",
          "format": "date-time"
        }
      },
      {
        "name": "closed_from",
        "in": "query",
        "required": false,
        "description": "Lower bound on closed_at as an ISO-8601 datetime (inclusive).",
        "schema": {
          "type": "string",
          "format": "date-time"
        }
      },
      {
        "name": "closed_to",
        "in": "query",
        "required": false,
        "description": "Upper bound on closed_at as an ISO-8601 datetime (inclusive).",
        "schema": {
          "type": "string",
          "format": "date-time"
        }
      },
      {
        "name": "fields",
        "in": "query",
        "required": false,
        "description": "Comma-separated list of fields to return. Use only these exact values: ticket_id, ticket_number, title, status_id, status_name, status_is_closed, priority_name, assigned_to_name, client_name, contact_name, updated_at, entered_at, closed_at, tags, or mobile_list. If you are not sure, omit fields entirely instead of guessing aliases.",
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "field_ranges[description_html]",
        "in": "query",
        "required": false,
        "description": "Optional UTF-8 byte range for the description_html field, formatted as start-end (for example 0-4095). When returned data is truncated, inspect meta.truncated_fields for continuation offsets.",
        "schema": {
          "type": "string",
          "pattern": "^\\d+-\\d+$"
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "ticket_id": {
                "type": "string",
                "format": "uuid"
              },
              "ticket_number": {
                "type": "string"
              },
              "title": {
                "type": "string"
              },
              "client_id": {
                "type": "string",
                "format": "uuid"
              },
              "board_id": {
                "type": "string",
                "format": "uuid"
              },
              "status_id": {
                "type": "string",
                "format": "uuid"
              },
              "priority_id": {
                "type": "string",
                "format": "uuid"
              },
              "assigned_to": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "uuid"
              },
              "entered_at": {
                "type": "string",
                "format": "date-time"
              }
            },
            "required": [
              "ticket_id",
              "ticket_number",
              "title",
              "client_id",
              "board_id",
              "status_id",
              "priority_id",
              "entered_at"
            ]
          }
        },
        "pagination": {
          "type": "object",
          "properties": {
            "page": {
              "type": "integer"
            },
            "limit": {
              "type": "integer"
            },
            "total": {
              "type": "integer"
            },
            "totalPages": {
              "type": "integer"
            },
            "hasNext": {
              "type": "boolean"
            },
            "hasPrev": {
              "type": "boolean"
            }
          }
        }
      }
    },
    "examples": [
      {
        "name": "Sample recent tickets for reference data",
        "request": {
          "query": {
            "limit": 5,
            "fields": "ticket_id,ticket_number,title,board_id,status_id,priority_id,assigned_to,entered_at",
            "is_open": true
          }
        },
        "notes": "Inspect the response payload to reuse board_id, status_id, priority_id, and assigned_to values that are known to be valid. Prefer fields=... to keep payloads compact, but only use the documented field names exactly as written. If you are unsure which field names are valid, omit fields instead of guessing. If you only need a single set of identifiers, take the first ticket in the data array that has non-null board_id, status_id, and priority_id and reuse those UUIDs for the new ticket."
      }
    ]
  },
  {
    "id": "post-_api_v1_tickets",
    "method": "post",
    "path": "/api/v1/tickets",
    "displayName": "Create Ticket",
    "summary": "Create a new ticket",
    "description": "Creates a new ticket on a specified board with the desired status and priority. Requires the user to have ticket create permissions. Do not invoke this until you have gathered valid UUIDs for board_id, client_id, status_id, and priority_id from prior lookup calls. IMPORTANT: status_id must belong to the same board as board_id — use GET /api/v1/statuses?type=ticket&board_id=... to discover valid statuses for the chosen board.",
    "tags": [
      "Work Management v1"
    ],
    "rbacResource": "ticket",
    "approvalRequired": true,
    "parameters": [
      {
        "name": "page",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "limit",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "sort",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "order",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "asc",
            "desc"
          ]
        }
      },
      {
        "name": "fields",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "search",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "query",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "title": {
          "type": "string",
          "description": "Ticket subject line."
        },
        "board_id": {
          "type": "string",
          "format": "uuid",
          "description": "Ticket board identifier. Call GET /api/v1/boards to list available boards and pick a valid board_id. Always provide the UUID, never the board name, slug, or display label."
        },
        "client_id": {
          "type": "string",
          "format": "uuid",
          "description": "Owning client identifier. Retrieve clients via GET /api/v1/clients (supporting filters such as name or status) to resolve the correct client_id, and provide that UUID in the payload (do not send the client name)."
        },
        "status_id": {
          "type": "string",
          "format": "uuid",
          "description": "Initial ticket status identifier. Call GET /api/v1/statuses?type=ticket&board_id=... to list valid statuses for the chosen board. The status_id MUST belong to the same board as board_id. Do not send a status label like \"Open\" or a field named \"status\"."
        },
        "priority_id": {
          "type": "string",
          "format": "uuid",
          "description": "Ticket priority identifier. Use GET /api/v1/priorities or sample existing tickets to obtain a valid priority_id. Always include the UUID (never send fields named \"priority\" or the textual priority name)."
        },
        "contact_name_id": {
          "type": "string",
          "format": "uuid",
          "nullable": true,
          "description": "Primary contact for this ticket. Look up contacts through GET /api/v1/contacts (optionally filter by client_id) before supplying this reference."
        },
        "location_id": {
          "type": "string",
          "format": "uuid",
          "nullable": true,
          "description": "Client location identifier. Call GET /api/v1/clients/{client_id}/locations to enumerate valid locations for the chosen client."
        },
        "category_id": {
          "type": "string",
          "format": "uuid",
          "nullable": true,
          "description": "Ticket category identifier. Fetch categories via GET /api/v1/categories/ticket (filter by board_id if necessary) to resolve the correct category_id."
        },
        "subcategory_id": {
          "type": "string",
          "format": "uuid",
          "nullable": true,
          "description": "Ticket subcategory identifier. After retrieving the category list or tree (GET /api/v1/categories/ticket or GET /api/v1/categories/ticket/tree/{board_id}), choose the desired subcategory_id."
        },
        "assigned_to": {
          "type": "string",
          "format": "uuid",
          "nullable": true,
          "description": "Technician assignment. Use GET /api/v1/users (filtering by role, team, or name) to acquire the user_id of the assignee and submit that UUID."
        },
        "url": {
          "type": "string",
          "format": "uri",
          "nullable": true
        },
        "attributes": {
          "type": "object",
          "additionalProperties": true
        },
        "tags": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "description": "Optional labels to associate with the ticket. Discover existing tag values via GET /api/v1/tags or GET /api/v1/tags/search before reusing them."
        }
      },
      "required": [
        "title",
        "board_id",
        "client_id",
        "status_id",
        "priority_id"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "type": "object",
          "properties": {
            "ticket_id": {
              "type": "string",
              "format": "uuid"
            },
            "ticket_number": {
              "type": "string"
            },
            "title": {
              "type": "string"
            },
            "status_id": {
              "type": "string",
              "format": "uuid"
            },
            "priority_id": {
              "type": "string",
              "format": "uuid"
            },
            "board_id": {
              "type": "string",
              "format": "uuid"
            },
            "client_id": {
              "type": "string",
              "format": "uuid"
            },
            "assigned_to": {
              "type": [
                "string",
                "null"
              ],
              "format": "uuid"
            }
          },
          "required": [
            "ticket_id",
            "ticket_number",
            "title",
            "status_id",
            "priority_id",
            "board_id",
            "client_id"
          ]
        }
      }
    },
    "examples": [
      {
        "name": "Create ticket example",
        "request": {
          "body": {
            "title": "Printer offline at HQ",
            "board_id": "11111111-1111-1111-1111-111111111111",
            "client_id": "22222222-2222-2222-2222-222222222222",
            "status_id": "33333333-3333-3333-3333-333333333333",
            "priority_id": "44444444-4444-4444-4444-444444444444",
            "contact_name_id": "55555555-5555-5555-5555-555555555555"
          }
        },
        "notes": "Before calling this endpoint, resolve every referenced identifier by invoking the appropriate lookup APIs: GET /api/v1/boards to choose board_id, GET /api/v1/statuses?type=ticket&board_id=... to choose a status_id that belongs to that board, GET /api/v1/clients to choose client_id, GET /api/v1/contacts?client_id=... for contact_name_id, GET /api/v1/clients/{client_id}/locations for location_id, GET /api/v1/categories/ticket for category/subcategory options, GET /api/v1/users to select the assignee, and GET /api/v1/tags to reuse tag names. CRITICAL: status_id must belong to the same board as board_id — mismatched values will be rejected with a 400 error. Always send UUID fields exactly as documented — do not substitute human-readable names such as \"High\" or \"In Progress,\" and do not introduce extra fields that are not part of this schema."
      }
    ]
  },
  {
    "id": "get-_api_v1_tickets_fromasset",
    "method": "get",
    "path": "/api/v1/tickets/from-asset",
    "displayName": "Create ticket from asset (POST only)",
    "summary": "Create ticket from asset (POST only)",
    "description": "This path creates a ticket from an asset via POST. GET is not supported and returns 405 Method Not Allowed.",
    "tags": [
      "Work Management v1"
    ],
    "approvalRequired": false,
    "parameters": []
  },
  {
    "id": "post-_api_v1_tickets_fromasset",
    "method": "post",
    "path": "/api/v1/tickets/from-asset",
    "displayName": "Create ticket from asset",
    "summary": "Create ticket from asset",
    "description": "Creates ticket from asset context via ApiTicketController.createFromAsset().",
    "tags": [
      "Work Management v1"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "additionalProperties": {},
      "description": "Controller/service-specific payload; see source route/controller for exact required shape."
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_tickets_search",
    "method": "get",
    "path": "/api/v1/tickets/search",
    "displayName": "Search tickets",
    "summary": "Search tickets",
    "description": "Searches tickets via ApiTicketController.search().",
    "tags": [
      "Work Management v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "page",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "limit",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "sort",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "order",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "asc",
            "desc"
          ]
        }
      },
      {
        "name": "fields",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "search",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "query",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "type": "array",
          "items": {
            "type": "object",
            "additionalProperties": {}
          }
        },
        "pagination": {
          "type": "object",
          "properties": {
            "page": {
              "type": "integer"
            },
            "limit": {
              "type": "integer"
            },
            "total": {
              "type": "integer"
            },
            "totalPages": {
              "type": "integer"
            },
            "hasNext": {
              "type": "boolean"
            },
            "hasPrev": {
              "type": "boolean"
            }
          },
          "required": [
            "page",
            "limit",
            "total",
            "totalPages",
            "hasNext",
            "hasPrev"
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data",
        "pagination"
      ]
    }
  },
  {
    "id": "get-_api_v1_tickets_stats",
    "method": "get",
    "path": "/api/v1/tickets/stats",
    "displayName": "Get Ticket Stats",
    "summary": "Aggregate ticket counts and metrics",
    "description": "Returns pre-computed ticket counts and metrics for the current tenant in a single call. Use this whenever the user asks aggregate questions like \"how many tickets are open\", \"how many high priority tickets\", \"how many overdue tickets\", or \"how many tickets per board/status/priority/category\". This endpoint returns totals grouped by status, priority, category, and board, plus counts of open/closed/overdue/unassigned tickets and tickets created today/this week/this month. Prefer this over paginating GET /api/v1/tickets and counting rows yourself.",
    "tags": [
      "Work Management v1"
    ],
    "rbacResource": "ticket",
    "approvalRequired": false,
    "parameters": [],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "type": "object",
          "description": "Ticket statistics for the current tenant. Priority names (e.g. \"High\", \"Medium\") are the keys in tickets_by_priority and map directly to the priority_name values used by GET /api/v1/tickets.",
          "properties": {
            "total_tickets": {
              "type": "integer",
              "description": "Total number of tickets in the tenant, regardless of status."
            },
            "open_tickets": {
              "type": "integer",
              "description": "Number of tickets that are currently open (status.is_closed = false)."
            },
            "closed_tickets": {
              "type": "integer",
              "description": "Number of tickets whose status is marked closed."
            },
            "overdue_tickets": {
              "type": "integer",
              "description": "Number of open tickets past their due/SLA date."
            },
            "unassigned_tickets": {
              "type": "integer",
              "description": "Number of open tickets with no assignee."
            },
            "tickets_by_status": {
              "type": "object",
              "additionalProperties": {
                "type": "integer"
              },
              "description": "Map of status display name to ticket count, for example {\"New\": 42, \"In Progress\": 18, \"Closed\": 140}."
            },
            "tickets_by_priority": {
              "type": "object",
              "additionalProperties": {
                "type": "integer"
              },
              "description": "Map of priority display name to ticket count, for example {\"High\": 12, \"Highest\": 3, \"Medium\": 55, \"Low\": 20}. These keys are the same strings accepted by the priority_name filter on GET /api/v1/tickets."
            },
            "tickets_by_category": {
              "type": "object",
              "additionalProperties": {
                "type": "integer"
              },
              "description": "Map of category display name to ticket count."
            },
            "tickets_by_board": {
              "type": "object",
              "additionalProperties": {
                "type": "integer"
              },
              "description": "Map of board display name to ticket count."
            },
            "average_resolution_time": {
              "type": [
                "number",
                "null"
              ],
              "description": "Average resolution time in hours across closed tickets, or null if there are no closed tickets."
            },
            "tickets_created_today": {
              "type": "integer"
            },
            "tickets_created_this_week": {
              "type": "integer"
            },
            "tickets_created_this_month": {
              "type": "integer"
            }
          },
          "required": [
            "total_tickets",
            "open_tickets",
            "closed_tickets",
            "overdue_tickets",
            "unassigned_tickets",
            "tickets_by_status",
            "tickets_by_priority",
            "tickets_by_category",
            "tickets_by_board",
            "tickets_created_today",
            "tickets_created_this_week",
            "tickets_created_this_month"
          ]
        }
      }
    },
    "examples": [
      {
        "name": "Answer \"how many high priority tickets are open\" in one call",
        "request": {},
        "notes": "Call this endpoint and read data.tickets_by_priority[\"High\"] for the count of high-priority tickets. Note the map covers all tickets regardless of status — if the user asks specifically about OPEN high-priority tickets and you need to scope by status, fall back to GET /api/v1/tickets?is_open=true&priority_name=High&limit=1 and read pagination.total from that response."
      }
    ]
  },
  {
    "id": "get-_api_v1_tickets_id",
    "method": "get",
    "path": "/api/v1/tickets/{id}",
    "displayName": "Get Ticket",
    "summary": "Get ticket by ID",
    "description": "Returns the full ticket record for a specific ticket. Prefer this over expanding list responses when you already know the ticket_id.",
    "tags": [
      "Work Management v1"
    ],
    "rbacResource": "ticket",
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Ticket identifier.",
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      },
      {
        "name": "field_ranges[description_html]",
        "in": "query",
        "required": false,
        "description": "Optional UTF-8 byte range for description_html, formatted as start-end (for example 0-4095). When returned data is truncated, inspect meta.truncated_fields for continuation offsets.",
        "schema": {
          "type": "string",
          "pattern": "^\\d+-\\d+$"
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    },
    "examples": [
      {
        "name": "Read one ticket in detail",
        "request": {
          "params": {
            "id": "11111111-1111-1111-1111-111111111111"
          }
        },
        "notes": "Use this endpoint after a list/search call gives you a ticket_id. If description_html is large, fetch it in byte windows with field_ranges[description_html]=start-end instead of asking for a bigger list payload."
      }
    ]
  },
  {
    "id": "put-_api_v1_tickets_id",
    "method": "put",
    "path": "/api/v1/tickets/{id}",
    "displayName": "Update ticket",
    "summary": "Update ticket",
    "description": "Updates ticket UUID.",
    "tags": [
      "Work Management v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "UUID path identifier from underlying resource tables.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "UUID path identifier from underlying resource tables."
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "additionalProperties": {},
      "description": "Controller/service-specific payload; see source route/controller for exact required shape."
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "delete-_api_v1_tickets_id",
    "method": "delete",
    "path": "/api/v1/tickets/{id}",
    "displayName": "Delete ticket",
    "summary": "Delete ticket",
    "description": "Deletes ticket UUID.",
    "tags": [
      "Work Management v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "UUID path identifier from underlying resource tables.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "UUID path identifier from underlying resource tables."
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "put-_api_v1_tickets_id_assignment",
    "method": "put",
    "path": "/api/v1/tickets/{id}/assignment",
    "displayName": "Update ticket assignment",
    "summary": "Update ticket assignment",
    "description": "Updates ticket assignment target.",
    "tags": [
      "Work Management v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "UUID path identifier from underlying resource tables.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "UUID path identifier from underlying resource tables."
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "additionalProperties": {},
      "description": "Controller/service-specific payload; see source route/controller for exact required shape."
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_tickets_id_comments",
    "method": "get",
    "path": "/api/v1/tickets/{id}/comments",
    "displayName": "Get Ticket Comments",
    "summary": "List comments for a ticket",
    "description": "Returns the comments attached to a ticket. Use small limits and field-scoped byte ranges when comment bodies are large.",
    "tags": [
      "Work Management v1"
    ],
    "rbacResource": "ticket",
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Ticket identifier.",
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      },
      {
        "name": "limit",
        "in": "query",
        "required": false,
        "description": "Maximum number of comments to return (1-200). Prefer small values when exploring ticket history.",
        "schema": {
          "type": "integer",
          "minimum": 1,
          "maximum": 200
        }
      },
      {
        "name": "offset",
        "in": "query",
        "required": false,
        "description": "Zero-based comment offset.",
        "schema": {
          "type": "integer",
          "minimum": 0
        }
      },
      {
        "name": "order",
        "in": "query",
        "required": false,
        "description": "Comment sort order.",
        "schema": {
          "type": "string",
          "enum": [
            "asc",
            "desc"
          ]
        }
      },
      {
        "name": "field_ranges[comment_text]",
        "in": "query",
        "required": false,
        "description": "Optional UTF-8 byte range for comment_text, formatted as start-end (for example 0-4095). Use meta.truncated_fields to continue fetching long comments.",
        "schema": {
          "type": "string",
          "pattern": "^\\d+-\\d+$"
        }
      },
      {
        "name": "field_ranges[comment_html]",
        "in": "query",
        "required": false,
        "description": "Optional UTF-8 byte range for comment_html, formatted as start-end (for example 0-4095).",
        "schema": {
          "type": "string",
          "pattern": "^\\d+-\\d+$"
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "type": "array",
          "items": {
            "type": "object",
            "additionalProperties": {}
          }
        },
        "pagination": {
          "type": "object",
          "properties": {
            "page": {
              "type": "integer"
            },
            "limit": {
              "type": "integer"
            },
            "total": {
              "type": "integer"
            },
            "totalPages": {
              "type": "integer"
            },
            "hasNext": {
              "type": "boolean"
            },
            "hasPrev": {
              "type": "boolean"
            }
          },
          "required": [
            "page",
            "limit",
            "total",
            "totalPages",
            "hasNext",
            "hasPrev"
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data",
        "pagination"
      ]
    },
    "examples": [
      {
        "name": "Read recent comments with ranged comment text",
        "request": {
          "params": {
            "id": "11111111-1111-1111-1111-111111111111"
          },
          "query": {
            "limit": 5,
            "order": "desc",
            "field_ranges[comment_text]": "0-4095"
          }
        },
        "notes": "Prefer this endpoint over large ticket list payloads when the user asks for comment history or long comment bodies."
      }
    ]
  },
  {
    "id": "post-_api_v1_tickets_id_comments",
    "method": "post",
    "path": "/api/v1/tickets/{id}/comments",
    "displayName": "Add Ticket Comment",
    "summary": "Add a comment to a ticket",
    "description": "Adds a client or internal comment to the specified ticket.",
    "tags": [
      "Work Management v1"
    ],
    "rbacResource": "ticket",
    "approvalRequired": true,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Ticket identifier.",
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "comment_text": {
          "type": "string",
          "description": "Comment body text."
        },
        "is_internal": {
          "type": "boolean",
          "description": "When true, records the comment as internal only.",
          "default": false
        },
        "time_spent": {
          "type": "number",
          "description": "Optional time (in minutes) to log with the comment.",
          "minimum": 0
        }
      },
      "required": [
        "comment_text"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "put-_api_v1_tickets_id_status",
    "method": "put",
    "path": "/api/v1/tickets/{id}/status",
    "displayName": "Update ticket status",
    "summary": "Update ticket status",
    "description": "Updates status for ticket UUID.",
    "tags": [
      "Work Management v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "UUID path identifier from underlying resource tables.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "UUID path identifier from underlying resource tables."
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "additionalProperties": {},
      "description": "Controller/service-specific payload; see source route/controller for exact required shape."
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_tickets_id_timeentries",
    "method": "get",
    "path": "/api/v1/tickets/{id}/time-entries",
    "displayName": "Get Ticket Time Entries",
    "summary": "List time entries logged on a ticket",
    "description": "Returns an authorization-aware summary of the time logged on a ticket. Each entry is evaluated through the authorization kernel against `time_entry:read`; the caller always sees their own entries, plus any other users' entries the kernel allows (e.g. team members managed by the caller, or entries permitted by an assigned authorization bundle). Entries the caller cannot see are still counted toward an anonymized aggregate (`othersHiddenCount` + `othersHiddenMinutes`) so that totals stay accurate without leaking individual entries.",
    "tags": [
      "Work Management v1"
    ],
    "rbacResource": "ticket",
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Ticket identifier.",
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    },
    "examples": [
      {
        "name": "Read time logged on a ticket",
        "request": {
          "params": {
            "id": "11111111-1111-1111-1111-111111111111"
          }
        },
        "notes": "Use this endpoint to render time-tracking summaries on the ticket detail page or in mobile clients without paging through the global timesheet list."
      }
    ]
  },
  {
    "id": "get-_api_v1_tickets_id_bundle",
    "method": "get",
    "path": "/api/v1/tickets/{id}/bundle",
    "displayName": "Get ticket bundle",
    "summary": "Get ticket bundle",
    "description": "Returns bundle membership for the ticket: role (master, child, or standalone), the master ticket, child tickets, and bundle settings.",
    "tags": [
      "Work Management v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "UUID path identifier from underlying resource tables.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "UUID path identifier from underlying resource tables."
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "post-_api_v1_tickets_id_bundle",
    "method": "post",
    "path": "/api/v1/tickets/{id}/bundle",
    "displayName": "Create ticket bundle",
    "summary": "Create ticket bundle",
    "description": "Bundles the given child tickets under ticket {id} as the master, with a sync mode of link_only or sync_updates.",
    "tags": [
      "Work Management v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "UUID path identifier from underlying resource tables.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "UUID path identifier from underlying resource tables."
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "additionalProperties": {},
      "description": "Controller/service-specific payload; see source route/controller for exact required shape."
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "delete-_api_v1_tickets_id_bundle",
    "method": "delete",
    "path": "/api/v1/tickets/{id}/bundle",
    "displayName": "Unbundle ticket",
    "summary": "Unbundle ticket",
    "description": "Unbundles master {id}, detaching all child tickets and removing bundle settings.",
    "tags": [
      "Work Management v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "UUID path identifier from underlying resource tables.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "UUID path identifier from underlying resource tables."
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "post-_api_v1_tickets_id_bundle_children",
    "method": "post",
    "path": "/api/v1/tickets/{id}/bundle/children",
    "displayName": "Add bundle children",
    "summary": "Add bundle children",
    "description": "Adds child tickets to the existing bundle mastered by {id}.",
    "tags": [
      "Work Management v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "UUID path identifier from underlying resource tables.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "UUID path identifier from underlying resource tables."
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "additionalProperties": {},
      "description": "Controller/service-specific payload; see source route/controller for exact required shape."
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "delete-_api_v1_tickets_id_bundle_children_childid",
    "method": "delete",
    "path": "/api/v1/tickets/{id}/bundle/children/{childId}",
    "displayName": "Remove bundle child",
    "summary": "Remove bundle child",
    "description": "Removes child {childId} from its bundle; removes bundle settings when no children remain.",
    "tags": [
      "Work Management v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "UUID path identifier from underlying resource tables.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "UUID path identifier from underlying resource tables."
        }
      },
      {
        "name": "childId",
        "in": "path",
        "required": true,
        "description": "ChildId path parameter.",
        "schema": {
          "type": "string"
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "post-_api_v1_tickets_id_bundle_promote",
    "method": "post",
    "path": "/api/v1/tickets/{id}/bundle/promote",
    "displayName": "Promote bundle master",
    "summary": "Promote bundle master",
    "description": "Promotes a child ticket to be the new bundle master, re-pointing the remaining children.",
    "tags": [
      "Work Management v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "UUID path identifier from underlying resource tables.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "UUID path identifier from underlying resource tables."
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "additionalProperties": {},
      "description": "Controller/service-specific payload; see source route/controller for exact required shape."
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "put-_api_v1_tickets_id_bundle_settings",
    "method": "put",
    "path": "/api/v1/tickets/{id}/bundle/settings",
    "displayName": "Update ticket bundle settings",
    "summary": "Update ticket bundle settings",
    "description": "Updates the bundle mode and/or reopen-on-child-reply policy for master {id}.",
    "tags": [
      "Work Management v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "UUID path identifier from underlying resource tables.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "UUID path identifier from underlying resource tables."
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "additionalProperties": {},
      "description": "Controller/service-specific payload; see source route/controller for exact required shape."
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_timeentries",
    "method": "get",
    "path": "/api/v1/time-entries",
    "displayName": "List time entries",
    "summary": "List time entries",
    "description": "Lists time entries via ApiBaseController list flow.",
    "tags": [
      "Work Management v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "page",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "limit",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "sort",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "order",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "asc",
            "desc"
          ]
        }
      },
      {
        "name": "fields",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "search",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "query",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "type": "array",
          "items": {
            "type": "object",
            "additionalProperties": {}
          }
        },
        "pagination": {
          "type": "object",
          "properties": {
            "page": {
              "type": "integer"
            },
            "limit": {
              "type": "integer"
            },
            "total": {
              "type": "integer"
            },
            "totalPages": {
              "type": "integer"
            },
            "hasNext": {
              "type": "boolean"
            },
            "hasPrev": {
              "type": "boolean"
            }
          },
          "required": [
            "page",
            "limit",
            "total",
            "totalPages",
            "hasNext",
            "hasPrev"
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data",
        "pagination"
      ]
    }
  },
  {
    "id": "post-_api_v1_timeentries",
    "method": "post",
    "path": "/api/v1/time-entries",
    "displayName": "Create time entry",
    "summary": "Create time entry",
    "description": "Creates time entry.",
    "tags": [
      "Work Management v1"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "work_item_type": {
          "type": "string"
        },
        "work_item_id": {
          "type": "string"
        },
        "user_id": {
          "type": "string",
          "format": "uuid"
        },
        "started_at": {
          "type": "string"
        },
        "ended_at": {
          "type": "string"
        },
        "duration_minutes": {
          "type": "number"
        },
        "billable_minutes": {
          "type": "number"
        },
        "notes": {
          "type": "string"
        }
      }
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_timeentries_activesession",
    "method": "get",
    "path": "/api/v1/time-entries/active-session",
    "displayName": "Get active tracking session",
    "summary": "Get active tracking session",
    "description": "Returns active tracking session for current user context.",
    "tags": [
      "Work Management v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "page",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "limit",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "sort",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "order",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "asc",
            "desc"
          ]
        }
      },
      {
        "name": "fields",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "search",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "query",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "post-_api_v1_timeentries_approve",
    "method": "post",
    "path": "/api/v1/time-entries/approve",
    "displayName": "Approve time entries",
    "summary": "Approve time entries",
    "description": "Approves time entries payload.",
    "tags": [
      "Work Management v1"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "additionalProperties": {},
      "description": "Controller/service-specific payload; see source route/controller for exact required shape."
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "post-_api_v1_timeentries_bulk",
    "method": "post",
    "path": "/api/v1/time-entries/bulk",
    "displayName": "Bulk create time entries",
    "summary": "Bulk create time entries",
    "description": "Bulk create time entry operation.",
    "tags": [
      "Work Management v1"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "additionalProperties": {},
      "description": "Controller/service-specific payload; see source route/controller for exact required shape."
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "put-_api_v1_timeentries_bulk",
    "method": "put",
    "path": "/api/v1/time-entries/bulk",
    "displayName": "Bulk update time entries",
    "summary": "Bulk update time entries",
    "description": "Bulk update time entry operation.",
    "tags": [
      "Work Management v1"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "additionalProperties": {},
      "description": "Controller/service-specific payload; see source route/controller for exact required shape."
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "delete-_api_v1_timeentries_bulk",
    "method": "delete",
    "path": "/api/v1/time-entries/bulk",
    "displayName": "Bulk delete time entries",
    "summary": "Bulk delete time entries",
    "description": "Bulk delete time entry operation.",
    "tags": [
      "Work Management v1"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "additionalProperties": {},
      "description": "Controller/service-specific payload; see source route/controller for exact required shape."
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_timeentries_export",
    "method": "get",
    "path": "/api/v1/time-entries/export",
    "displayName": "Export time entries",
    "summary": "Export time entries",
    "description": "Exports time entries with optional filter/format query.",
    "tags": [
      "Work Management v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "page",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "limit",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "sort",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "order",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "asc",
            "desc"
          ]
        }
      },
      {
        "name": "fields",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "search",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "query",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "type": "array",
          "items": {
            "type": "object",
            "additionalProperties": {}
          }
        },
        "pagination": {
          "type": "object",
          "properties": {
            "page": {
              "type": "integer"
            },
            "limit": {
              "type": "integer"
            },
            "total": {
              "type": "integer"
            },
            "totalPages": {
              "type": "integer"
            },
            "hasNext": {
              "type": "boolean"
            },
            "hasPrev": {
              "type": "boolean"
            }
          },
          "required": [
            "page",
            "limit",
            "total",
            "totalPages",
            "hasNext",
            "hasPrev"
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data",
        "pagination"
      ]
    }
  },
  {
    "id": "post-_api_v1_timeentries_requestchanges",
    "method": "post",
    "path": "/api/v1/time-entries/request-changes",
    "displayName": "Request time entry changes",
    "summary": "Request time entry changes",
    "description": "Requests changes for submitted time entries.",
    "tags": [
      "Work Management v1"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "additionalProperties": {},
      "description": "Controller/service-specific payload; see source route/controller for exact required shape."
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_timeentries_search",
    "method": "get",
    "path": "/api/v1/time-entries/search",
    "displayName": "Search time entries",
    "summary": "Search time entries",
    "description": "Searches time entries with controller-specific filters.",
    "tags": [
      "Work Management v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "page",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "limit",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "sort",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "order",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "asc",
            "desc"
          ]
        }
      },
      {
        "name": "fields",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "search",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "query",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "type": "array",
          "items": {
            "type": "object",
            "additionalProperties": {}
          }
        },
        "pagination": {
          "type": "object",
          "properties": {
            "page": {
              "type": "integer"
            },
            "limit": {
              "type": "integer"
            },
            "total": {
              "type": "integer"
            },
            "totalPages": {
              "type": "integer"
            },
            "hasNext": {
              "type": "boolean"
            },
            "hasPrev": {
              "type": "boolean"
            }
          },
          "required": [
            "page",
            "limit",
            "total",
            "totalPages",
            "hasNext",
            "hasPrev"
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data",
        "pagination"
      ]
    }
  },
  {
    "id": "post-_api_v1_timeentries_starttracking",
    "method": "post",
    "path": "/api/v1/time-entries/start-tracking",
    "displayName": "Start time tracking",
    "summary": "Start time tracking",
    "description": "Starts active tracking session.",
    "tags": [
      "Work Management v1"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "additionalProperties": {},
      "description": "Controller/service-specific payload; see source route/controller for exact required shape."
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_timeentries_stats",
    "method": "get",
    "path": "/api/v1/time-entries/stats",
    "displayName": "Get time entry stats",
    "summary": "Get time entry stats",
    "description": "Returns time entry statistics.",
    "tags": [
      "Work Management v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "page",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "limit",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "sort",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "order",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "asc",
            "desc"
          ]
        }
      },
      {
        "name": "fields",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "search",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "query",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "type": "array",
          "items": {
            "type": "object",
            "additionalProperties": {}
          }
        },
        "pagination": {
          "type": "object",
          "properties": {
            "page": {
              "type": "integer"
            },
            "limit": {
              "type": "integer"
            },
            "total": {
              "type": "integer"
            },
            "totalPages": {
              "type": "integer"
            },
            "hasNext": {
              "type": "boolean"
            },
            "hasPrev": {
              "type": "boolean"
            }
          },
          "required": [
            "page",
            "limit",
            "total",
            "totalPages",
            "hasNext",
            "hasPrev"
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data",
        "pagination"
      ]
    }
  },
  {
    "id": "post-_api_v1_timeentries_stoptracking_sessionid",
    "method": "post",
    "path": "/api/v1/time-entries/stop-tracking/{sessionId}",
    "displayName": "Stop time tracking",
    "summary": "Stop time tracking",
    "description": "Stops active tracking session by session id.",
    "tags": [
      "Work Management v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "sessionId",
        "in": "path",
        "required": true,
        "description": "Active time-tracking session identifier.",
        "schema": {
          "type": "string",
          "description": "Active time-tracking session identifier."
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "additionalProperties": {},
      "description": "Controller/service-specific payload; see source route/controller for exact required shape."
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_timeentries_templates",
    "method": "get",
    "path": "/api/v1/time-entries/templates",
    "displayName": "List time entry templates",
    "summary": "List time entry templates",
    "description": "Lists available time entry templates.",
    "tags": [
      "Work Management v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "page",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "limit",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "sort",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "order",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "asc",
            "desc"
          ]
        }
      },
      {
        "name": "fields",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "search",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "query",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "type": "array",
          "items": {
            "type": "object",
            "additionalProperties": {}
          }
        },
        "pagination": {
          "type": "object",
          "properties": {
            "page": {
              "type": "integer"
            },
            "limit": {
              "type": "integer"
            },
            "total": {
              "type": "integer"
            },
            "totalPages": {
              "type": "integer"
            },
            "hasNext": {
              "type": "boolean"
            },
            "hasPrev": {
              "type": "boolean"
            }
          },
          "required": [
            "page",
            "limit",
            "total",
            "totalPages",
            "hasNext",
            "hasPrev"
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data",
        "pagination"
      ]
    }
  },
  {
    "id": "get-_api_v1_timeentries_id",
    "method": "get",
    "path": "/api/v1/time-entries/{id}",
    "displayName": "Get time entry",
    "summary": "Get time entry",
    "description": "Gets time entry UUID.",
    "tags": [
      "Work Management v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "UUID path identifier from underlying resource tables.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "UUID path identifier from underlying resource tables."
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "put-_api_v1_timeentries_id",
    "method": "put",
    "path": "/api/v1/time-entries/{id}",
    "displayName": "Update time entry",
    "summary": "Update time entry",
    "description": "Updates time entry UUID.",
    "tags": [
      "Work Management v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "UUID path identifier from underlying resource tables.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "UUID path identifier from underlying resource tables."
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "additionalProperties": {},
      "description": "Controller/service-specific payload; see source route/controller for exact required shape."
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "delete-_api_v1_timeentries_id",
    "method": "delete",
    "path": "/api/v1/time-entries/{id}",
    "displayName": "Delete time entry",
    "summary": "Delete time entry",
    "description": "Deletes time entry UUID.",
    "tags": [
      "Work Management v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "UUID path identifier from underlying resource tables.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "UUID path identifier from underlying resource tables."
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "additionalProperties": {},
      "description": "Controller/service-specific payload; see source route/controller for exact required shape."
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_timeperiods",
    "method": "get",
    "path": "/api/v1/time-periods",
    "displayName": "List time periods",
    "summary": "List time periods",
    "description": "Lists time periods via ApiTimeSheetController.listTimePeriods().",
    "tags": [
      "Work Management v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "page",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "limit",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "sort",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "order",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "asc",
            "desc"
          ]
        }
      },
      {
        "name": "fields",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "search",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "query",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "type": "array",
          "items": {
            "type": "object",
            "additionalProperties": {}
          }
        },
        "pagination": {
          "type": "object",
          "properties": {
            "page": {
              "type": "integer"
            },
            "limit": {
              "type": "integer"
            },
            "total": {
              "type": "integer"
            },
            "totalPages": {
              "type": "integer"
            },
            "hasNext": {
              "type": "boolean"
            },
            "hasPrev": {
              "type": "boolean"
            }
          },
          "required": [
            "page",
            "limit",
            "total",
            "totalPages",
            "hasNext",
            "hasPrev"
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data",
        "pagination"
      ]
    }
  },
  {
    "id": "post-_api_v1_timeperiods",
    "method": "post",
    "path": "/api/v1/time-periods",
    "displayName": "Create time period",
    "summary": "Create time period",
    "description": "Creates time period via ApiTimeSheetController.createTimePeriod().",
    "tags": [
      "Work Management v1"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "additionalProperties": {},
      "description": "Controller/service-specific payload; see source route/controller for exact required shape."
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_timeperiods_current",
    "method": "get",
    "path": "/api/v1/time-periods/current",
    "displayName": "Get current time period",
    "summary": "Get current time period",
    "description": "Current route delegates to ApiTimeSheetController.list() and does not call a dedicated current-period method.",
    "tags": [
      "Work Management v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "page",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "limit",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "sort",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "order",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "asc",
            "desc"
          ]
        }
      },
      {
        "name": "fields",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "search",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "query",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_timeperiods_id",
    "method": "get",
    "path": "/api/v1/time-periods/{id}",
    "displayName": "Get time period",
    "summary": "Get time period",
    "description": "Gets time period UUID via getTimePeriod().",
    "tags": [
      "Work Management v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "UUID path identifier from underlying resource tables.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "UUID path identifier from underlying resource tables."
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "put-_api_v1_timeperiods_id",
    "method": "put",
    "path": "/api/v1/time-periods/{id}",
    "displayName": "Update time period",
    "summary": "Update time period",
    "description": "Updates time period UUID via updateTimePeriod().",
    "tags": [
      "Work Management v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "UUID path identifier from underlying resource tables.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "UUID path identifier from underlying resource tables."
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "additionalProperties": {},
      "description": "Controller/service-specific payload; see source route/controller for exact required shape."
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "delete-_api_v1_timeperiods_id",
    "method": "delete",
    "path": "/api/v1/time-periods/{id}",
    "displayName": "Delete time period",
    "summary": "Delete time period",
    "description": "Deletes time period UUID via deleteTimePeriod().",
    "tags": [
      "Work Management v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "UUID path identifier from underlying resource tables.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "UUID path identifier from underlying resource tables."
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "additionalProperties": {},
      "description": "Controller/service-specific payload; see source route/controller for exact required shape."
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "post-_api_v1_timeperiods_id_close",
    "method": "post",
    "path": "/api/v1/time-periods/{id}/close",
    "displayName": "Close time period",
    "summary": "Close time period",
    "description": "Current route delegates to ApiTimeSheetController.update() (time sheet update flow), not dedicated time-period close logic.",
    "tags": [
      "Work Management v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "UUID path identifier from underlying resource tables.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "UUID path identifier from underlying resource tables."
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "additionalProperties": {},
      "description": "Controller/service-specific payload; see source route/controller for exact required shape."
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "post-_api_v1_timeperiods_id_reopen",
    "method": "post",
    "path": "/api/v1/time-periods/{id}/reopen",
    "displayName": "Reopen time period",
    "summary": "Reopen time period",
    "description": "Current route delegates to ApiTimeSheetController.update() (time sheet update flow), not dedicated time-period reopen logic.",
    "tags": [
      "Work Management v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "UUID path identifier from underlying resource tables.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "UUID path identifier from underlying resource tables."
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "additionalProperties": {},
      "description": "Controller/service-specific payload; see source route/controller for exact required shape."
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_timesheets",
    "method": "get",
    "path": "/api/v1/time-sheets",
    "displayName": "List time sheets",
    "summary": "List time sheets",
    "description": "Lists time sheets via ApiTimeSheetController.list().",
    "tags": [
      "Work Management v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "page",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "limit",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "sort",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "order",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "asc",
            "desc"
          ]
        }
      },
      {
        "name": "fields",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "search",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "query",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "type": "array",
          "items": {
            "type": "object",
            "additionalProperties": {}
          }
        },
        "pagination": {
          "type": "object",
          "properties": {
            "page": {
              "type": "integer"
            },
            "limit": {
              "type": "integer"
            },
            "total": {
              "type": "integer"
            },
            "totalPages": {
              "type": "integer"
            },
            "hasNext": {
              "type": "boolean"
            },
            "hasPrev": {
              "type": "boolean"
            }
          },
          "required": [
            "page",
            "limit",
            "total",
            "totalPages",
            "hasNext",
            "hasPrev"
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data",
        "pagination"
      ]
    }
  },
  {
    "id": "post-_api_v1_timesheets",
    "method": "post",
    "path": "/api/v1/time-sheets",
    "displayName": "Create time sheet",
    "summary": "Create time sheet",
    "description": "Creates time sheet via create() path.",
    "tags": [
      "Work Management v1"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "user_id": {
          "type": "string",
          "format": "uuid"
        },
        "period_id": {
          "type": "string",
          "format": "uuid"
        },
        "status": {
          "type": "string"
        },
        "notes": {
          "type": "string"
        }
      }
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "post-_api_v1_timesheets_bulk",
    "method": "post",
    "path": "/api/v1/time-sheets/bulk",
    "displayName": "Bulk time sheet operation",
    "summary": "Bulk time sheet operation",
    "description": "Current route delegates to ApiTimeSheetController.list() (read path) instead of bulk approval/update logic.",
    "tags": [
      "Work Management v1"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "additionalProperties": {},
      "description": "Controller/service-specific payload; see source route/controller for exact required shape."
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_timesheets_export",
    "method": "get",
    "path": "/api/v1/time-sheets/export",
    "displayName": "Export time sheets",
    "summary": "Export time sheets",
    "description": "Exports time sheets using ApiTimeSheetController.export().",
    "tags": [
      "Work Management v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "page",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "limit",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "sort",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "order",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "asc",
            "desc"
          ]
        }
      },
      {
        "name": "fields",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "search",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "query",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "type": "array",
          "items": {
            "type": "object",
            "additionalProperties": {}
          }
        },
        "pagination": {
          "type": "object",
          "properties": {
            "page": {
              "type": "integer"
            },
            "limit": {
              "type": "integer"
            },
            "total": {
              "type": "integer"
            },
            "totalPages": {
              "type": "integer"
            },
            "hasNext": {
              "type": "boolean"
            },
            "hasPrev": {
              "type": "boolean"
            }
          },
          "required": [
            "page",
            "limit",
            "total",
            "totalPages",
            "hasNext",
            "hasPrev"
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data",
        "pagination"
      ]
    }
  },
  {
    "id": "get-_api_v1_timesheets_search",
    "method": "get",
    "path": "/api/v1/time-sheets/search",
    "displayName": "Search time sheets",
    "summary": "Search time sheets",
    "description": "Current route delegates to ApiTimeSheetController.list() rather than search().",
    "tags": [
      "Work Management v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "page",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "limit",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "sort",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "order",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "asc",
            "desc"
          ]
        }
      },
      {
        "name": "fields",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "search",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "query",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "type": "array",
          "items": {
            "type": "object",
            "additionalProperties": {}
          }
        },
        "pagination": {
          "type": "object",
          "properties": {
            "page": {
              "type": "integer"
            },
            "limit": {
              "type": "integer"
            },
            "total": {
              "type": "integer"
            },
            "totalPages": {
              "type": "integer"
            },
            "hasNext": {
              "type": "boolean"
            },
            "hasPrev": {
              "type": "boolean"
            }
          },
          "required": [
            "page",
            "limit",
            "total",
            "totalPages",
            "hasNext",
            "hasPrev"
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data",
        "pagination"
      ]
    }
  },
  {
    "id": "get-_api_v1_timesheets_id",
    "method": "get",
    "path": "/api/v1/time-sheets/{id}",
    "displayName": "Get time sheet",
    "summary": "Get time sheet",
    "description": "Gets time sheet UUID with details via getWithDetails().",
    "tags": [
      "Work Management v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "UUID path identifier from underlying resource tables.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "UUID path identifier from underlying resource tables."
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "put-_api_v1_timesheets_id",
    "method": "put",
    "path": "/api/v1/time-sheets/{id}",
    "displayName": "Update time sheet",
    "summary": "Update time sheet",
    "description": "Updates time sheet UUID.",
    "tags": [
      "Work Management v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "UUID path identifier from underlying resource tables.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "UUID path identifier from underlying resource tables."
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "additionalProperties": {},
      "description": "Controller/service-specific payload; see source route/controller for exact required shape."
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "delete-_api_v1_timesheets_id",
    "method": "delete",
    "path": "/api/v1/time-sheets/{id}",
    "displayName": "Delete time sheet",
    "summary": "Delete time sheet",
    "description": "Deletes time sheet UUID via ApiBase delete path.",
    "tags": [
      "Work Management v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "UUID path identifier from underlying resource tables.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "UUID path identifier from underlying resource tables."
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "additionalProperties": {},
      "description": "Controller/service-specific payload; see source route/controller for exact required shape."
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "post-_api_v1_timesheets_id_addentry",
    "method": "post",
    "path": "/api/v1/time-sheets/{id}/add-entry",
    "displayName": "Add time sheet entry",
    "summary": "Add time sheet entry",
    "description": "Current route delegates to ApiTimeSheetController.create() (time sheet create path), not entry-add-specific logic.",
    "tags": [
      "Work Management v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "UUID path identifier from underlying resource tables.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "UUID path identifier from underlying resource tables."
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "additionalProperties": {},
      "description": "Controller/service-specific payload; see source route/controller for exact required shape."
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "post-_api_v1_timesheets_id_approve",
    "method": "post",
    "path": "/api/v1/time-sheets/{id}/approve",
    "displayName": "Approve time sheet",
    "summary": "Approve time sheet",
    "description": "Approves time sheet UUID via approve().",
    "tags": [
      "Work Management v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "UUID path identifier from underlying resource tables.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "UUID path identifier from underlying resource tables."
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "additionalProperties": {},
      "description": "Controller/service-specific payload; see source route/controller for exact required shape."
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_timesheets_id_entries",
    "method": "get",
    "path": "/api/v1/time-sheets/{id}/entries",
    "displayName": "List time sheet entries",
    "summary": "List time sheet entries",
    "description": "Current route delegates to ApiTimeSheetController.list() rather than a per-sheet entries reader.",
    "tags": [
      "Work Management v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "UUID path identifier from underlying resource tables.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "UUID path identifier from underlying resource tables."
        }
      },
      {
        "name": "page",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "limit",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "sort",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "order",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "asc",
            "desc"
          ]
        }
      },
      {
        "name": "fields",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "search",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "query",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "type": "array",
          "items": {
            "type": "object",
            "additionalProperties": {}
          }
        },
        "pagination": {
          "type": "object",
          "properties": {
            "page": {
              "type": "integer"
            },
            "limit": {
              "type": "integer"
            },
            "total": {
              "type": "integer"
            },
            "totalPages": {
              "type": "integer"
            },
            "hasNext": {
              "type": "boolean"
            },
            "hasPrev": {
              "type": "boolean"
            }
          },
          "required": [
            "page",
            "limit",
            "total",
            "totalPages",
            "hasNext",
            "hasPrev"
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data",
        "pagination"
      ]
    }
  },
  {
    "id": "post-_api_v1_timesheets_id_reject",
    "method": "post",
    "path": "/api/v1/time-sheets/{id}/reject",
    "displayName": "Reject time sheet",
    "summary": "Reject time sheet",
    "description": "Current route delegates to ApiTimeSheetController.update() instead of reject-specific flow.",
    "tags": [
      "Work Management v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "UUID path identifier from underlying resource tables.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "UUID path identifier from underlying resource tables."
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "additionalProperties": {},
      "description": "Controller/service-specific payload; see source route/controller for exact required shape."
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "delete-_api_v1_timesheets_id_removeentry",
    "method": "delete",
    "path": "/api/v1/time-sheets/{id}/remove-entry",
    "displayName": "Remove time sheet entry",
    "summary": "Remove time sheet entry",
    "description": "Current route delegates to ApiTimeSheetController.delete() instead of entry-remove-specific flow.",
    "tags": [
      "Work Management v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "UUID path identifier from underlying resource tables.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "UUID path identifier from underlying resource tables."
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "additionalProperties": {},
      "description": "Controller/service-specific payload; see source route/controller for exact required shape."
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "post-_api_v1_timesheets_id_requestchanges",
    "method": "post",
    "path": "/api/v1/time-sheets/{id}/request-changes",
    "displayName": "Request time sheet changes",
    "summary": "Request time sheet changes",
    "description": "Requests changes via requestChanges().",
    "tags": [
      "Work Management v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "UUID path identifier from underlying resource tables.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "UUID path identifier from underlying resource tables."
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "additionalProperties": {},
      "description": "Controller/service-specific payload; see source route/controller for exact required shape."
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "post-_api_v1_timesheets_id_reverseapproval",
    "method": "post",
    "path": "/api/v1/time-sheets/{id}/reverse-approval",
    "displayName": "Reverse time sheet approval",
    "summary": "Reverse time sheet approval",
    "description": "Reverses approval via reverseApproval().",
    "tags": [
      "Work Management v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "UUID path identifier from underlying resource tables.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "UUID path identifier from underlying resource tables."
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "additionalProperties": {},
      "description": "Controller/service-specific payload; see source route/controller for exact required shape."
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "post-_api_v1_timesheets_id_submit",
    "method": "post",
    "path": "/api/v1/time-sheets/{id}/submit",
    "displayName": "Submit time sheet",
    "summary": "Submit time sheet",
    "description": "Submits time sheet for approval via submit().",
    "tags": [
      "Work Management v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "UUID path identifier from underlying resource tables.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "UUID path identifier from underlying resource tables."
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "additionalProperties": {},
      "description": "Controller/service-specific payload; see source route/controller for exact required shape."
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_timesheets_id_summary",
    "method": "get",
    "path": "/api/v1/time-sheets/{id}/summary",
    "displayName": "Get time sheet summary",
    "summary": "Get time sheet summary",
    "description": "Current route delegates to ApiTimeSheetController.list() instead of summary-specific computation.",
    "tags": [
      "Work Management v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "UUID path identifier from underlying resource tables.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "UUID path identifier from underlying resource tables."
        }
      },
      {
        "name": "page",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "limit",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "sort",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "order",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "asc",
            "desc"
          ]
        }
      },
      {
        "name": "fields",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "search",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "query",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "type": "array",
          "items": {
            "type": "object",
            "additionalProperties": {}
          }
        },
        "pagination": {
          "type": "object",
          "properties": {
            "page": {
              "type": "integer"
            },
            "limit": {
              "type": "integer"
            },
            "total": {
              "type": "integer"
            },
            "totalPages": {
              "type": "integer"
            },
            "hasNext": {
              "type": "boolean"
            },
            "hasPrev": {
              "type": "boolean"
            }
          },
          "required": [
            "page",
            "limit",
            "total",
            "totalPages",
            "hasNext",
            "hasPrev"
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data",
        "pagination"
      ]
    }
  },
  {
    "id": "get-_api_v1_tickets_priorities",
    "method": "get",
    "path": "/api/v1/tickets/priorities",
    "displayName": "List ticket priorities",
    "summary": "List ticket priorities",
    "description": "Returns the tenant ticket priorities (item_type=ticket), ordered by name.",
    "tags": [
      "Work Management v1"
    ],
    "approvalRequired": false,
    "parameters": [],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_tickets_statuses",
    "method": "get",
    "path": "/api/v1/tickets/statuses",
    "displayName": "List ticket statuses",
    "summary": "List ticket statuses",
    "description": "Returns board-owned ticket statuses for the tenant, optionally filtered by board_id, sorted by board then order_number.",
    "tags": [
      "Work Management v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "board_id",
        "in": "query",
        "required": false,
        "description": "Filter statuses to this board.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Filter statuses to this board."
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "put-_api_v1_tickets_id_comments_commentid",
    "method": "put",
    "path": "/api/v1/tickets/{id}/comments/{commentId}",
    "displayName": "Update a ticket comment",
    "summary": "Update a ticket comment",
    "description": "Updates the text of a comment on a ticket. Comment text must be 1–5000 visible characters.",
    "tags": [
      "Work Management v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Ticket UUID.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Ticket UUID."
        }
      },
      {
        "name": "commentId",
        "in": "path",
        "required": true,
        "description": "Comment UUID.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Comment UUID."
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "comment_text": {
          "type": "string",
          "minLength": 1,
          "maxLength": 5000,
          "description": "Updated comment text (1–5000 visible chars)."
        }
      },
      "required": [
        "comment_text"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "post-_api_v1_tickets_id_comments_commentid_reactions",
    "method": "post",
    "path": "/api/v1/tickets/{id}/comments/{commentId}/reactions",
    "displayName": "Toggle a comment reaction",
    "summary": "Toggle a comment reaction",
    "description": "Adds or removes the given emoji reaction on a comment for the authenticated user. Returns { added: boolean } indicating whether the reaction was added (true) or removed (false).",
    "tags": [
      "Work Management v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Ticket UUID.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Ticket UUID."
        }
      },
      {
        "name": "commentId",
        "in": "path",
        "required": true,
        "description": "Comment UUID.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Comment UUID."
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "emoji": {
          "type": "string",
          "description": "Emoji to toggle on the comment."
        }
      },
      "required": [
        "emoji"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_tickets_id_documents",
    "method": "get",
    "path": "/api/v1/tickets/{id}/documents",
    "displayName": "List ticket documents",
    "summary": "List ticket documents",
    "description": "Returns the documents (file attachments) associated with a ticket.",
    "tags": [
      "Work Management v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "UUID path identifier from underlying resource tables.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "UUID path identifier from underlying resource tables."
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "post-_api_v1_tickets_id_documents",
    "method": "post",
    "path": "/api/v1/tickets/{id}/documents",
    "displayName": "Upload a ticket document",
    "summary": "Upload a ticket document",
    "description": "Uploads a file as a document attachment to a ticket. Send multipart/form-data with a `file` field. Returns the created document.",
    "tags": [
      "Work Management v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "UUID path identifier from underlying resource tables.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "UUID path identifier from underlying resource tables."
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_tickets_id_documents_documentid",
    "method": "get",
    "path": "/api/v1/tickets/{id}/documents/{documentId}",
    "displayName": "Download a ticket document",
    "summary": "Download a ticket document",
    "description": "Downloads a specific document attached to a ticket as binary data with Content-Type and Content-Disposition headers.",
    "tags": [
      "Work Management v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Ticket UUID.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Ticket UUID."
        }
      },
      {
        "name": "documentId",
        "in": "path",
        "required": true,
        "description": "Document UUID.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Document UUID."
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "delete-_api_v1_tickets_id_documents_documentid",
    "method": "delete",
    "path": "/api/v1/tickets/{id}/documents/{documentId}",
    "displayName": "Delete a ticket document",
    "summary": "Delete a ticket document",
    "description": "Removes a document from a ticket.",
    "tags": [
      "Work Management v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Ticket UUID.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Ticket UUID."
        }
      },
      {
        "name": "documentId",
        "in": "path",
        "required": true,
        "description": "Document UUID.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Document UUID."
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_tickets_id_materials",
    "method": "get",
    "path": "/api/v1/tickets/{id}/materials",
    "displayName": "List ticket materials",
    "summary": "List ticket materials",
    "description": "Returns the materials (service items/supplies) recorded against a ticket.",
    "tags": [
      "Work Management v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "UUID path identifier from underlying resource tables.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "UUID path identifier from underlying resource tables."
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "post-_api_v1_tickets_id_materials",
    "method": "post",
    "path": "/api/v1/tickets/{id}/materials",
    "displayName": "Add a ticket material",
    "summary": "Add a ticket material",
    "description": "Associates a service item (material/supply) with a ticket, specifying quantity, rate, and currency. Returns the created material.",
    "tags": [
      "Work Management v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "UUID path identifier from underlying resource tables.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "UUID path identifier from underlying resource tables."
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "service_id": {
          "type": "string",
          "format": "uuid"
        },
        "quantity": {
          "type": "number",
          "exclusiveMinimum": 0
        },
        "rate": {
          "type": "number",
          "minimum": 0
        },
        "currency_code": {
          "type": "string",
          "minLength": 3,
          "maxLength": 3
        },
        "description": {
          "type": [
            "string",
            "null"
          ],
          "maxLength": 1000
        }
      },
      "required": [
        "service_id",
        "quantity",
        "rate",
        "currency_code"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_quotes",
    "method": "get",
    "path": "/api/v1/quotes",
    "displayName": "List quotes",
    "summary": "List quotes",
    "description": "Lists quotes via ApiQuoteController.list() with authorization-aware filtering.",
    "tags": [
      "Quotes & Contracts v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "page",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "limit",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "sort",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "order",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "asc",
            "desc"
          ]
        }
      },
      {
        "name": "search",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "status",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "include_items",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ]
        }
      },
      {
        "name": "include_client",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ]
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "type": "array",
          "items": {
            "type": "object",
            "additionalProperties": {}
          }
        },
        "pagination": {
          "type": "object",
          "properties": {
            "page": {
              "type": "integer"
            },
            "limit": {
              "type": "integer"
            },
            "total": {
              "type": "integer"
            },
            "totalPages": {
              "type": "integer"
            }
          },
          "required": [
            "page",
            "limit",
            "total",
            "totalPages"
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        },
        "_links": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "post-_api_v1_quotes",
    "method": "post",
    "path": "/api/v1/quotes",
    "displayName": "Create quote",
    "summary": "Create quote",
    "description": "Creates quote via ApiQuoteController.create().",
    "tags": [
      "Quotes & Contracts v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "page",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "limit",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "sort",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "order",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "asc",
            "desc"
          ]
        }
      },
      {
        "name": "search",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "status",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "include_items",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ]
        }
      },
      {
        "name": "include_client",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ]
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "client_id": {
          "type": "string",
          "format": "uuid"
        },
        "title": {
          "type": "string"
        },
        "quote_number": {
          "type": "string"
        },
        "valid_until": {
          "type": "string"
        },
        "notes": {
          "type": "string"
        },
        "terms": {
          "type": "string"
        },
        "items": {
          "type": "array",
          "items": {
            "type": "object",
            "additionalProperties": {}
          }
        }
      },
      "required": [
        "client_id"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_quotes_id",
    "method": "get",
    "path": "/api/v1/quotes/{id}",
    "displayName": "Get quote",
    "summary": "Get quote",
    "description": "Gets quote UUID via ApiQuoteController.getById().",
    "tags": [
      "Quotes & Contracts v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Quote UUID from quotes.quote_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Quote UUID from quotes.quote_id."
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "put-_api_v1_quotes_id",
    "method": "put",
    "path": "/api/v1/quotes/{id}",
    "displayName": "Update quote",
    "summary": "Update quote",
    "description": "Updates quote UUID via ApiQuoteController.update().",
    "tags": [
      "Quotes & Contracts v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Quote UUID from quotes.quote_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Quote UUID from quotes.quote_id."
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "additionalProperties": {},
      "description": "Controller/service-specific payload; see quote/contract controller schemas for exact required fields."
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "delete-_api_v1_quotes_id",
    "method": "delete",
    "path": "/api/v1/quotes/{id}",
    "displayName": "Delete quote",
    "summary": "Delete quote",
    "description": "Deletes quote UUID via ApiQuoteController.delete().",
    "tags": [
      "Quotes & Contracts v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Quote UUID from quotes.quote_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Quote UUID from quotes.quote_id."
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_quotes_id_activities",
    "method": "get",
    "path": "/api/v1/quotes/{id}/activities",
    "displayName": "List quote activities",
    "summary": "List quote activities",
    "description": "Lists quote activity history via listActivities().",
    "tags": [
      "Quotes & Contracts v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Quote UUID from quotes.quote_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Quote UUID from quotes.quote_id."
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "post-_api_v1_quotes_id_approve",
    "method": "post",
    "path": "/api/v1/quotes/{id}/approve",
    "displayName": "Approve quote",
    "summary": "Approve quote",
    "description": "Approves quote pending-approval state via approve(); includes self-approval guard.",
    "tags": [
      "Quotes & Contracts v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Quote UUID from quotes.quote_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Quote UUID from quotes.quote_id."
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "additionalProperties": {},
      "description": "Controller/service-specific payload; see quote/contract controller schemas for exact required fields."
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "post-_api_v1_quotes_id_convert",
    "method": "post",
    "path": "/api/v1/quotes/{id}/convert",
    "displayName": "Convert quote",
    "summary": "Convert quote",
    "description": "Converts quote to downstream entities via convert().",
    "tags": [
      "Quotes & Contracts v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Quote UUID from quotes.quote_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Quote UUID from quotes.quote_id."
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "additionalProperties": {},
      "description": "Controller/service-specific payload; see quote/contract controller schemas for exact required fields."
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_quotes_id_convert_preview",
    "method": "get",
    "path": "/api/v1/quotes/{id}/convert/preview",
    "displayName": "Preview quote conversion",
    "summary": "Preview quote conversion",
    "description": "Returns conversion preview via conversionPreview().",
    "tags": [
      "Quotes & Contracts v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Quote UUID from quotes.quote_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Quote UUID from quotes.quote_id."
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_quotes_id_items",
    "method": "get",
    "path": "/api/v1/quotes/{id}/items",
    "displayName": "List quote items",
    "summary": "List quote items",
    "description": "Lists quote items via listItems().",
    "tags": [
      "Quotes & Contracts v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Quote UUID from quotes.quote_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Quote UUID from quotes.quote_id."
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "post-_api_v1_quotes_id_items",
    "method": "post",
    "path": "/api/v1/quotes/{id}/items",
    "displayName": "Add quote item",
    "summary": "Add quote item",
    "description": "Adds quote item via addItem().",
    "tags": [
      "Quotes & Contracts v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Quote UUID from quotes.quote_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Quote UUID from quotes.quote_id."
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "additionalProperties": {},
      "description": "Controller/service-specific payload; see quote/contract controller schemas for exact required fields."
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "put-_api_v1_quotes_id_items_itemid",
    "method": "put",
    "path": "/api/v1/quotes/{id}/items/{itemId}",
    "displayName": "Update quote item",
    "summary": "Update quote item",
    "description": "Updates quote item via updateItem().",
    "tags": [
      "Quotes & Contracts v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Quote UUID from quotes.quote_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Quote UUID from quotes.quote_id."
        }
      },
      {
        "name": "itemId",
        "in": "path",
        "required": true,
        "description": "ItemId path parameter.",
        "schema": {
          "type": "string"
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "additionalProperties": {},
      "description": "Controller/service-specific payload; see quote/contract controller schemas for exact required fields."
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "delete-_api_v1_quotes_id_items_itemid",
    "method": "delete",
    "path": "/api/v1/quotes/{id}/items/{itemId}",
    "displayName": "Delete quote item",
    "summary": "Delete quote item",
    "description": "Deletes quote item via deleteItem().",
    "tags": [
      "Quotes & Contracts v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Quote UUID from quotes.quote_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Quote UUID from quotes.quote_id."
        }
      },
      {
        "name": "itemId",
        "in": "path",
        "required": true,
        "description": "ItemId path parameter.",
        "schema": {
          "type": "string"
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "post-_api_v1_quotes_id_items_reorder",
    "method": "post",
    "path": "/api/v1/quotes/{id}/items/reorder",
    "displayName": "Reorder quote items",
    "summary": "Reorder quote items",
    "description": "Reorders quote item sequence via reorderItems().",
    "tags": [
      "Quotes & Contracts v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Quote UUID from quotes.quote_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Quote UUID from quotes.quote_id."
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "additionalProperties": {},
      "description": "Controller/service-specific payload; see quote/contract controller schemas for exact required fields."
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "post-_api_v1_quotes_id_remind",
    "method": "post",
    "path": "/api/v1/quotes/{id}/remind",
    "displayName": "Send quote reminder",
    "summary": "Send quote reminder",
    "description": "Sends reminder for quote via remind().",
    "tags": [
      "Quotes & Contracts v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Quote UUID from quotes.quote_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Quote UUID from quotes.quote_id."
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "additionalProperties": {},
      "description": "Controller/service-specific payload; see quote/contract controller schemas for exact required fields."
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "post-_api_v1_quotes_id_requestchanges",
    "method": "post",
    "path": "/api/v1/quotes/{id}/request-changes",
    "displayName": "Request quote changes",
    "summary": "Request quote changes",
    "description": "Requests changes on pending-approval quote via requestChanges().",
    "tags": [
      "Quotes & Contracts v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Quote UUID from quotes.quote_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Quote UUID from quotes.quote_id."
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "additionalProperties": {},
      "description": "Controller/service-specific payload; see quote/contract controller schemas for exact required fields."
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "post-_api_v1_quotes_id_resend",
    "method": "post",
    "path": "/api/v1/quotes/{id}/resend",
    "displayName": "Resend quote",
    "summary": "Resend quote",
    "description": "Resends quote via resend().",
    "tags": [
      "Quotes & Contracts v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Quote UUID from quotes.quote_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Quote UUID from quotes.quote_id."
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "additionalProperties": {},
      "description": "Controller/service-specific payload; see quote/contract controller schemas for exact required fields."
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_quotes_id_revisions",
    "method": "get",
    "path": "/api/v1/quotes/{id}/revisions",
    "displayName": "List quote revisions",
    "summary": "List quote revisions",
    "description": "Lists quote versions via listVersions().",
    "tags": [
      "Quotes & Contracts v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Quote UUID from quotes.quote_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Quote UUID from quotes.quote_id."
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "post-_api_v1_quotes_id_revisions",
    "method": "post",
    "path": "/api/v1/quotes/{id}/revisions",
    "displayName": "Create quote revision",
    "summary": "Create quote revision",
    "description": "Creates quote revision via createRevision().",
    "tags": [
      "Quotes & Contracts v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Quote UUID from quotes.quote_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Quote UUID from quotes.quote_id."
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "additionalProperties": {},
      "description": "Controller/service-specific payload; see quote/contract controller schemas for exact required fields."
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "post-_api_v1_quotes_id_send",
    "method": "post",
    "path": "/api/v1/quotes/{id}/send",
    "displayName": "Send quote",
    "summary": "Send quote",
    "description": "Sends quote to recipient workflow via send().",
    "tags": [
      "Quotes & Contracts v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Quote UUID from quotes.quote_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Quote UUID from quotes.quote_id."
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "additionalProperties": {},
      "description": "Controller/service-specific payload; see quote/contract controller schemas for exact required fields."
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "post-_api_v1_quotes_id_submitforapproval",
    "method": "post",
    "path": "/api/v1/quotes/{id}/submit-for-approval",
    "displayName": "Submit quote for approval",
    "summary": "Submit quote for approval",
    "description": "Moves quote to pending-approval state via submitForApproval().",
    "tags": [
      "Quotes & Contracts v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Quote UUID from quotes.quote_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Quote UUID from quotes.quote_id."
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "additionalProperties": {},
      "description": "Controller/service-specific payload; see quote/contract controller schemas for exact required fields."
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "get-_api_v1_contracts",
    "method": "get",
    "path": "/api/v1/contracts",
    "displayName": "List contracts",
    "summary": "List contracts",
    "description": "Lists contracts via ApiContractLineController.listContracts() (v2 controller mounted under v1 route).",
    "tags": [
      "Quotes & Contracts v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "page",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "limit",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "sort",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "order",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "asc",
            "desc"
          ]
        }
      },
      {
        "name": "search",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "status",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "include_items",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ]
        }
      },
      {
        "name": "include_client",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ]
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "type": "array",
          "items": {
            "type": "object",
            "additionalProperties": {}
          }
        },
        "pagination": {
          "type": "object",
          "properties": {
            "page": {
              "type": "integer"
            },
            "limit": {
              "type": "integer"
            },
            "total": {
              "type": "integer"
            },
            "totalPages": {
              "type": "integer"
            }
          },
          "required": [
            "page",
            "limit",
            "total",
            "totalPages"
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        },
        "_links": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "post-_api_v1_contracts",
    "method": "post",
    "path": "/api/v1/contracts",
    "displayName": "Create contract",
    "summary": "Create contract",
    "description": "Creates contract via ApiContractLineController.createContract() (v2 controller mounted under v1 route).",
    "tags": [
      "Quotes & Contracts v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "page",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "limit",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "sort",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "order",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "asc",
            "desc"
          ]
        }
      },
      {
        "name": "search",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "status",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "include_items",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ]
        }
      },
      {
        "name": "include_client",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ]
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "client_id": {
          "type": "string",
          "format": "uuid"
        },
        "contract_name": {
          "type": "string"
        },
        "start_date": {
          "type": "string"
        },
        "end_date": {
          "type": "string"
        },
        "billing_frequency": {
          "type": "string"
        }
      },
      "required": [
        "client_id"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "post-_api_v1_contracts_contractid_contractlines",
    "method": "post",
    "path": "/api/v1/contracts/{contractId}/contract-lines",
    "displayName": "Attach contract line",
    "summary": "Attach contract line",
    "description": "Attaches contract line to contract via addContractLine() using body contract_line_id/custom_rate.",
    "tags": [
      "Quotes & Contracts v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "contractId",
        "in": "path",
        "required": true,
        "description": "Contract UUID from contracts.contract_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Contract UUID from contracts.contract_id."
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "contract_line_id": {
          "type": "string",
          "format": "uuid"
        },
        "custom_rate": {
          "type": "number"
        }
      },
      "required": [
        "contract_line_id"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "delete-_api_v1_contracts_contractid_contractlines_contractlineid",
    "method": "delete",
    "path": "/api/v1/contracts/{contractId}/contract-lines/{contractLineId}",
    "displayName": "Detach contract line",
    "summary": "Detach contract line",
    "description": "Detaches contract line from contract via removeContractLine().",
    "tags": [
      "Quotes & Contracts v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "contractId",
        "in": "path",
        "required": true,
        "description": "Contract UUID from contracts.contract_id.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "description": "Contract UUID from contracts.contract_id."
        }
      },
      {
        "name": "contractLineId",
        "in": "path",
        "required": true,
        "description": "ContractLineId path parameter.",
        "schema": {
          "type": "string"
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          ]
        },
        "meta": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "data"
      ]
    }
  },
  {
    "id": "post-_api_v1_featureaccess",
    "method": "post",
    "path": "/api/v1/feature-access",
    "displayName": "Check feature access",
    "summary": "Check feature access",
    "description": "Checks feature access via ApiPermissionController.checkFeatureAccess() using API key auth and permission read checks.",
    "tags": [
      "Meta & Utility v1"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "user_id": {
          "type": "string",
          "format": "uuid"
        },
        "feature_name": {
          "type": "string"
        }
      },
      "required": [
        "feature_name"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            },
            {
              "type": "string"
            },
            {
              "type": "number"
            },
            {
              "type": "boolean"
            },
            {
              "type": "null"
            }
          ]
        },
        "flags": {
          "type": "object",
          "additionalProperties": {}
        },
        "context": {
          "type": "object",
          "additionalProperties": {}
        },
        "enabled": {
          "type": "boolean"
        },
        "reason": {
          "type": "string"
        },
        "usageStatsEnabled": {
          "type": "boolean"
        },
        "controlledBy": {
          "type": "string"
        },
        "message": {
          "type": "string"
        },
        "success": {
          "type": "boolean"
        }
      }
    }
  },
  {
    "id": "get-_api_v1_featureflags",
    "method": "get",
    "path": "/api/v1/feature-flags",
    "displayName": "Get feature flags",
    "summary": "Get feature flags",
    "description": "Returns feature flags for current session user; route uses getSession() and featureFlags service.",
    "tags": [
      "Meta & Utility v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "format",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "flags",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "period",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "language",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "package_name",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "version",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            },
            {
              "type": "string"
            },
            {
              "type": "number"
            },
            {
              "type": "boolean"
            },
            {
              "type": "null"
            }
          ]
        },
        "flags": {
          "type": "object",
          "additionalProperties": {}
        },
        "context": {
          "type": "object",
          "additionalProperties": {}
        },
        "enabled": {
          "type": "boolean"
        },
        "reason": {
          "type": "string"
        },
        "usageStatsEnabled": {
          "type": "boolean"
        },
        "controlledBy": {
          "type": "string"
        },
        "message": {
          "type": "string"
        },
        "success": {
          "type": "boolean"
        }
      }
    }
  },
  {
    "id": "post-_api_v1_featureflags",
    "method": "post",
    "path": "/api/v1/feature-flags",
    "displayName": "Evaluate feature flags with custom context",
    "summary": "Evaluate feature flags with custom context",
    "description": "Evaluates requested/all flags with optional custom context payload; requires session user.",
    "tags": [
      "Meta & Utility v1"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "flags": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "context": {
          "type": "object",
          "properties": {
            "userRole": {
              "type": "string"
            },
            "companySize": {
              "type": "string",
              "enum": [
                "small",
                "medium",
                "large",
                "enterprise"
              ]
            },
            "subscriptionPlan": {
              "type": "string"
            },
            "customProperties": {
              "type": "object",
              "additionalProperties": {}
            }
          }
        }
      }
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            },
            {
              "type": "string"
            },
            {
              "type": "number"
            },
            {
              "type": "boolean"
            },
            {
              "type": "null"
            }
          ]
        },
        "flags": {
          "type": "object",
          "additionalProperties": {}
        },
        "context": {
          "type": "object",
          "additionalProperties": {}
        },
        "enabled": {
          "type": "boolean"
        },
        "reason": {
          "type": "string"
        },
        "usageStatsEnabled": {
          "type": "boolean"
        },
        "controlledBy": {
          "type": "string"
        },
        "message": {
          "type": "string"
        },
        "success": {
          "type": "boolean"
        }
      }
    }
  },
  {
    "id": "get-_api_v1_meta_docs",
    "method": "get",
    "path": "/api/v1/meta/docs",
    "displayName": "Get API docs",
    "summary": "Get API docs",
    "description": "Returns Swagger UI HTML or redirects to OpenAPI endpoint depending on format query.",
    "tags": [
      "Meta & Utility v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "format",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "flags",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "period",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "language",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "package_name",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "version",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      }
    ]
  },
  {
    "id": "get-_api_v1_meta_endpoints",
    "method": "get",
    "path": "/api/v1/meta/endpoints",
    "displayName": "List API endpoints metadata",
    "summary": "List API endpoints metadata",
    "description": "Returns endpoint inventory metadata via ApiMetadataController.getEndpoints().",
    "tags": [
      "Meta & Utility v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "format",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "flags",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "period",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "language",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "package_name",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "version",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            },
            {
              "type": "string"
            },
            {
              "type": "number"
            },
            {
              "type": "boolean"
            },
            {
              "type": "null"
            }
          ]
        },
        "flags": {
          "type": "object",
          "additionalProperties": {}
        },
        "context": {
          "type": "object",
          "additionalProperties": {}
        },
        "enabled": {
          "type": "boolean"
        },
        "reason": {
          "type": "string"
        },
        "usageStatsEnabled": {
          "type": "boolean"
        },
        "controlledBy": {
          "type": "string"
        },
        "message": {
          "type": "string"
        },
        "success": {
          "type": "boolean"
        }
      }
    }
  },
  {
    "id": "get-_api_v1_meta_health",
    "method": "get",
    "path": "/api/v1/meta/health",
    "displayName": "Get API health metadata",
    "summary": "Get API health metadata",
    "description": "Returns API health metadata via ApiMetadataController.getHealth().",
    "tags": [
      "Meta & Utility v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "format",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "flags",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "period",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "language",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "package_name",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "version",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            },
            {
              "type": "string"
            },
            {
              "type": "number"
            },
            {
              "type": "boolean"
            },
            {
              "type": "null"
            }
          ]
        },
        "flags": {
          "type": "object",
          "additionalProperties": {}
        },
        "context": {
          "type": "object",
          "additionalProperties": {}
        },
        "enabled": {
          "type": "boolean"
        },
        "reason": {
          "type": "string"
        },
        "usageStatsEnabled": {
          "type": "boolean"
        },
        "controlledBy": {
          "type": "string"
        },
        "message": {
          "type": "string"
        },
        "success": {
          "type": "boolean"
        }
      }
    }
  },
  {
    "id": "get-_api_v1_meta_openapi",
    "method": "get",
    "path": "/api/v1/meta/openapi",
    "displayName": "Get generated OpenAPI metadata",
    "summary": "Get generated OpenAPI metadata",
    "description": "Returns generated OpenAPI document JSON/YAML based on query format.",
    "tags": [
      "Meta & Utility v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "format",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "flags",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "period",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "language",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "package_name",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "version",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            },
            {
              "type": "string"
            },
            {
              "type": "number"
            },
            {
              "type": "boolean"
            },
            {
              "type": "null"
            }
          ]
        },
        "flags": {
          "type": "object",
          "additionalProperties": {}
        },
        "context": {
          "type": "object",
          "additionalProperties": {}
        },
        "enabled": {
          "type": "boolean"
        },
        "reason": {
          "type": "string"
        },
        "usageStatsEnabled": {
          "type": "boolean"
        },
        "controlledBy": {
          "type": "string"
        },
        "message": {
          "type": "string"
        },
        "success": {
          "type": "boolean"
        }
      }
    }
  },
  {
    "id": "get-_api_v1_meta_permissions",
    "method": "get",
    "path": "/api/v1/meta/permissions",
    "displayName": "List API permissions metadata",
    "summary": "List API permissions metadata",
    "description": "Returns permission metadata via ApiMetadataController.getPermissions().",
    "tags": [
      "Meta & Utility v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "format",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "flags",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "period",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "language",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "package_name",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "version",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            },
            {
              "type": "string"
            },
            {
              "type": "number"
            },
            {
              "type": "boolean"
            },
            {
              "type": "null"
            }
          ]
        },
        "flags": {
          "type": "object",
          "additionalProperties": {}
        },
        "context": {
          "type": "object",
          "additionalProperties": {}
        },
        "enabled": {
          "type": "boolean"
        },
        "reason": {
          "type": "string"
        },
        "usageStatsEnabled": {
          "type": "boolean"
        },
        "controlledBy": {
          "type": "string"
        },
        "message": {
          "type": "string"
        },
        "success": {
          "type": "boolean"
        }
      }
    }
  },
  {
    "id": "get-_api_v1_meta_schemas",
    "method": "get",
    "path": "/api/v1/meta/schemas",
    "displayName": "List API schemas metadata",
    "summary": "List API schemas metadata",
    "description": "Returns schema metadata via ApiMetadataController.getSchemas().",
    "tags": [
      "Meta & Utility v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "format",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "flags",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "period",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "language",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "package_name",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "version",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            },
            {
              "type": "string"
            },
            {
              "type": "number"
            },
            {
              "type": "boolean"
            },
            {
              "type": "null"
            }
          ]
        },
        "flags": {
          "type": "object",
          "additionalProperties": {}
        },
        "context": {
          "type": "object",
          "additionalProperties": {}
        },
        "enabled": {
          "type": "boolean"
        },
        "reason": {
          "type": "string"
        },
        "usageStatsEnabled": {
          "type": "boolean"
        },
        "controlledBy": {
          "type": "string"
        },
        "message": {
          "type": "string"
        },
        "success": {
          "type": "boolean"
        }
      }
    }
  },
  {
    "id": "get-_api_v1_meta_sdk",
    "method": "get",
    "path": "/api/v1/meta/sdk",
    "displayName": "Generate SDK metadata payload",
    "summary": "Generate SDK metadata payload",
    "description": "Generates SDK structure payload for selected language/format via generateSdk().",
    "tags": [
      "Meta & Utility v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "format",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "flags",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "period",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "language",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "package_name",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "version",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            },
            {
              "type": "string"
            },
            {
              "type": "number"
            },
            {
              "type": "boolean"
            },
            {
              "type": "null"
            }
          ]
        },
        "flags": {
          "type": "object",
          "additionalProperties": {}
        },
        "context": {
          "type": "object",
          "additionalProperties": {}
        },
        "enabled": {
          "type": "boolean"
        },
        "reason": {
          "type": "string"
        },
        "usageStatsEnabled": {
          "type": "boolean"
        },
        "controlledBy": {
          "type": "string"
        },
        "message": {
          "type": "string"
        },
        "success": {
          "type": "boolean"
        }
      }
    }
  },
  {
    "id": "get-_api_v1_meta_stats",
    "method": "get",
    "path": "/api/v1/meta/stats",
    "displayName": "Get API stats metadata",
    "summary": "Get API stats metadata",
    "description": "Returns API usage stats for requested period via getStats().",
    "tags": [
      "Meta & Utility v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "format",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "flags",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "period",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "language",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "package_name",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "version",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            },
            {
              "type": "string"
            },
            {
              "type": "number"
            },
            {
              "type": "boolean"
            },
            {
              "type": "null"
            }
          ]
        },
        "flags": {
          "type": "object",
          "additionalProperties": {}
        },
        "context": {
          "type": "object",
          "additionalProperties": {}
        },
        "enabled": {
          "type": "boolean"
        },
        "reason": {
          "type": "string"
        },
        "usageStatsEnabled": {
          "type": "boolean"
        },
        "controlledBy": {
          "type": "string"
        },
        "message": {
          "type": "string"
        },
        "success": {
          "type": "boolean"
        }
      }
    }
  },
  {
    "id": "get-_api_v1_testauth",
    "method": "get",
    "path": "/api/v1/test-auth",
    "displayName": "Test API key auth",
    "summary": "Test API key auth",
    "description": "Debug endpoint wrapping withApiKeyAuth middleware; returns only non-sensitive authenticated context identifiers.",
    "tags": [
      "Meta & Utility v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "format",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "flags",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "period",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "language",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "package_name",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "version",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            },
            {
              "type": "string"
            },
            {
              "type": "number"
            },
            {
              "type": "boolean"
            },
            {
              "type": "null"
            }
          ]
        },
        "flags": {
          "type": "object",
          "additionalProperties": {}
        },
        "context": {
          "type": "object",
          "additionalProperties": {}
        },
        "enabled": {
          "type": "boolean"
        },
        "reason": {
          "type": "string"
        },
        "usageStatsEnabled": {
          "type": "boolean"
        },
        "controlledBy": {
          "type": "string"
        },
        "message": {
          "type": "string"
        },
        "success": {
          "type": "boolean"
        }
      }
    }
  },
  {
    "id": "get-_api_v1_user_telemetrydecision",
    "method": "get",
    "path": "/api/v1/user/telemetry-decision",
    "displayName": "Get telemetry decision",
    "summary": "Get telemetry decision",
    "description": "Returns telemetry enabled/disabled decision from environment for current session user.",
    "tags": [
      "Meta & Utility v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "format",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "flags",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "period",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "language",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "package_name",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "version",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            },
            {
              "type": "string"
            },
            {
              "type": "number"
            },
            {
              "type": "boolean"
            },
            {
              "type": "null"
            }
          ]
        },
        "flags": {
          "type": "object",
          "additionalProperties": {}
        },
        "context": {
          "type": "object",
          "additionalProperties": {}
        },
        "enabled": {
          "type": "boolean"
        },
        "reason": {
          "type": "string"
        },
        "usageStatsEnabled": {
          "type": "boolean"
        },
        "controlledBy": {
          "type": "string"
        },
        "message": {
          "type": "string"
        },
        "success": {
          "type": "boolean"
        }
      }
    }
  },
  {
    "id": "get-_api_v1_user_telemetrypreferences",
    "method": "get",
    "path": "/api/v1/user/telemetry-preferences",
    "displayName": "Get telemetry preferences",
    "summary": "Get telemetry preferences",
    "description": "Read-only. Returns the usage-stats telemetry state, which is controlled by the ALGA_USAGE_STATS environment variable (not per-user); requires session user. There are no write verbs because the preference cannot be changed through the API.",
    "tags": [
      "Meta & Utility v1"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "format",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "flags",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "period",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "language",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "package_name",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "version",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "data": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {}
            },
            {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": {}
              }
            },
            {
              "type": "string"
            },
            {
              "type": "number"
            },
            {
              "type": "boolean"
            },
            {
              "type": "null"
            }
          ]
        },
        "flags": {
          "type": "object",
          "additionalProperties": {}
        },
        "context": {
          "type": "object",
          "additionalProperties": {}
        },
        "enabled": {
          "type": "boolean"
        },
        "reason": {
          "type": "string"
        },
        "usageStatsEnabled": {
          "type": "boolean"
        },
        "controlledBy": {
          "type": "string"
        },
        "message": {
          "type": "string"
        },
        "success": {
          "type": "boolean"
        }
      }
    }
  },
  {
    "id": "get-_api_extensions_softwareone_agreements",
    "method": "get",
    "path": "/api/extensions/softwareone/agreements",
    "displayName": "List SoftwareOne agreements",
    "summary": "List SoftwareOne agreements",
    "description": "Returns SoftwareOne agreement records available to the SoftwareOne extension. The current handler is an MVP placeholder backed by hardcoded dummy data; comments in the route indicate that a full implementation will validate permissions, derive tenant context, fetch from the SoftwareOne API, and apply filtering, sorting, and pagination. This route is not in the middleware API-key skip list, so callers must provide x-api-key at the API layer.",
    "tags": [
      "SoftwareOne Extensions"
    ],
    "approvalRequired": false,
    "parameters": [],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "success": {
          "type": "boolean",
          "enum": [
            true
          ],
          "description": "Request succeeded."
        },
        "data": {
          "type": "array",
          "items": {
            "$ref": "#/components/schemas/SoftwareOneAgreement"
          },
          "description": "SoftwareOne agreement records."
        },
        "meta": {
          "$ref": "#/components/schemas/SoftwareOnePaginationMeta"
        }
      },
      "required": [
        "success",
        "data",
        "meta"
      ]
    }
  },
  {
    "id": "post-_api_extensions_softwareone_agreements",
    "method": "post",
    "path": "/api/extensions/softwareone/agreements",
    "displayName": "Sync SoftwareOne agreements",
    "summary": "Sync SoftwareOne agreements",
    "description": "Triggers the SoftwareOne agreements sync placeholder. The current handler parses the JSON body but ignores all fields, then returns a dummy count. A full implementation is expected to validate permissions, derive tenant context, call the SoftwareOne API, persist agreements, and return actual sync counts. This route is not in the middleware API-key skip list, so callers must provide x-api-key at the API layer.",
    "tags": [
      "SoftwareOne Extensions"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "fullSync": {
          "type": "boolean",
          "description": "Optional future full-sync flag. Currently ignored by the MVP handlers."
        },
        "syncStatements": {
          "type": "boolean",
          "description": "Optional future statement sync flag. Currently ignored by the MVP handlers."
        },
        "syncAgreements": {
          "type": "boolean",
          "description": "Optional future agreement sync flag. Currently ignored by the MVP handlers."
        }
      },
      "description": "Sync options. The current SoftwareOne MVP handlers parse JSON but ignore all body fields."
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "success": {
          "type": "boolean",
          "enum": [
            true
          ],
          "description": "Sync request completed successfully."
        },
        "message": {
          "type": "string",
          "description": "Human-readable sync result message."
        },
        "count": {
          "type": "integer",
          "description": "Number of dummy records included in the sync result."
        }
      },
      "required": [
        "success",
        "message",
        "count"
      ]
    }
  },
  {
    "id": "get-_api_extensions_softwareone_agreements_id",
    "method": "get",
    "path": "/api/extensions/softwareone/agreements/{id}",
    "displayName": "Get SoftwareOne agreement",
    "summary": "Get SoftwareOne agreement",
    "description": "Returns one SoftwareOne agreement by external agreement ID, including additional detail fields such as dates, payment terms, contact, and license count. The current handler is an MVP placeholder backed by hardcoded dummy data. The id path parameter is a SoftwareOne-style string such as agr-001, not an Alga UUID.",
    "tags": [
      "SoftwareOne Extensions"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "SoftwareOne external identifier, such as agr-001 or stmt-001. This is not an Alga UUID.",
        "schema": {
          "type": "string",
          "description": "SoftwareOne external identifier, such as agr-001 or stmt-001. This is not an Alga UUID."
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "success": {
          "type": "boolean",
          "enum": [
            true
          ],
          "description": "Request succeeded."
        },
        "data": {
          "$ref": "#/components/schemas/SoftwareOneAgreementDetail"
        }
      },
      "required": [
        "success",
        "data"
      ]
    }
  },
  {
    "id": "get-_api_extensions_softwareone_statements",
    "method": "get",
    "path": "/api/extensions/softwareone/statements",
    "displayName": "List SoftwareOne statements",
    "summary": "List SoftwareOne statements",
    "description": "Returns SoftwareOne billing statement records available to the SoftwareOne extension. The current handler is an MVP placeholder backed by hardcoded dummy data; comments in the route indicate that a full implementation will validate permissions, derive tenant context, fetch from the SoftwareOne API, and apply filtering, sorting, and pagination. This route is not in the middleware API-key skip list, so callers must provide x-api-key at the API layer.",
    "tags": [
      "SoftwareOne Extensions"
    ],
    "approvalRequired": false,
    "parameters": [],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "success": {
          "type": "boolean",
          "enum": [
            true
          ],
          "description": "Request succeeded."
        },
        "data": {
          "type": "array",
          "items": {
            "$ref": "#/components/schemas/SoftwareOneStatement"
          },
          "description": "SoftwareOne statement records."
        },
        "meta": {
          "$ref": "#/components/schemas/SoftwareOnePaginationMeta"
        }
      },
      "required": [
        "success",
        "data",
        "meta"
      ]
    }
  },
  {
    "id": "post-_api_extensions_softwareone_statements",
    "method": "post",
    "path": "/api/extensions/softwareone/statements",
    "displayName": "Sync SoftwareOne statements",
    "summary": "Sync SoftwareOne statements",
    "description": "Triggers the SoftwareOne statements sync placeholder. The current handler parses the JSON body but ignores all fields, then returns a dummy count. A full implementation is expected to validate permissions, derive tenant context, call the SoftwareOne API, persist statements, and return actual sync counts. This route is not in the middleware API-key skip list, so callers must provide x-api-key at the API layer.",
    "tags": [
      "SoftwareOne Extensions"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "fullSync": {
          "type": "boolean",
          "description": "Optional future full-sync flag. Currently ignored by the MVP handlers."
        },
        "syncStatements": {
          "type": "boolean",
          "description": "Optional future statement sync flag. Currently ignored by the MVP handlers."
        },
        "syncAgreements": {
          "type": "boolean",
          "description": "Optional future agreement sync flag. Currently ignored by the MVP handlers."
        }
      },
      "description": "Sync options. The current SoftwareOne MVP handlers parse JSON but ignore all body fields."
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "success": {
          "type": "boolean",
          "enum": [
            true
          ],
          "description": "Sync request completed successfully."
        },
        "message": {
          "type": "string",
          "description": "Human-readable sync result message."
        },
        "count": {
          "type": "integer",
          "description": "Number of dummy records included in the sync result."
        }
      },
      "required": [
        "success",
        "message",
        "count"
      ]
    }
  },
  {
    "id": "get-_api_extensions_softwareone_statements_id",
    "method": "get",
    "path": "/api/extensions/softwareone/statements/{id}",
    "displayName": "Get SoftwareOne statement",
    "summary": "Get SoftwareOne statement",
    "description": "Returns one SoftwareOne billing statement by external statement ID, including additional detail fields such as subtotal, tax amount, description, and billing address. The current handler is an MVP placeholder backed by hardcoded dummy data. The id path parameter is a SoftwareOne-style string such as stmt-001, not an Alga UUID.",
    "tags": [
      "SoftwareOne Extensions"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "SoftwareOne external identifier, such as agr-001 or stmt-001. This is not an Alga UUID.",
        "schema": {
          "type": "string",
          "description": "SoftwareOne external identifier, such as agr-001 or stmt-001. This is not an Alga UUID."
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "success": {
          "type": "boolean",
          "enum": [
            true
          ],
          "description": "Request succeeded."
        },
        "data": {
          "$ref": "#/components/schemas/SoftwareOneStatement"
        }
      },
      "required": [
        "success",
        "data"
      ]
    }
  },
  {
    "id": "get-_api_extensions_softwareone_statements_id_charges",
    "method": "get",
    "path": "/api/extensions/softwareone/statements/{id}/charges",
    "displayName": "List SoftwareOne statement charges",
    "summary": "List SoftwareOne statement charges",
    "description": "Returns line-item charges for a SoftwareOne billing statement. The current handler is an MVP placeholder backed by hardcoded dummy data keyed by SoftwareOne statement IDs such as stmt-001. Unknown statement IDs return 200 with an empty data array rather than 404. The id path parameter is not an Alga UUID.",
    "tags": [
      "SoftwareOne Extensions"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "SoftwareOne external identifier, such as agr-001 or stmt-001. This is not an Alga UUID.",
        "schema": {
          "type": "string",
          "description": "SoftwareOne external identifier, such as agr-001 or stmt-001. This is not an Alga UUID."
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "success": {
          "type": "boolean",
          "enum": [
            true
          ],
          "description": "Request succeeded."
        },
        "data": {
          "type": "array",
          "items": {
            "$ref": "#/components/schemas/SoftwareOneCharge"
          },
          "description": "Charge line items for the requested statement. Unknown statement IDs return an empty array."
        },
        "meta": {
          "type": "object",
          "properties": {
            "total": {
              "type": "integer",
              "description": "Number of charge records returned."
            },
            "statementId": {
              "type": "string",
              "description": "Statement ID from the path parameter."
            }
          },
          "required": [
            "total",
            "statementId"
          ]
        }
      },
      "required": [
        "success",
        "data",
        "meta"
      ]
    }
  },
  {
    "id": "post-_api_extensions_softwareone_sync",
    "method": "post",
    "path": "/api/extensions/softwareone/sync",
    "displayName": "Sync SoftwareOne data",
    "summary": "Sync SoftwareOne data",
    "description": "Triggers the SoftwareOne aggregate sync placeholder. The current handler accepts optional syncAgreements and syncStatements booleans, waits briefly to simulate work, and returns dummy counts and a syncedAt timestamp. A full implementation will validate permissions, derive tenant context, connect to the SoftwareOne API, and persist agreement and statement data.",
    "tags": [
      "SoftwareOne Extensions"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "fullSync": {
          "type": "boolean",
          "description": "Optional future full-sync flag. Currently ignored by the MVP handlers."
        },
        "syncStatements": {
          "type": "boolean",
          "description": "Optional future statement sync flag. Currently ignored by the MVP handlers."
        },
        "syncAgreements": {
          "type": "boolean",
          "description": "Optional future agreement sync flag. Currently ignored by the MVP handlers."
        }
      },
      "description": "Sync options. The current SoftwareOne MVP handlers parse JSON but ignore all body fields."
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "success": {
          "type": "boolean",
          "enum": [
            true
          ],
          "description": "Sync request completed successfully."
        },
        "message": {
          "type": "string",
          "description": "Human-readable sync result message."
        },
        "data": {
          "type": "object",
          "properties": {
            "agreementsCount": {
              "type": "integer",
              "description": "Number of agreements synced. Zero when syncAgreements is false."
            },
            "statementsCount": {
              "type": "integer",
              "description": "Number of statements synced. Zero when syncStatements is false."
            },
            "syncedAt": {
              "type": "string",
              "format": "date-time",
              "description": "ISO timestamp when the dummy sync completed."
            }
          },
          "required": [
            "agreementsCount",
            "statementsCount",
            "syncedAt"
          ]
        }
      },
      "required": [
        "success",
        "message",
        "data"
      ]
    }
  },
  {
    "id": "get-_api_extensions_extensionid_agreements",
    "method": "get",
    "path": "/api/extensions/{extensionId}/agreements",
    "displayName": "List agreements for extension",
    "summary": "List agreements for extension",
    "description": "Generic extension agreements placeholder. The current handler accepts any extensionId, performs no handler-level extension validation, and returns hardcoded SoftwareOne-style agreement data with meta.extensionId echoed from the path. A full implementation will validate the extension ID, check permissions, derive tenant context, and fetch extension-specific data.",
    "tags": [
      "SoftwareOne Extensions"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "extensionId",
        "in": "path",
        "required": true,
        "description": "Extension identifier from the URL. The MVP generic routes accept any value and echo it in response metadata.",
        "schema": {
          "type": "string",
          "description": "Extension identifier from the URL. The MVP generic routes accept any value and echo it in response metadata."
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "success": {
          "type": "boolean",
          "enum": [
            true
          ],
          "description": "Request succeeded."
        },
        "data": {
          "type": "array",
          "items": {
            "$ref": "#/components/schemas/SoftwareOneAgreement"
          },
          "description": "Agreement records returned by the generic extension MVP handler."
        },
        "meta": {
          "type": "object",
          "properties": {
            "total": {
              "type": "integer",
              "description": "Number of agreements returned."
            },
            "extensionId": {
              "type": "string",
              "description": "Extension ID echoed from the path."
            }
          },
          "required": [
            "total",
            "extensionId"
          ]
        }
      },
      "required": [
        "success",
        "data",
        "meta"
      ]
    }
  },
  {
    "id": "get-_api_extensions_extensionid_agreements_id",
    "method": "get",
    "path": "/api/extensions/{extensionId}/agreements/{id}",
    "displayName": "Get agreement for extension",
    "summary": "Get agreement for extension",
    "description": "Generic extension agreement detail placeholder. The current handler accepts any extensionId, looks up an agreement by SoftwareOne-style external ID such as agr-001, and returns hardcoded detail data with meta.extensionId echoed from the path. The id path parameter is not an Alga UUID.",
    "tags": [
      "SoftwareOne Extensions"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "extensionId",
        "in": "path",
        "required": true,
        "description": "Extension identifier from the URL. The MVP generic routes accept any value and echo it in response metadata.",
        "schema": {
          "type": "string",
          "description": "Extension identifier from the URL. The MVP generic routes accept any value and echo it in response metadata."
        }
      },
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "SoftwareOne-style external record identifier, such as agr-001 or stmt-001. This is not an Alga UUID.",
        "schema": {
          "type": "string",
          "description": "SoftwareOne-style external record identifier, such as agr-001 or stmt-001. This is not an Alga UUID."
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "success": {
          "type": "boolean",
          "enum": [
            true
          ],
          "description": "Request succeeded."
        },
        "data": {
          "$ref": "#/components/schemas/SoftwareOneAgreementDetail"
        },
        "meta": {
          "type": "object",
          "properties": {
            "extensionId": {
              "type": "string",
              "description": "Extension ID echoed from the path."
            }
          },
          "required": [
            "extensionId"
          ]
        }
      },
      "required": [
        "success",
        "data",
        "meta"
      ]
    }
  },
  {
    "id": "get-_api_extensions_extensionid_statements",
    "method": "get",
    "path": "/api/extensions/{extensionId}/statements",
    "displayName": "List statements for extension",
    "summary": "List statements for extension",
    "description": "Generic extension statements placeholder. The current handler accepts any extensionId, performs no handler-level extension validation, and returns hardcoded SoftwareOne-style statement data with meta.extensionId echoed from the path. A full implementation will validate the extension ID, check permissions, derive tenant context, and fetch extension-specific data.",
    "tags": [
      "SoftwareOne Extensions"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "extensionId",
        "in": "path",
        "required": true,
        "description": "Extension identifier from the URL. The MVP generic routes accept any value and echo it in response metadata.",
        "schema": {
          "type": "string",
          "description": "Extension identifier from the URL. The MVP generic routes accept any value and echo it in response metadata."
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "success": {
          "type": "boolean",
          "enum": [
            true
          ],
          "description": "Request succeeded."
        },
        "data": {
          "type": "array",
          "items": {
            "$ref": "#/components/schemas/SoftwareOneStatement"
          },
          "description": "Statement records returned by the generic extension MVP handler."
        },
        "meta": {
          "type": "object",
          "properties": {
            "total": {
              "type": "integer",
              "description": "Number of statements returned."
            },
            "extensionId": {
              "type": "string",
              "description": "Extension ID echoed from the path."
            }
          },
          "required": [
            "total",
            "extensionId"
          ]
        }
      },
      "required": [
        "success",
        "data",
        "meta"
      ]
    }
  },
  {
    "id": "get-_api_extensions_extensionid_statements_id",
    "method": "get",
    "path": "/api/extensions/{extensionId}/statements/{id}",
    "displayName": "Get statement for extension",
    "summary": "Get statement for extension",
    "description": "Generic extension statement detail placeholder. The current handler accepts any extensionId, looks up a statement by SoftwareOne-style external ID such as stmt-001, and returns hardcoded detail data with meta.extensionId echoed from the path. The id path parameter is not an Alga UUID.",
    "tags": [
      "SoftwareOne Extensions"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "extensionId",
        "in": "path",
        "required": true,
        "description": "Extension identifier from the URL. The MVP generic routes accept any value and echo it in response metadata.",
        "schema": {
          "type": "string",
          "description": "Extension identifier from the URL. The MVP generic routes accept any value and echo it in response metadata."
        }
      },
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "SoftwareOne-style external record identifier, such as agr-001 or stmt-001. This is not an Alga UUID.",
        "schema": {
          "type": "string",
          "description": "SoftwareOne-style external record identifier, such as agr-001 or stmt-001. This is not an Alga UUID."
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "success": {
          "type": "boolean",
          "enum": [
            true
          ],
          "description": "Request succeeded."
        },
        "data": {
          "$ref": "#/components/schemas/SoftwareOneStatement"
        },
        "meta": {
          "type": "object",
          "properties": {
            "extensionId": {
              "type": "string",
              "description": "Extension ID echoed from the path."
            }
          },
          "required": [
            "extensionId"
          ]
        }
      },
      "required": [
        "success",
        "data",
        "meta"
      ]
    }
  },
  {
    "id": "get-_api_extensions_extensionid_statements_id_charges",
    "method": "get",
    "path": "/api/extensions/{extensionId}/statements/{id}/charges",
    "displayName": "List charges for extension statement",
    "summary": "List charges for extension statement",
    "description": "Generic extension statement charges placeholder. The current handler accepts any extensionId, returns hardcoded charge data keyed by SoftwareOne-style statement IDs such as stmt-001, and echoes extensionId in response metadata. Unknown statement IDs return 200 with an empty data array rather than 404.",
    "tags": [
      "SoftwareOne Extensions"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "extensionId",
        "in": "path",
        "required": true,
        "description": "Extension identifier from the URL. The MVP generic routes accept any value and echo it in response metadata.",
        "schema": {
          "type": "string",
          "description": "Extension identifier from the URL. The MVP generic routes accept any value and echo it in response metadata."
        }
      },
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "SoftwareOne-style external record identifier, such as agr-001 or stmt-001. This is not an Alga UUID.",
        "schema": {
          "type": "string",
          "description": "SoftwareOne-style external record identifier, such as agr-001 or stmt-001. This is not an Alga UUID."
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "success": {
          "type": "boolean",
          "enum": [
            true
          ],
          "description": "Request succeeded."
        },
        "data": {
          "type": "array",
          "items": {
            "$ref": "#/components/schemas/SoftwareOneCharge"
          },
          "description": "Charge line items. Unknown statement IDs return an empty array."
        },
        "meta": {
          "type": "object",
          "properties": {
            "total": {
              "type": "integer",
              "description": "Number of charge records returned."
            },
            "statementId": {
              "type": "string",
              "description": "Statement ID from the path parameter."
            },
            "extensionId": {
              "type": "string",
              "description": "Extension ID echoed from the path."
            }
          },
          "required": [
            "total",
            "statementId",
            "extensionId"
          ]
        }
      },
      "required": [
        "success",
        "data",
        "meta"
      ]
    }
  },
  {
    "id": "post-_api_extensions_extensionid_sync",
    "method": "post",
    "path": "/api/extensions/{extensionId}/sync",
    "displayName": "Sync extension data",
    "summary": "Sync extension data",
    "description": "Generic extension sync placeholder. The current handler accepts any extensionId and optional syncAgreements and syncStatements booleans, simulates work, and returns dummy agreement and statement counts with meta extensionId in the response data. A full implementation will validate extension identity, check permissions, derive tenant context, call the extension-specific backend, and persist data.",
    "tags": [
      "SoftwareOne Extensions"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "extensionId",
        "in": "path",
        "required": true,
        "description": "Extension identifier from the URL. The MVP generic routes accept any value and echo it in response metadata.",
        "schema": {
          "type": "string",
          "description": "Extension identifier from the URL. The MVP generic routes accept any value and echo it in response metadata."
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "fullSync": {
          "type": "boolean",
          "description": "Optional future full-sync flag. Currently ignored by the MVP handlers."
        },
        "syncStatements": {
          "type": "boolean",
          "description": "Optional future statement sync flag. Currently ignored by the MVP handlers."
        },
        "syncAgreements": {
          "type": "boolean",
          "description": "Optional future agreement sync flag. Currently ignored by the MVP handlers."
        }
      },
      "description": "Sync options. The current SoftwareOne MVP handlers parse JSON but ignore all body fields."
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "success": {
          "type": "boolean",
          "enum": [
            true
          ],
          "description": "Sync request completed successfully."
        },
        "message": {
          "type": "string",
          "description": "Human-readable sync result message."
        },
        "data": {
          "type": "object",
          "properties": {
            "agreementsCount": {
              "type": "integer",
              "description": "Number of agreements synced. Zero when syncAgreements is false."
            },
            "statementsCount": {
              "type": "integer",
              "description": "Number of statements synced. Zero when syncStatements is false."
            },
            "syncedAt": {
              "type": "string",
              "format": "date-time",
              "description": "ISO timestamp when the dummy sync completed."
            },
            "extensionId": {
              "type": "string",
              "description": "Extension ID echoed from the path."
            }
          },
          "required": [
            "agreementsCount",
            "statementsCount",
            "syncedAt",
            "extensionId"
          ]
        }
      },
      "required": [
        "success",
        "message",
        "data"
      ]
    }
  },
  {
    "id": "post-_api_accounting_csv_export",
    "method": "post",
    "path": "/api/accounting/csv/export",
    "displayName": "POST accounting",
    "summary": "POST accounting",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "accounting"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {}
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "post-_api_accounting_csv_import_tax",
    "method": "post",
    "path": "/api/accounting/csv/import/tax",
    "displayName": "POST accounting",
    "summary": "POST accounting",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "accounting"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {}
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "get-_api_accounting_csv_import_tax_history",
    "method": "get",
    "path": "/api/accounting/csv/import/tax/history",
    "displayName": "GET accounting",
    "summary": "GET accounting",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "accounting"
    ],
    "approvalRequired": false,
    "parameters": [],
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "post-_api_accounting_csv_import_tax_rollback_importid",
    "method": "post",
    "path": "/api/accounting/csv/import/tax/rollback/{importId}",
    "displayName": "POST accounting",
    "summary": "POST accounting",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "accounting"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "importId",
        "in": "path",
        "required": true,
        "description": "ImportId path parameter.",
        "schema": {
          "type": "string"
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "properties": {}
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "get-_api_accounting_csv_import_tax_template",
    "method": "get",
    "path": "/api/accounting/csv/import/tax/template",
    "displayName": "GET accounting",
    "summary": "GET accounting",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "accounting"
    ],
    "approvalRequired": false,
    "parameters": [],
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "get-_api_accounting_exports",
    "method": "get",
    "path": "/api/accounting/exports",
    "displayName": "GET accounting",
    "summary": "GET accounting",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "accounting"
    ],
    "approvalRequired": false,
    "parameters": [],
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "post-_api_accounting_exports",
    "method": "post",
    "path": "/api/accounting/exports",
    "displayName": "POST accounting",
    "summary": "POST accounting",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "accounting"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {}
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "post-_api_accounting_exports_locks_invoice_reset",
    "method": "post",
    "path": "/api/accounting/exports/locks/invoice/reset",
    "displayName": "POST accounting",
    "summary": "POST accounting",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "accounting"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {}
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "post-_api_accounting_exports_preview",
    "method": "post",
    "path": "/api/accounting/exports/preview",
    "displayName": "POST accounting",
    "summary": "POST accounting",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "accounting"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {}
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "get-_api_accounting_exports_batchid",
    "method": "get",
    "path": "/api/accounting/exports/{batchId}",
    "displayName": "GET accounting",
    "summary": "GET accounting",
    "tags": [
      "accounting"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "batchId",
        "in": "path",
        "required": true,
        "description": "BatchId path parameter.",
        "schema": {
          "type": "string"
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "patch-_api_accounting_exports_batchid",
    "method": "patch",
    "path": "/api/accounting/exports/{batchId}",
    "displayName": "PATCH accounting",
    "summary": "PATCH accounting",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "accounting"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "batchId",
        "in": "path",
        "required": true,
        "description": "BatchId path parameter.",
        "schema": {
          "type": "string"
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "properties": {}
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "post-_api_accounting_exports_batchid_download",
    "method": "post",
    "path": "/api/accounting/exports/{batchId}/download",
    "displayName": "POST accounting",
    "summary": "POST accounting",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "accounting"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "batchId",
        "in": "path",
        "required": true,
        "description": "BatchId path parameter.",
        "schema": {
          "type": "string"
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "properties": {}
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "post-_api_accounting_exports_batchid_errors",
    "method": "post",
    "path": "/api/accounting/exports/{batchId}/errors",
    "displayName": "POST accounting",
    "summary": "POST accounting",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "accounting"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "batchId",
        "in": "path",
        "required": true,
        "description": "BatchId path parameter.",
        "schema": {
          "type": "string"
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "properties": {}
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "post-_api_accounting_exports_batchid_execute",
    "method": "post",
    "path": "/api/accounting/exports/{batchId}/execute",
    "displayName": "POST accounting",
    "summary": "POST accounting",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "accounting"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "batchId",
        "in": "path",
        "required": true,
        "description": "BatchId path parameter.",
        "schema": {
          "type": "string"
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "properties": {}
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "post-_api_accounting_exports_batchid_lines",
    "method": "post",
    "path": "/api/accounting/exports/{batchId}/lines",
    "displayName": "POST accounting",
    "summary": "POST accounting",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "accounting"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "batchId",
        "in": "path",
        "required": true,
        "description": "BatchId path parameter.",
        "schema": {
          "type": "string"
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "properties": {}
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "get-_api_auth_e2e_google_authorize",
    "method": "get",
    "path": "/api/auth/e2e/google/authorize",
    "displayName": "GET auth",
    "summary": "GET auth",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "auth"
    ],
    "approvalRequired": false,
    "parameters": [],
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "get-_api_auth_e2e_google_complete",
    "method": "get",
    "path": "/api/auth/e2e/google/complete",
    "displayName": "GET auth",
    "summary": "GET auth",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "auth"
    ],
    "approvalRequired": false,
    "parameters": [],
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "post-_api_auth_e2e_google_token",
    "method": "post",
    "path": "/api/auth/e2e/google/token",
    "displayName": "POST auth",
    "summary": "POST auth",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "auth"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {}
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "get-_api_auth_e2e_google_userinfo",
    "method": "get",
    "path": "/api/auth/e2e/google/userinfo",
    "displayName": "GET auth",
    "summary": "GET auth",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "auth"
    ],
    "approvalRequired": false,
    "parameters": [],
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "get-_api_auth_google_calendar_callback",
    "method": "get",
    "path": "/api/auth/google/calendar/callback",
    "displayName": "GET auth",
    "summary": "GET auth",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "auth"
    ],
    "approvalRequired": false,
    "parameters": [],
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "get-_api_auth_microsoft_calendar_callback",
    "method": "get",
    "path": "/api/auth/microsoft/calendar/callback",
    "displayName": "GET auth",
    "summary": "GET auth",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "auth"
    ],
    "approvalRequired": false,
    "parameters": [],
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "get-_api_auth_microsoft_entra_callback",
    "method": "get",
    "path": "/api/auth/microsoft/entra/callback",
    "displayName": "GET auth",
    "summary": "GET auth",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "auth"
    ],
    "approvalRequired": false,
    "parameters": [],
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "post-_api_auth_msp_rememberemail",
    "method": "post",
    "path": "/api/auth/msp/remember-email",
    "displayName": "POST auth",
    "summary": "POST auth",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "auth"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {}
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "post-_api_auth_msp_sso_discover",
    "method": "post",
    "path": "/api/auth/msp/sso/discover",
    "displayName": "POST auth",
    "summary": "POST auth",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "auth"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {}
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "post-_api_auth_msp_sso_resolve",
    "method": "post",
    "path": "/api/auth/msp/sso/resolve",
    "displayName": "POST auth",
    "summary": "POST auth",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "auth"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {}
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "get-_api_auth_sessions",
    "method": "get",
    "path": "/api/auth/sessions",
    "displayName": "GET auth",
    "summary": "GET auth",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "auth"
    ],
    "approvalRequired": false,
    "parameters": [],
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "delete-_api_auth_sessions",
    "method": "delete",
    "path": "/api/auth/sessions",
    "displayName": "DELETE auth",
    "summary": "DELETE auth",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "auth"
    ],
    "approvalRequired": false,
    "parameters": [],
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "get-_api_auth_sessions_all",
    "method": "get",
    "path": "/api/auth/sessions/all",
    "displayName": "GET auth",
    "summary": "GET auth",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "auth"
    ],
    "approvalRequired": false,
    "parameters": [],
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "delete-_api_auth_sessions_sessionid",
    "method": "delete",
    "path": "/api/auth/sessions/{sessionId}",
    "displayName": "DELETE auth",
    "summary": "DELETE auth",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "auth"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "sessionId",
        "in": "path",
        "required": true,
        "description": "SessionId path parameter.",
        "schema": {
          "type": "string"
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "get-_api_billing_checktenant",
    "method": "get",
    "path": "/api/billing/check-tenant",
    "displayName": "GET billing",
    "summary": "GET billing",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "billing"
    ],
    "approvalRequired": false,
    "parameters": [],
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "get-_api_calendar_appointment_id",
    "method": "get",
    "path": "/api/calendar/appointment/{id}",
    "displayName": "GET calendar",
    "summary": "GET calendar",
    "tags": [
      "calendar"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Resource identifier.",
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "get-_api_calendar_webhooks_google",
    "method": "get",
    "path": "/api/calendar/webhooks/google",
    "displayName": "GET calendar",
    "summary": "GET calendar",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "calendar"
    ],
    "approvalRequired": false,
    "parameters": [],
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "post-_api_calendar_webhooks_google",
    "method": "post",
    "path": "/api/calendar/webhooks/google",
    "displayName": "POST calendar",
    "summary": "POST calendar",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "calendar"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {}
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "get-_api_calendar_webhooks_microsoft",
    "method": "get",
    "path": "/api/calendar/webhooks/microsoft",
    "displayName": "GET calendar",
    "summary": "GET calendar",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "calendar"
    ],
    "approvalRequired": false,
    "parameters": [],
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "post-_api_calendar_webhooks_microsoft",
    "method": "post",
    "path": "/api/calendar/webhooks/microsoft",
    "displayName": "POST calendar",
    "summary": "POST calendar",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "calendar"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {}
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "post-_api_chat_v1_completions",
    "method": "post",
    "path": "/api/chat/v1/completions",
    "displayName": "POST chat",
    "summary": "POST chat",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "chat"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {}
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "post-_api_chat_v1_completions_stream",
    "method": "post",
    "path": "/api/chat/v1/completions/stream",
    "displayName": "POST chat",
    "summary": "POST chat",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "chat"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {}
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "post-_api_chat_v1_execute",
    "method": "post",
    "path": "/api/chat/v1/execute",
    "displayName": "POST chat",
    "summary": "POST chat",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "chat"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {}
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "post-_api_clientportal_domainsession",
    "method": "post",
    "path": "/api/client-portal/domain-session",
    "displayName": "POST client-portal",
    "summary": "POST client-portal",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "client-portal"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {}
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "get-_api_clients",
    "method": "get",
    "path": "/api/clients",
    "displayName": "GET clients",
    "summary": "GET clients",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "clients"
    ],
    "approvalRequired": false,
    "parameters": [],
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "get-_api_documents_documentid_content",
    "method": "get",
    "path": "/api/documents/{documentId}/content",
    "displayName": "GET documents",
    "summary": "GET documents",
    "tags": [
      "documents"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "documentId",
        "in": "path",
        "required": true,
        "description": "DocumentId path parameter.",
        "schema": {
          "type": "string"
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "get-_api_documents_documentid_preview",
    "method": "get",
    "path": "/api/documents/{documentId}/preview",
    "displayName": "GET documents",
    "summary": "GET documents",
    "tags": [
      "documents"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "documentId",
        "in": "path",
        "required": true,
        "description": "DocumentId path parameter.",
        "schema": {
          "type": "string"
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "get-_api_documents_documentid_thumbnail",
    "method": "get",
    "path": "/api/documents/{documentId}/thumbnail",
    "displayName": "GET documents",
    "summary": "GET documents",
    "tags": [
      "documents"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "documentId",
        "in": "path",
        "required": true,
        "description": "DocumentId path parameter.",
        "schema": {
          "type": "string"
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "post-_api_email_imap_reconnect",
    "method": "post",
    "path": "/api/email/imap/reconnect",
    "displayName": "POST email",
    "summary": "POST email",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "email"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {}
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "post-_api_email_imap_resync",
    "method": "post",
    "path": "/api/email/imap/resync",
    "displayName": "POST email",
    "summary": "POST email",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "email"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {}
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "get-_api_email_oauth_imap_callback",
    "method": "get",
    "path": "/api/email/oauth/imap/callback",
    "displayName": "GET email",
    "summary": "GET email",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "email"
    ],
    "approvalRequired": false,
    "parameters": [],
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "post-_api_email_oauth_imap_initiate",
    "method": "post",
    "path": "/api/email/oauth/imap/initiate",
    "displayName": "POST email",
    "summary": "POST email",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "email"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {}
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "post-_api_email_webhooks_imap",
    "method": "post",
    "path": "/api/email/webhooks/imap",
    "displayName": "POST email",
    "summary": "POST email",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "email"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {}
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "post-_api_email_webhooks_resend",
    "method": "post",
    "path": "/api/email/webhooks/resend",
    "displayName": "POST email",
    "summary": "POST email",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "email"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {}
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "post-_api_extbundles_abort",
    "method": "post",
    "path": "/api/ext-bundles/abort",
    "displayName": "POST ext-bundles",
    "summary": "POST ext-bundles",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "ext-bundles"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {}
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "post-_api_extbundles_finalize",
    "method": "post",
    "path": "/api/ext-bundles/finalize",
    "displayName": "POST ext-bundles",
    "summary": "POST ext-bundles",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "ext-bundles"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {}
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "post-_api_extbundles_uploadproxy",
    "method": "post",
    "path": "/api/ext-bundles/upload-proxy",
    "displayName": "POST ext-bundles",
    "summary": "POST ext-bundles",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "ext-bundles"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {}
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "get-_api_extdebug_stream",
    "method": "get",
    "path": "/api/ext-debug/stream",
    "displayName": "GET ext-debug",
    "summary": "GET ext-debug",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "ext-debug"
    ],
    "approvalRequired": false,
    "parameters": [],
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "post-_api_extdebug_stream",
    "method": "post",
    "path": "/api/ext-debug/stream",
    "displayName": "POST ext-debug",
    "summary": "POST ext-debug",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "ext-debug"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {}
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "get-_api_extproxy_extensionid_path",
    "method": "get",
    "path": "/api/ext-proxy/{extensionId}/{path}",
    "displayName": "GET ext-proxy",
    "summary": "GET ext-proxy",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "ext-proxy"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "extensionId",
        "in": "path",
        "required": true,
        "description": "ExtensionId path parameter.",
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "path",
        "in": "path",
        "required": true,
        "description": "Path path parameter.",
        "schema": {
          "type": "string"
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "post-_api_extproxy_extensionid_path",
    "method": "post",
    "path": "/api/ext-proxy/{extensionId}/{path}",
    "displayName": "POST ext-proxy",
    "summary": "POST ext-proxy",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "ext-proxy"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "extensionId",
        "in": "path",
        "required": true,
        "description": "ExtensionId path parameter.",
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "path",
        "in": "path",
        "required": true,
        "description": "Path path parameter.",
        "schema": {
          "type": "string"
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "properties": {}
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "put-_api_extproxy_extensionid_path",
    "method": "put",
    "path": "/api/ext-proxy/{extensionId}/{path}",
    "displayName": "PUT ext-proxy",
    "summary": "PUT ext-proxy",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "ext-proxy"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "extensionId",
        "in": "path",
        "required": true,
        "description": "ExtensionId path parameter.",
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "path",
        "in": "path",
        "required": true,
        "description": "Path path parameter.",
        "schema": {
          "type": "string"
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "properties": {}
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "patch-_api_extproxy_extensionid_path",
    "method": "patch",
    "path": "/api/ext-proxy/{extensionId}/{path}",
    "displayName": "PATCH ext-proxy",
    "summary": "PATCH ext-proxy",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "ext-proxy"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "extensionId",
        "in": "path",
        "required": true,
        "description": "ExtensionId path parameter.",
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "path",
        "in": "path",
        "required": true,
        "description": "Path path parameter.",
        "schema": {
          "type": "string"
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "properties": {}
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "delete-_api_extproxy_extensionid_path",
    "method": "delete",
    "path": "/api/ext-proxy/{extensionId}/{path}",
    "displayName": "DELETE ext-proxy",
    "summary": "DELETE ext-proxy",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "ext-proxy"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "extensionId",
        "in": "path",
        "required": true,
        "description": "ExtensionId path parameter.",
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "path",
        "in": "path",
        "required": true,
        "description": "Path path parameter.",
        "schema": {
          "type": "string"
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "post-_api_import_approve",
    "method": "post",
    "path": "/api/import/approve",
    "displayName": "POST import",
    "summary": "POST import",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "import"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {}
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "get-_api_import_details",
    "method": "get",
    "path": "/api/import/details",
    "displayName": "GET import",
    "summary": "GET import",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "import"
    ],
    "approvalRequired": false,
    "parameters": [],
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "get-_api_import_history",
    "method": "get",
    "path": "/api/import/history",
    "displayName": "GET import",
    "summary": "GET import",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "import"
    ],
    "approvalRequired": false,
    "parameters": [],
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "get-_api_import_mapping",
    "method": "get",
    "path": "/api/import/mapping",
    "displayName": "GET import",
    "summary": "GET import",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "import"
    ],
    "approvalRequired": false,
    "parameters": [],
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "post-_api_import_preview",
    "method": "post",
    "path": "/api/import/preview",
    "displayName": "POST import",
    "summary": "POST import",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "import"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {}
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "get-_api_import_sources",
    "method": "get",
    "path": "/api/import/sources",
    "displayName": "GET import",
    "summary": "GET import",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "import"
    ],
    "approvalRequired": false,
    "parameters": [],
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "get-_api_integrations_entra",
    "method": "get",
    "path": "/api/integrations/entra",
    "displayName": "GET integrations",
    "summary": "GET integrations",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "integrations"
    ],
    "approvalRequired": false,
    "parameters": [],
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "post-_api_integrations_entra_connect",
    "method": "post",
    "path": "/api/integrations/entra/connect",
    "displayName": "POST integrations",
    "summary": "POST integrations",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "integrations"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {}
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "post-_api_integrations_entra_disconnect",
    "method": "post",
    "path": "/api/integrations/entra/disconnect",
    "displayName": "POST integrations",
    "summary": "POST integrations",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "integrations"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {}
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "post-_api_integrations_entra_discovery",
    "method": "post",
    "path": "/api/integrations/entra/discovery",
    "displayName": "POST integrations",
    "summary": "POST integrations",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "integrations"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {}
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "post-_api_integrations_entra_mappings_confirm",
    "method": "post",
    "path": "/api/integrations/entra/mappings/confirm",
    "displayName": "POST integrations",
    "summary": "POST integrations",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "integrations"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {}
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "get-_api_integrations_entra_mappings_preview",
    "method": "get",
    "path": "/api/integrations/entra/mappings/preview",
    "displayName": "GET integrations",
    "summary": "GET integrations",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "integrations"
    ],
    "approvalRequired": false,
    "parameters": [],
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "post-_api_integrations_entra_mappings_remap",
    "method": "post",
    "path": "/api/integrations/entra/mappings/remap",
    "displayName": "POST integrations",
    "summary": "POST integrations",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "integrations"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {}
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "post-_api_integrations_entra_mappings_unmap",
    "method": "post",
    "path": "/api/integrations/entra/mappings/unmap",
    "displayName": "POST integrations",
    "summary": "POST integrations",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "integrations"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {}
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "post-_api_integrations_entra_sync",
    "method": "post",
    "path": "/api/integrations/entra/sync",
    "displayName": "POST integrations",
    "summary": "POST integrations",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "integrations"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {}
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "get-_api_integrations_entra_sync_runs",
    "method": "get",
    "path": "/api/integrations/entra/sync/runs",
    "displayName": "GET integrations",
    "summary": "GET integrations",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "integrations"
    ],
    "approvalRequired": false,
    "parameters": [],
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "get-_api_integrations_entra_sync_runs_runid",
    "method": "get",
    "path": "/api/integrations/entra/sync/runs/{runId}",
    "displayName": "GET integrations",
    "summary": "GET integrations",
    "tags": [
      "integrations"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "runId",
        "in": "path",
        "required": true,
        "description": "RunId path parameter.",
        "schema": {
          "type": "string"
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "post-_api_integrations_entra_validatecipp",
    "method": "post",
    "path": "/api/integrations/entra/validate-cipp",
    "displayName": "POST integrations",
    "summary": "POST integrations",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "integrations"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {}
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "post-_api_integrations_entra_validatedirect",
    "method": "post",
    "path": "/api/integrations/entra/validate-direct",
    "displayName": "POST integrations",
    "summary": "POST integrations",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "integrations"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {}
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "get-_api_integrations_ninjaone_callback",
    "method": "get",
    "path": "/api/integrations/ninjaone/callback",
    "displayName": "GET integrations",
    "summary": "GET integrations",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "integrations"
    ],
    "approvalRequired": false,
    "parameters": [],
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "get-_api_integrations_xero_callback",
    "method": "get",
    "path": "/api/integrations/xero/callback",
    "displayName": "GET integrations",
    "summary": "GET integrations",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "integrations"
    ],
    "approvalRequired": false,
    "parameters": [],
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "get-_api_integrations_xero_connect",
    "method": "get",
    "path": "/api/integrations/xero/connect",
    "displayName": "GET integrations",
    "summary": "GET integrations",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "integrations"
    ],
    "approvalRequired": false,
    "parameters": [],
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "post-_api_internal_checktenantemail",
    "method": "post",
    "path": "/api/internal/check-tenant-email",
    "displayName": "POST internal",
    "summary": "POST internal",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "internal"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {}
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "post-_api_internal_collab_persist",
    "method": "post",
    "path": "/api/internal/collab/persist",
    "displayName": "POST internal",
    "summary": "POST internal",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "internal"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {}
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "post-_api_internal_extclients_install_installid",
    "method": "post",
    "path": "/api/internal/ext-clients/install/{installId}",
    "displayName": "POST internal",
    "summary": "POST internal",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "internal"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "installId",
        "in": "path",
        "required": true,
        "description": "InstallId path parameter.",
        "schema": {
          "type": "string"
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "properties": {}
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "post-_api_internal_extinvoicing_install_installid",
    "method": "post",
    "path": "/api/internal/ext-invoicing/install/{installId}",
    "displayName": "POST internal",
    "summary": "POST internal",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "internal"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "installId",
        "in": "path",
        "required": true,
        "description": "InstallId path parameter.",
        "schema": {
          "type": "string"
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "properties": {}
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "post-_api_internal_extrunner_installconfig",
    "method": "post",
    "path": "/api/internal/ext-runner/install-config",
    "displayName": "POST internal",
    "summary": "POST internal",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "internal"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {}
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "post-_api_internal_extscheduler_install_installid",
    "method": "post",
    "path": "/api/internal/ext-scheduler/install/{installId}",
    "displayName": "POST internal",
    "summary": "POST internal",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "internal"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "installId",
        "in": "path",
        "required": true,
        "description": "InstallId path parameter.",
        "schema": {
          "type": "string"
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "properties": {}
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "post-_api_internal_extservices_install_installid",
    "method": "post",
    "path": "/api/internal/ext-services/install/{installId}",
    "displayName": "POST internal",
    "summary": "POST internal",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "internal"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "installId",
        "in": "path",
        "required": true,
        "description": "InstallId path parameter.",
        "schema": {
          "type": "string"
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "properties": {}
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "post-_api_internal_extstorage_install_installid",
    "method": "post",
    "path": "/api/internal/ext-storage/install/{installId}",
    "displayName": "POST internal",
    "summary": "POST internal",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "internal"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "installId",
        "in": "path",
        "required": true,
        "description": "InstallId path parameter.",
        "schema": {
          "type": "string"
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "properties": {}
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "get-_api_onlinemeetings_recordings_artifactid",
    "method": "get",
    "path": "/api/online-meetings/recordings/{artifactId}",
    "displayName": "GET online-meetings",
    "summary": "GET online-meetings",
    "tags": [
      "online-meetings"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "artifactId",
        "in": "path",
        "required": true,
        "description": "ArtifactId path parameter.",
        "schema": {
          "type": "string"
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "post-_api_public_appointmentrequest",
    "method": "post",
    "path": "/api/public/appointment-request",
    "displayName": "POST public",
    "summary": "POST public",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "public"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {}
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "get-_api_public_appointmentrequest_availabledates",
    "method": "get",
    "path": "/api/public/appointment-request/available-dates",
    "displayName": "GET public",
    "summary": "GET public",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "public"
    ],
    "approvalRequired": false,
    "parameters": [],
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "get-_api_public_appointmentrequest_availableservices",
    "method": "get",
    "path": "/api/public/appointment-request/available-services",
    "displayName": "GET public",
    "summary": "GET public",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "public"
    ],
    "approvalRequired": false,
    "parameters": [],
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "get-_api_public_appointmentrequest_availableslots",
    "method": "get",
    "path": "/api/public/appointment-request/available-slots",
    "displayName": "GET public",
    "summary": "GET public",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "public"
    ],
    "approvalRequired": false,
    "parameters": [],
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "get-_api_secrets",
    "method": "get",
    "path": "/api/secrets",
    "displayName": "GET secrets",
    "summary": "GET secrets",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "secrets"
    ],
    "approvalRequired": false,
    "parameters": [],
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "post-_api_secrets",
    "method": "post",
    "path": "/api/secrets",
    "displayName": "POST secrets",
    "summary": "POST secrets",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "secrets"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {}
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "get-_api_secrets_name",
    "method": "get",
    "path": "/api/secrets/{name}",
    "displayName": "GET secrets",
    "summary": "GET secrets",
    "tags": [
      "secrets"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "name",
        "in": "path",
        "required": true,
        "description": "Name path parameter.",
        "schema": {
          "type": "string"
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "patch-_api_secrets_name",
    "method": "patch",
    "path": "/api/secrets/{name}",
    "displayName": "PATCH secrets",
    "summary": "PATCH secrets",
    "tags": [
      "secrets"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "name",
        "in": "path",
        "required": true,
        "description": "Name path parameter.",
        "schema": {
          "type": "string"
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "properties": {}
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "delete-_api_secrets_name",
    "method": "delete",
    "path": "/api/secrets/{name}",
    "displayName": "DELETE secrets",
    "summary": "DELETE secrets",
    "tags": [
      "secrets"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "name",
        "in": "path",
        "required": true,
        "description": "Name path parameter.",
        "schema": {
          "type": "string"
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "get-_api_share_token",
    "method": "get",
    "path": "/api/share/{token}",
    "displayName": "GET share",
    "summary": "GET share",
    "tags": [
      "share"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "token",
        "in": "path",
        "required": true,
        "description": "Token path parameter.",
        "schema": {
          "type": "string"
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "get-_api_share_token_info",
    "method": "get",
    "path": "/api/share/{token}/info",
    "displayName": "GET share",
    "summary": "GET share",
    "tags": [
      "share"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "token",
        "in": "path",
        "required": true,
        "description": "Token path parameter.",
        "schema": {
          "type": "string"
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "get-_api_teams_auth_callback_bot",
    "method": "get",
    "path": "/api/teams/auth/callback/bot",
    "displayName": "GET teams",
    "summary": "GET teams",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "teams"
    ],
    "approvalRequired": false,
    "parameters": [],
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "get-_api_teams_auth_callback_messageextension",
    "method": "get",
    "path": "/api/teams/auth/callback/message-extension",
    "displayName": "GET teams",
    "summary": "GET teams",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "teams"
    ],
    "approvalRequired": false,
    "parameters": [],
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "get-_api_teams_auth_callback_tab",
    "method": "get",
    "path": "/api/teams/auth/callback/tab",
    "displayName": "GET teams",
    "summary": "GET teams",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "teams"
    ],
    "approvalRequired": false,
    "parameters": [],
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "post-_api_teams_bot_messages",
    "method": "post",
    "path": "/api/teams/bot/messages",
    "displayName": "POST teams",
    "summary": "POST teams",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "teams"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {}
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "post-_api_teams_messageextension_query",
    "method": "post",
    "path": "/api/teams/message-extension/query",
    "displayName": "POST teams",
    "summary": "POST teams",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "teams"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {}
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "get-_api_teams_package",
    "method": "get",
    "path": "/api/teams/package",
    "displayName": "GET teams",
    "summary": "GET teams",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "teams"
    ],
    "approvalRequired": false,
    "parameters": [],
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "post-_api_teams_package",
    "method": "post",
    "path": "/api/teams/package",
    "displayName": "POST teams",
    "summary": "POST teams",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "teams"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {}
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "get-_api_teams_package_download",
    "method": "get",
    "path": "/api/teams/package/download",
    "displayName": "GET teams",
    "summary": "GET teams",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "teams"
    ],
    "approvalRequired": false,
    "parameters": [],
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "post-_api_teams_quickactions",
    "method": "post",
    "path": "/api/teams/quick-actions",
    "displayName": "POST teams",
    "summary": "POST teams",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "teams"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {}
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "get-_api_teams_webhooks_recordings",
    "method": "get",
    "path": "/api/teams/webhooks/recordings",
    "displayName": "GET teams",
    "summary": "GET teams",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "teams"
    ],
    "approvalRequired": false,
    "parameters": [],
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "post-_api_teams_webhooks_recordings",
    "method": "post",
    "path": "/api/teams/webhooks/recordings",
    "displayName": "POST teams",
    "summary": "POST teams",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "teams"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {}
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "get-_api_tickets_id_livetoken",
    "method": "get",
    "path": "/api/tickets/{id}/live-token",
    "displayName": "GET tickets",
    "summary": "GET tickets",
    "tags": [
      "tickets"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Resource identifier.",
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "post-_api_v1_mobile_account_delete",
    "method": "post",
    "path": "/api/v1/mobile/account/delete",
    "displayName": "POST v1",
    "summary": "POST v1",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "mobile"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {}
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "post-_api_v1_mobile_auth_apple",
    "method": "post",
    "path": "/api/v1/mobile/auth/apple",
    "displayName": "POST v1",
    "summary": "POST v1",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "mobile"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {}
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "get-_api_v1_mobile_auth_apple_link",
    "method": "get",
    "path": "/api/v1/mobile/auth/apple/link",
    "displayName": "GET v1",
    "summary": "GET v1",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "mobile"
    ],
    "approvalRequired": false,
    "parameters": [],
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "post-_api_v1_mobile_auth_apple_link",
    "method": "post",
    "path": "/api/v1/mobile/auth/apple/link",
    "displayName": "POST v1",
    "summary": "POST v1",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "mobile"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {}
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "delete-_api_v1_mobile_auth_apple_link",
    "method": "delete",
    "path": "/api/v1/mobile/auth/apple/link",
    "displayName": "DELETE v1",
    "summary": "DELETE v1",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "mobile"
    ],
    "approvalRequired": false,
    "parameters": [],
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "post-_api_v1_mobile_auth_apple_notifications",
    "method": "post",
    "path": "/api/v1/mobile/auth/apple/notifications",
    "displayName": "POST v1",
    "summary": "POST v1",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "mobile"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {}
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "get-_api_v1_mobile_auth_capabilities",
    "method": "get",
    "path": "/api/v1/mobile/auth/capabilities",
    "displayName": "GET v1",
    "summary": "GET v1",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "mobile"
    ],
    "approvalRequired": false,
    "parameters": [],
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "post-_api_v1_mobile_auth_exchange",
    "method": "post",
    "path": "/api/v1/mobile/auth/exchange",
    "displayName": "POST v1",
    "summary": "POST v1",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "mobile"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {}
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "post-_api_v1_mobile_auth_refresh",
    "method": "post",
    "path": "/api/v1/mobile/auth/refresh",
    "displayName": "POST v1",
    "summary": "POST v1",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "mobile"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {}
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "post-_api_v1_mobile_auth_revoke",
    "method": "post",
    "path": "/api/v1/mobile/auth/revoke",
    "displayName": "POST v1",
    "summary": "POST v1",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "mobile"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {}
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "post-_api_v1_mobile_iap_checkemail",
    "method": "post",
    "path": "/api/v1/mobile/iap/check-email",
    "displayName": "POST v1",
    "summary": "POST v1",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "mobile"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {}
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "post-_api_v1_mobile_iap_notifications",
    "method": "post",
    "path": "/api/v1/mobile/iap/notifications",
    "displayName": "POST v1",
    "summary": "POST v1",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "mobile"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {}
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "post-_api_v1_mobile_iap_provision",
    "method": "post",
    "path": "/api/v1/mobile/iap/provision",
    "displayName": "POST v1",
    "summary": "POST v1",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "mobile"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {}
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "post-_api_v1_mobile_iap_restore",
    "method": "post",
    "path": "/api/v1/mobile/iap/restore",
    "displayName": "POST v1",
    "summary": "POST v1",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "mobile"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {}
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "get-_api_v1_mobile_moderation_mutes",
    "method": "get",
    "path": "/api/v1/mobile/moderation/mutes",
    "displayName": "GET v1",
    "summary": "GET v1",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "mobile"
    ],
    "approvalRequired": false,
    "parameters": [],
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "post-_api_v1_mobile_moderation_mutes",
    "method": "post",
    "path": "/api/v1/mobile/moderation/mutes",
    "displayName": "POST v1",
    "summary": "POST v1",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "mobile"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {}
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "delete-_api_v1_mobile_moderation_mutes_userid",
    "method": "delete",
    "path": "/api/v1/mobile/moderation/mutes/{userId}",
    "displayName": "DELETE v1",
    "summary": "DELETE v1",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "mobile"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "userId",
        "in": "path",
        "required": true,
        "description": "UserId path parameter.",
        "schema": {
          "type": "string"
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "post-_api_v1_mobile_moderation_report",
    "method": "post",
    "path": "/api/v1/mobile/moderation/report",
    "displayName": "POST v1",
    "summary": "POST v1",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "mobile"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {}
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "put-_api_v1_mobile_pushtoken",
    "method": "put",
    "path": "/api/v1/mobile/push-token",
    "displayName": "PUT v1",
    "summary": "PUT v1",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "mobile"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {}
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "delete-_api_v1_mobile_pushtoken",
    "method": "delete",
    "path": "/api/v1/mobile/push-token",
    "displayName": "DELETE v1",
    "summary": "DELETE v1",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "mobile"
    ],
    "approvalRequired": false,
    "parameters": [],
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "get-_api_v1_platformfeatureflags",
    "method": "get",
    "path": "/api/v1/platform-feature-flags",
    "displayName": "GET v1",
    "summary": "GET v1",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "platform-feature-flags"
    ],
    "approvalRequired": false,
    "parameters": [],
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "post-_api_v1_platformfeatureflags",
    "method": "post",
    "path": "/api/v1/platform-feature-flags",
    "displayName": "POST v1",
    "summary": "POST v1",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "platform-feature-flags"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {}
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "get-_api_v1_platformfeatureflags_flagid",
    "method": "get",
    "path": "/api/v1/platform-feature-flags/{flagId}",
    "displayName": "GET v1",
    "summary": "GET v1",
    "tags": [
      "platform-feature-flags"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "flagId",
        "in": "path",
        "required": true,
        "description": "FlagId path parameter.",
        "schema": {
          "type": "string"
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "post-_api_v1_platformfeatureflags_flagid",
    "method": "post",
    "path": "/api/v1/platform-feature-flags/{flagId}",
    "displayName": "POST v1",
    "summary": "POST v1",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "platform-feature-flags"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "flagId",
        "in": "path",
        "required": true,
        "description": "FlagId path parameter.",
        "schema": {
          "type": "string"
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "properties": {}
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "patch-_api_v1_platformfeatureflags_flagid",
    "method": "patch",
    "path": "/api/v1/platform-feature-flags/{flagId}",
    "displayName": "PATCH v1",
    "summary": "PATCH v1",
    "tags": [
      "platform-feature-flags"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "flagId",
        "in": "path",
        "required": true,
        "description": "FlagId path parameter.",
        "schema": {
          "type": "string"
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "properties": {}
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "delete-_api_v1_platformfeatureflags_flagid",
    "method": "delete",
    "path": "/api/v1/platform-feature-flags/{flagId}",
    "displayName": "DELETE v1",
    "summary": "DELETE v1",
    "tags": [
      "platform-feature-flags"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "flagId",
        "in": "path",
        "required": true,
        "description": "FlagId path parameter.",
        "schema": {
          "type": "string"
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "post-_api_v1_platformfeatureflags_flagid_tenants",
    "method": "post",
    "path": "/api/v1/platform-feature-flags/{flagId}/tenants",
    "displayName": "POST v1",
    "summary": "POST v1",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "platform-feature-flags"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "flagId",
        "in": "path",
        "required": true,
        "description": "FlagId path parameter.",
        "schema": {
          "type": "string"
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "properties": {}
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "get-_api_v1_platformnotifications",
    "method": "get",
    "path": "/api/v1/platform-notifications",
    "displayName": "GET v1",
    "summary": "GET v1",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "platform-notifications"
    ],
    "approvalRequired": false,
    "parameters": [],
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "post-_api_v1_platformnotifications",
    "method": "post",
    "path": "/api/v1/platform-notifications",
    "displayName": "POST v1",
    "summary": "POST v1",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "platform-notifications"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {}
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "post-_api_v1_platformnotifications_resolverecipients",
    "method": "post",
    "path": "/api/v1/platform-notifications/resolve-recipients",
    "displayName": "POST v1",
    "summary": "POST v1",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "platform-notifications"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {}
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "get-_api_v1_platformnotifications_notificationid",
    "method": "get",
    "path": "/api/v1/platform-notifications/{notificationId}",
    "displayName": "GET v1",
    "summary": "GET v1",
    "tags": [
      "platform-notifications"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "notificationId",
        "in": "path",
        "required": true,
        "description": "NotificationId path parameter.",
        "schema": {
          "type": "string"
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "post-_api_v1_platformnotifications_notificationid",
    "method": "post",
    "path": "/api/v1/platform-notifications/{notificationId}",
    "displayName": "POST v1",
    "summary": "POST v1",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "platform-notifications"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "notificationId",
        "in": "path",
        "required": true,
        "description": "NotificationId path parameter.",
        "schema": {
          "type": "string"
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "properties": {}
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "put-_api_v1_platformnotifications_notificationid",
    "method": "put",
    "path": "/api/v1/platform-notifications/{notificationId}",
    "displayName": "PUT v1",
    "summary": "PUT v1",
    "tags": [
      "platform-notifications"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "notificationId",
        "in": "path",
        "required": true,
        "description": "NotificationId path parameter.",
        "schema": {
          "type": "string"
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "properties": {}
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "delete-_api_v1_platformnotifications_notificationid",
    "method": "delete",
    "path": "/api/v1/platform-notifications/{notificationId}",
    "displayName": "DELETE v1",
    "summary": "DELETE v1",
    "tags": [
      "platform-notifications"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "notificationId",
        "in": "path",
        "required": true,
        "description": "NotificationId path parameter.",
        "schema": {
          "type": "string"
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "get-_api_v1_platformnotifications_notificationid_reads",
    "method": "get",
    "path": "/api/v1/platform-notifications/{notificationId}/reads",
    "displayName": "GET v1",
    "summary": "GET v1",
    "tags": [
      "platform-notifications"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "notificationId",
        "in": "path",
        "required": true,
        "description": "NotificationId path parameter.",
        "schema": {
          "type": "string"
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "get-_api_v1_platformnotifications_notificationid_stats",
    "method": "get",
    "path": "/api/v1/platform-notifications/{notificationId}/stats",
    "displayName": "GET v1",
    "summary": "GET v1",
    "tags": [
      "platform-notifications"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "notificationId",
        "in": "path",
        "required": true,
        "description": "NotificationId path parameter.",
        "schema": {
          "type": "string"
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "get-_api_v1_platformreports",
    "method": "get",
    "path": "/api/v1/platform-reports",
    "displayName": "GET v1",
    "summary": "GET v1",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "platform-reports"
    ],
    "approvalRequired": false,
    "parameters": [],
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "post-_api_v1_platformreports",
    "method": "post",
    "path": "/api/v1/platform-reports",
    "displayName": "POST v1",
    "summary": "POST v1",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "platform-reports"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {}
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "post-_api_v1_platformreports_access",
    "method": "post",
    "path": "/api/v1/platform-reports/access",
    "displayName": "POST v1",
    "summary": "POST v1",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "platform-reports"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {}
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "get-_api_v1_platformreports_audit",
    "method": "get",
    "path": "/api/v1/platform-reports/audit",
    "displayName": "GET v1",
    "summary": "GET v1",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "platform-reports"
    ],
    "approvalRequired": false,
    "parameters": [],
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "get-_api_v1_platformreports_schema",
    "method": "get",
    "path": "/api/v1/platform-reports/schema",
    "displayName": "GET v1",
    "summary": "GET v1",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "platform-reports"
    ],
    "approvalRequired": false,
    "parameters": [],
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "get-_api_v1_platformreports_reportid",
    "method": "get",
    "path": "/api/v1/platform-reports/{reportId}",
    "displayName": "GET v1",
    "summary": "GET v1",
    "tags": [
      "platform-reports"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "reportId",
        "in": "path",
        "required": true,
        "description": "ReportId path parameter.",
        "schema": {
          "type": "string"
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "post-_api_v1_platformreports_reportid",
    "method": "post",
    "path": "/api/v1/platform-reports/{reportId}",
    "displayName": "POST v1",
    "summary": "POST v1",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "platform-reports"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "reportId",
        "in": "path",
        "required": true,
        "description": "ReportId path parameter.",
        "schema": {
          "type": "string"
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "properties": {}
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "put-_api_v1_platformreports_reportid",
    "method": "put",
    "path": "/api/v1/platform-reports/{reportId}",
    "displayName": "PUT v1",
    "summary": "PUT v1",
    "tags": [
      "platform-reports"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "reportId",
        "in": "path",
        "required": true,
        "description": "ReportId path parameter.",
        "schema": {
          "type": "string"
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "properties": {}
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "delete-_api_v1_platformreports_reportid",
    "method": "delete",
    "path": "/api/v1/platform-reports/{reportId}",
    "displayName": "DELETE v1",
    "summary": "DELETE v1",
    "tags": [
      "platform-reports"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "reportId",
        "in": "path",
        "required": true,
        "description": "ReportId path parameter.",
        "schema": {
          "type": "string"
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "post-_api_v1_platformreports_reportid_execute",
    "method": "post",
    "path": "/api/v1/platform-reports/{reportId}/execute",
    "displayName": "POST v1",
    "summary": "POST v1",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "platform-reports"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "reportId",
        "in": "path",
        "required": true,
        "description": "ReportId path parameter.",
        "schema": {
          "type": "string"
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "properties": {}
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "get-_api_v1_storage_namespaces_namespace_records",
    "method": "get",
    "path": "/api/v1/storage/namespaces/{namespace}/records",
    "displayName": "List records in a namespace",
    "summary": "List records in a namespace",
    "tags": [
      "Storage"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "namespace",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string",
          "minLength": 1,
          "maxLength": 128
        }
      },
      {
        "name": "limit",
        "in": "query",
        "required": false,
        "schema": {
          "type": "integer",
          "minimum": 1,
          "maximum": 100
        }
      },
      {
        "name": "cursor",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "keyPrefix",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "maxLength": 256
        }
      },
      {
        "name": "includeValues",
        "in": "query",
        "required": false,
        "schema": {
          "type": "boolean"
        }
      },
      {
        "name": "includeMetadata",
        "in": "query",
        "required": false,
        "schema": {
          "type": "boolean"
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "items": {
          "type": "array",
          "items": {
            "$ref": "#/components/schemas/StorageListItem"
          }
        },
        "nextCursor": {
          "type": [
            "string",
            "null"
          ]
        }
      },
      "required": [
        "items",
        "nextCursor"
      ]
    },
    "playbooks": [
      "storage/list-namespace"
    ],
    "examples": [
      {
        "name": "List records with prefix filter",
        "request": {
          "params": {
            "namespace": "integrations:zendesk"
          },
          "query": {
            "prefix": "tickets/"
          }
        }
      }
    ]
  },
  {
    "id": "post-_api_v1_storage_namespaces_namespace_records",
    "method": "post",
    "path": "/api/v1/storage/namespaces/{namespace}/records",
    "displayName": "Bulk insert or update records",
    "summary": "Bulk insert or update records",
    "tags": [
      "Storage"
    ],
    "approvalRequired": true,
    "parameters": [
      {
        "name": "namespace",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string",
          "minLength": 1,
          "maxLength": 128
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "items": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "key": {
                "type": "string",
                "minLength": 1,
                "maxLength": 256
              },
              "value": {},
              "metadata": {
                "type": "object",
                "additionalProperties": {}
              },
              "ttlSeconds": {
                "type": "integer",
                "exclusiveMinimum": 0
              },
              "ifRevision": {
                "type": "integer",
                "minimum": 0
              },
              "schemaVersion": {
                "type": "integer",
                "exclusiveMinimum": 0
              }
            },
            "required": [
              "key"
            ]
          },
          "minItems": 1
        }
      },
      "required": [
        "items"
      ]
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "namespace": {
          "type": "string"
        },
        "items": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "key": {
                "type": "string"
              },
              "revision": {
                "type": "integer",
                "exclusiveMinimum": 0
              },
              "ttlExpiresAt": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date-time"
              }
            },
            "required": [
              "key",
              "revision",
              "ttlExpiresAt"
            ]
          }
        }
      },
      "required": [
        "namespace",
        "items"
      ]
    },
    "playbooks": [
      "storage/bulk-upsert-records"
    ],
    "examples": [
      {
        "name": "Bulk upsert configuration values",
        "request": {
          "params": {
            "namespace": "automation:workflow"
          },
          "body": {
            "records": [
              {
                "key": "webhook/url",
                "value": "https://hooks.example.com/inbound",
                "contentType": "text/plain"
              }
            ]
          }
        }
      }
    ]
  },
  {
    "id": "get-_api_v1_storage_namespaces_namespace_records_key",
    "method": "get",
    "path": "/api/v1/storage/namespaces/{namespace}/records/{key}",
    "displayName": "Get a record by key",
    "summary": "Get a record by key",
    "tags": [
      "Storage"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "namespace",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string",
          "minLength": 1,
          "maxLength": 128
        }
      },
      {
        "name": "key",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string",
          "minLength": 1,
          "maxLength": 256
        }
      },
      {
        "name": "if-revision-match",
        "in": "header",
        "required": false,
        "schema": {
          "type": "string"
        }
      }
    ],
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "namespace": {
          "type": "string"
        },
        "key": {
          "type": "string"
        },
        "revision": {
          "type": "integer",
          "exclusiveMinimum": 0
        },
        "value": {},
        "metadata": {
          "type": "object",
          "additionalProperties": {}
        },
        "ttlExpiresAt": {
          "type": [
            "string",
            "null"
          ],
          "format": "date-time"
        },
        "createdAt": {
          "type": "string",
          "format": "date-time"
        },
        "updatedAt": {
          "type": "string",
          "format": "date-time"
        }
      },
      "required": [
        "namespace",
        "key",
        "revision",
        "metadata",
        "ttlExpiresAt",
        "createdAt",
        "updatedAt"
      ]
    },
    "playbooks": [
      "storage/get-record"
    ],
    "examples": [
      {
        "name": "Retrieve a workflow record",
        "request": {
          "params": {
            "namespace": "automation:workflow",
            "key": "webhook/url"
          }
        }
      }
    ]
  },
  {
    "id": "put-_api_v1_storage_namespaces_namespace_records_key",
    "method": "put",
    "path": "/api/v1/storage/namespaces/{namespace}/records/{key}",
    "displayName": "Create or update a record by key",
    "summary": "Create or update a record by key",
    "tags": [
      "Storage"
    ],
    "approvalRequired": true,
    "parameters": [
      {
        "name": "namespace",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string",
          "minLength": 1,
          "maxLength": 128
        }
      },
      {
        "name": "key",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string",
          "minLength": 1,
          "maxLength": 256
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "properties": {
        "value": {},
        "metadata": {
          "type": "object",
          "additionalProperties": {}
        },
        "ttlSeconds": {
          "type": "integer",
          "exclusiveMinimum": 0
        },
        "ifRevision": {
          "type": "integer",
          "minimum": 0
        },
        "schemaVersion": {
          "type": "integer",
          "exclusiveMinimum": 0
        }
      }
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {
        "namespace": {
          "type": "string"
        },
        "key": {
          "type": "string"
        },
        "revision": {
          "type": "integer",
          "exclusiveMinimum": 0
        },
        "ttlExpiresAt": {
          "type": [
            "string",
            "null"
          ],
          "format": "date-time"
        },
        "createdAt": {
          "type": "string",
          "format": "date-time"
        },
        "updatedAt": {
          "type": "string",
          "format": "date-time"
        }
      },
      "required": [
        "namespace",
        "key",
        "revision",
        "ttlExpiresAt",
        "createdAt",
        "updatedAt"
      ]
    },
    "playbooks": [
      "storage/put-record"
    ],
    "examples": [
      {
        "name": "Set workflow webhook URL",
        "request": {
          "params": {
            "namespace": "automation:workflow",
            "key": "webhook/url"
          },
          "body": {
            "value": "https://hooks.example.com/inbound",
            "contentType": "text/plain"
          }
        }
      }
    ]
  },
  {
    "id": "delete-_api_v1_storage_namespaces_namespace_records_key",
    "method": "delete",
    "path": "/api/v1/storage/namespaces/{namespace}/records/{key}",
    "displayName": "Delete a record by key",
    "summary": "Delete a record by key",
    "tags": [
      "Storage"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "namespace",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string",
          "minLength": 1,
          "maxLength": 128
        }
      },
      {
        "name": "key",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string",
          "minLength": 1,
          "maxLength": 256
        }
      },
      {
        "name": "ifRevision",
        "in": "query",
        "required": false,
        "schema": {
          "type": [
            "integer",
            "null"
          ],
          "minimum": 0
        }
      }
    ]
  },
  {
    "id": "get-_api_v1_tenantmanagement_addons",
    "method": "get",
    "path": "/api/v1/tenant-management/addons",
    "displayName": "GET v1",
    "summary": "GET v1",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "tenant-management"
    ],
    "approvalRequired": false,
    "parameters": [],
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "get-_api_v1_tenantmanagement_audit",
    "method": "get",
    "path": "/api/v1/tenant-management/audit",
    "displayName": "GET v1",
    "summary": "GET v1",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "tenant-management"
    ],
    "approvalRequired": false,
    "parameters": [],
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "post-_api_v1_tenantmanagement_confirmdeletion",
    "method": "post",
    "path": "/api/v1/tenant-management/confirm-deletion",
    "displayName": "POST v1",
    "summary": "POST v1",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "tenant-management"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {}
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "post-_api_v1_tenantmanagement_createtenant",
    "method": "post",
    "path": "/api/v1/tenant-management/create-tenant",
    "displayName": "POST v1",
    "summary": "POST v1",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "tenant-management"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {}
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "post-_api_v1_tenantmanagement_exporttenant",
    "method": "post",
    "path": "/api/v1/tenant-management/export-tenant",
    "displayName": "POST v1",
    "summary": "POST v1",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "tenant-management"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {}
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "get-_api_v1_tenantmanagement_exports",
    "method": "get",
    "path": "/api/v1/tenant-management/exports",
    "displayName": "GET v1",
    "summary": "GET v1",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "tenant-management"
    ],
    "approvalRequired": false,
    "parameters": [],
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "post-_api_v1_tenantmanagement_exports_exportid_downloadurl",
    "method": "post",
    "path": "/api/v1/tenant-management/exports/{exportId}/download-url",
    "displayName": "POST v1",
    "summary": "POST v1",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "tenant-management"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "exportId",
        "in": "path",
        "required": true,
        "description": "ExportId path parameter.",
        "schema": {
          "type": "string"
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "properties": {}
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "get-_api_v1_tenantmanagement_pendingdeletions",
    "method": "get",
    "path": "/api/v1/tenant-management/pending-deletions",
    "displayName": "GET v1",
    "summary": "GET v1",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "tenant-management"
    ],
    "approvalRequired": false,
    "parameters": [],
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "post-_api_v1_tenantmanagement_resendwelcomeemail",
    "method": "post",
    "path": "/api/v1/tenant-management/resend-welcome-email",
    "displayName": "POST v1",
    "summary": "POST v1",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "tenant-management"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {}
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "post-_api_v1_tenantmanagement_rollbackdeletion",
    "method": "post",
    "path": "/api/v1/tenant-management/rollback-deletion",
    "displayName": "POST v1",
    "summary": "POST v1",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "tenant-management"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {}
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "post-_api_v1_tenantmanagement_startdeletion",
    "method": "post",
    "path": "/api/v1/tenant-management/start-deletion",
    "displayName": "POST v1",
    "summary": "POST v1",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "tenant-management"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {}
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "post-_api_v1_tenantmanagement_startpremiumtrial",
    "method": "post",
    "path": "/api/v1/tenant-management/start-premium-trial",
    "displayName": "POST v1",
    "summary": "POST v1",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "tenant-management"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {}
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "get-_api_v1_tenantmanagement_tenants",
    "method": "get",
    "path": "/api/v1/tenant-management/tenants",
    "displayName": "GET v1",
    "summary": "GET v1",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "tenant-management"
    ],
    "approvalRequired": false,
    "parameters": [],
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "post-_api_v1_tenantmanagement_tenants_tenantid_addons",
    "method": "post",
    "path": "/api/v1/tenant-management/tenants/{tenantId}/addons",
    "displayName": "POST v1",
    "summary": "POST v1",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "tenant-management"
    ],
    "approvalRequired": false,
    "parameters": [
      {
        "name": "tenantId",
        "in": "path",
        "required": true,
        "description": "TenantId path parameter.",
        "schema": {
          "type": "string"
        }
      }
    ],
    "requestBodySchema": {
      "type": "object",
      "properties": {}
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "get-_api_webhooks_ninjaone",
    "method": "get",
    "path": "/api/webhooks/ninjaone",
    "displayName": "GET webhooks",
    "summary": "GET webhooks",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "webhooks"
    ],
    "approvalRequired": false,
    "parameters": [],
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "post-_api_webhooks_ninjaone",
    "method": "post",
    "path": "/api/webhooks/ninjaone",
    "displayName": "POST webhooks",
    "summary": "POST webhooks",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "webhooks"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {}
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "post-_api_webhooks_stripe",
    "method": "post",
    "path": "/api/webhooks/stripe",
    "displayName": "POST webhooks",
    "summary": "POST webhooks",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "webhooks"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {}
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "post-_api_webhooks_stripe_payments",
    "method": "post",
    "path": "/api/webhooks/stripe/payments",
    "displayName": "POST webhooks",
    "summary": "POST webhooks",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "webhooks"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {}
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  },
  {
    "id": "post-_api_webhooks_tacticalrmm",
    "method": "post",
    "path": "/api/webhooks/tacticalrmm",
    "displayName": "POST webhooks",
    "summary": "POST webhooks",
    "description": "This operation was generated automatically from the route inventory. Replace with canonical OpenAPI metadata.",
    "tags": [
      "webhooks"
    ],
    "approvalRequired": false,
    "parameters": [],
    "requestBodySchema": {
      "type": "object",
      "properties": {}
    },
    "responseBodySchema": {
      "type": "object",
      "properties": {}
    }
  }
];

export default chatApiRegistry;
