{
    "openapi": "3.1.0",
    "info": {
        "title": "Fieldmotion CRM PHP API",
        "version": "1.0.0",
        "description": "Generated from inline `@fm-doc` blocks in `crm/www/php`.\n\nRoutes follow the dispatcher convention `/a/Object_action` -> `php/Object/action.php` -> `Object_action()`.\n\nEndpoints are documented as `POST` operations with `application/x-www-form-urlencoded` bodies because the dispatcher reads from `$_REQUEST`. Existing callers may still use GET where the endpoint allows it."
    },
    "servers": [
        {
            "url": "/"
        }
    ],
    "tags": [
        {
            "name": "Accounting"
        },
        {
            "name": "Assets"
        },
        {
            "name": "ContractProgrammeImport"
        },
        {
            "name": "ContractProgramme"
        },
        {
            "name": "Customer"
        },
        {
            "name": "Customers"
        },
        {
            "name": "Departments"
        },
        {
            "name": "DigitalWasteTracking"
        },
        {
            "name": "Form"
        },
        {
            "name": "GoodReturned"
        },
        {
            "name": "GoodsReturnedEntry"
        },
        {
            "name": "GoodsReturnedNote"
        },
        {
            "name": "GoodsReturned"
        },
        {
            "name": "InvoiceRow"
        },
        {
            "name": "Invoice"
        },
        {
            "name": "Jobs"
        },
        {
            "name": "QuoteRecurring"
        },
        {
            "name": "QuotesRecurring"
        },
        {
            "name": "Reports"
        },
        {
            "name": "Stock"
        },
        {
            "name": "TeamAccess"
        },
        {
            "name": "Timesheet"
        },
        {
            "name": "Training"
        },
        {
            "name": "UserClockin"
        },
        {
            "name": "UserClockins"
        },
        {
            "name": "Util"
        }
    ],
    "paths": {
        "/a/Accounting_authorisation": {
            "post": {
                "operationId": "Accounting_authorisation",
                "summary": "Start provider OAuth authorisation.",
                "description": "Xero requests granular invoice and payment permissions. Existing connections can repeat this OAuth consent flow to update permissions without disconnecting or clearing sync links. A signed-in Xero callback retains the currently linked organisation.",
                "tags": [
                    "Accounting"
                ],
                "responses": {
                    "200": {
                        "description": "Successful response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "additionalProperties": true
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Error response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": "request failed"
                                }
                            }
                        }
                    }
                },
                "x-fm-route": "Accounting_authorisation",
                "x-fm-source-file": "php/Accounting/authorisation.php",
                "x-fm-auth-modes": [
                    "session_cookie",
                    "api_key_signature",
                    "app_session_signature",
                    "public_xero_get"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "provider": {
                                        "description": "quickbooks, xero, or microsoftbusinesscentral."
                                    },
                                    "ret": {
                                        "description": "Return the URL payload instead of redirecting."
                                    }
                                },
                                "additionalProperties": true,
                                "required": [
                                    "provider"
                                ]
                            }
                        }
                    }
                },
                "security": [
                    {
                        "fmSessionCookie": [],
                        "fmCsrfHeader": []
                    },
                    {
                        "fmApiKeyId": [],
                        "fmApiKeySignature": [],
                        "fmApiKeyNow": []
                    },
                    {
                        "fmAppCid": [],
                        "fmAppSid": [],
                        "fmAppMd5": [],
                        "fmAppJson": []
                    }
                ]
            }
        },
        "/a/Accounting_disconnect": {
            "post": {
                "operationId": "Accounting_disconnect",
                "summary": "Disconnect a provider and optionally clear links.",
                "description": "Source: `php/Accounting/disconnect.php`",
                "tags": [
                    "Accounting"
                ],
                "responses": {
                    "200": {
                        "description": "Successful response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "additionalProperties": true
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Error response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": "request failed"
                                }
                            }
                        }
                    }
                },
                "x-fm-route": "Accounting_disconnect",
                "x-fm-source-file": "php/Accounting/disconnect.php",
                "x-fm-auth-modes": [
                    "session_cookie",
                    "api_key_signature",
                    "app_session_signature"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "provider": {
                                        "description": "quickbooks, xero, or microsoftbusinesscentral."
                                    },
                                    "sure": {
                                        "description": "Must be yes."
                                    },
                                    "clear": {
                                        "description": "Use yes to clear existing provider links."
                                    }
                                },
                                "additionalProperties": true,
                                "required": [
                                    "provider",
                                    "sure"
                                ]
                            }
                        }
                    }
                },
                "security": [
                    {
                        "fmSessionCookie": [],
                        "fmCsrfHeader": []
                    },
                    {
                        "fmApiKeyId": [],
                        "fmApiKeySignature": [],
                        "fmApiKeyNow": []
                    },
                    {
                        "fmAppCid": [],
                        "fmAppSid": [],
                        "fmAppMd5": [],
                        "fmAppJson": []
                    }
                ]
            }
        },
        "/a/Accounting_logLoad": {
            "post": {
                "operationId": "Accounting_logLoad",
                "summary": "Load one provider sync log.",
                "description": "Source: `php/Accounting/logLoad.php`",
                "tags": [
                    "Accounting"
                ],
                "responses": {
                    "200": {
                        "description": "Successful response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "additionalProperties": true
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Error response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": "request failed"
                                }
                            }
                        }
                    }
                },
                "x-fm-route": "Accounting_logLoad",
                "x-fm-source-file": "php/Accounting/logLoad.php",
                "x-fm-auth-modes": [
                    "session_cookie",
                    "api_key_signature",
                    "app_session_signature"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "provider": {
                                        "description": "quickbooks, xero, or microsoftbusinesscentral."
                                    },
                                    "id": {
                                        "description": "Log row ID."
                                    }
                                },
                                "additionalProperties": true,
                                "required": [
                                    "provider",
                                    "id"
                                ]
                            }
                        }
                    }
                },
                "security": [
                    {
                        "fmSessionCookie": [],
                        "fmCsrfHeader": []
                    },
                    {
                        "fmApiKeyId": [],
                        "fmApiKeySignature": [],
                        "fmApiKeyNow": []
                    },
                    {
                        "fmAppCid": [],
                        "fmAppSid": [],
                        "fmAppMd5": [],
                        "fmAppJson": []
                    }
                ]
            }
        },
        "/a/Accounting_logsList": {
            "post": {
                "operationId": "Accounting_logsList",
                "summary": "List provider sync logs.",
                "description": "Source: `php/Accounting/logsList.php`",
                "tags": [
                    "Accounting"
                ],
                "responses": {
                    "200": {
                        "description": "Successful response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "additionalProperties": true
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Error response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": "request failed"
                                }
                            }
                        }
                    }
                },
                "x-fm-route": "Accounting_logsList",
                "x-fm-source-file": "php/Accounting/logsList.php",
                "x-fm-auth-modes": [
                    "session_cookie",
                    "api_key_signature",
                    "app_session_signature"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "provider": {
                                        "description": "quickbooks, xero, or microsoftbusinesscentral."
                                    },
                                    "from": {
                                        "description": "Optional start epoch where supported."
                                    },
                                    "to": {
                                        "description": "Optional end epoch where supported."
                                    }
                                },
                                "additionalProperties": true,
                                "required": [
                                    "provider"
                                ]
                            }
                        }
                    }
                },
                "security": [
                    {
                        "fmSessionCookie": [],
                        "fmCsrfHeader": []
                    },
                    {
                        "fmApiKeyId": [],
                        "fmApiKeySignature": [],
                        "fmApiKeyNow": []
                    },
                    {
                        "fmAppCid": [],
                        "fmAppSid": [],
                        "fmAppMd5": [],
                        "fmAppJson": []
                    }
                ]
            }
        },
        "/a/Accounting_progress": {
            "post": {
                "operationId": "Accounting_progress",
                "summary": "Return current provider sync progress.",
                "description": "Source: `php/Accounting/progress.php`",
                "tags": [
                    "Accounting"
                ],
                "responses": {
                    "200": {
                        "description": "Successful response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "additionalProperties": true
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Error response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": "request failed"
                                }
                            }
                        }
                    }
                },
                "x-fm-route": "Accounting_progress",
                "x-fm-source-file": "php/Accounting/progress.php",
                "x-fm-auth-modes": [
                    "session_cookie",
                    "api_key_signature",
                    "app_session_signature"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "provider": {
                                        "description": "quickbooks, xero, or microsoftbusinesscentral."
                                    }
                                },
                                "additionalProperties": true,
                                "required": [
                                    "provider"
                                ]
                            }
                        }
                    }
                },
                "security": [
                    {
                        "fmSessionCookie": [],
                        "fmCsrfHeader": []
                    },
                    {
                        "fmApiKeyId": [],
                        "fmApiKeySignature": [],
                        "fmApiKeyNow": []
                    },
                    {
                        "fmAppCid": [],
                        "fmAppSid": [],
                        "fmAppMd5": [],
                        "fmAppJson": []
                    }
                ]
            }
        },
        "/a/Accounting_providerCapabilities": {
            "post": {
                "operationId": "Accounting_providerCapabilities",
                "summary": "List supported cloud accounting providers and capabilities.",
                "description": "Source: `php/Accounting/providerCapabilities.php`",
                "tags": [
                    "Accounting"
                ],
                "responses": {
                    "200": {
                        "description": "Successful response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "additionalProperties": true
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Error response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": "request failed"
                                }
                            }
                        }
                    }
                },
                "x-fm-route": "Accounting_providerCapabilities",
                "x-fm-source-file": "php/Accounting/providerCapabilities.php",
                "x-fm-auth-modes": [
                    "session_cookie",
                    "api_key_signature",
                    "app_session_signature"
                ],
                "security": [
                    {
                        "fmSessionCookie": [],
                        "fmCsrfHeader": []
                    },
                    {
                        "fmApiKeyId": [],
                        "fmApiKeySignature": [],
                        "fmApiKeyNow": []
                    },
                    {
                        "fmAppCid": [],
                        "fmAppSid": [],
                        "fmAppMd5": [],
                        "fmAppJson": []
                    }
                ]
            }
        },
        "/a/Accounting_status": {
            "post": {
                "operationId": "Accounting_status",
                "summary": "Return normalized provider connection status.",
                "description": "For Xero, scope_status is current, needs_update, unknown, or disconnected. permissions_update_required is true for a connected broad-only/unknown grant or an explicit insufficient-scope error. This is advisory and does not disable sync. No tokens or raw scope claims are returned.",
                "tags": [
                    "Accounting"
                ],
                "responses": {
                    "200": {
                        "description": "Successful response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "ok": {
                                            "type": "integer"
                                        },
                                        "provider": {
                                            "type": "string"
                                        },
                                        "state": {
                                            "type": "integer"
                                        },
                                        "organisation": {
                                            "type": "string"
                                        },
                                        "scope_status": {
                                            "type": "string"
                                        },
                                        "permissions_update_required": {
                                            "type": "boolean"
                                        }
                                    },
                                    "additionalProperties": true
                                },
                                "example": {
                                    "ok": 1,
                                    "provider": "xero",
                                    "state": 1,
                                    "organisation": "Example Company",
                                    "scope_status": "needs_update",
                                    "permissions_update_required": true
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Error response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": "request failed"
                                }
                            }
                        }
                    }
                },
                "x-fm-route": "Accounting_status",
                "x-fm-source-file": "php/Accounting/status.php",
                "x-fm-auth-modes": [
                    "session_cookie",
                    "api_key_signature",
                    "app_session_signature"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "provider": {
                                        "description": "quickbooks, xero, or microsoftbusinesscentral."
                                    }
                                },
                                "additionalProperties": true,
                                "required": [
                                    "provider"
                                ]
                            },
                            "examples": {
                                "default": {
                                    "summary": "Example request",
                                    "value": {
                                        "provider": "xero"
                                    }
                                }
                            }
                        }
                    }
                },
                "security": [
                    {
                        "fmSessionCookie": [],
                        "fmCsrfHeader": []
                    },
                    {
                        "fmApiKeyId": [],
                        "fmApiKeySignature": [],
                        "fmApiKeyNow": []
                    },
                    {
                        "fmAppCid": [],
                        "fmAppSid": [],
                        "fmAppMd5": [],
                        "fmAppJson": []
                    }
                ]
            }
        },
        "/a/Accounting_sync": {
            "post": {
                "operationId": "Accounting_sync",
                "summary": "Run or resume a provider sync.",
                "description": "Xero errors with permissions_update_required=true indicate that the user should open Xero settings and select Update Permissions. Existing broad-scope connections are not blocked solely because they have not migrated.",
                "tags": [
                    "Accounting"
                ],
                "responses": {
                    "200": {
                        "description": "Successful response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "additionalProperties": true
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Error response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": "request failed"
                                }
                            }
                        }
                    }
                },
                "x-fm-route": "Accounting_sync",
                "x-fm-source-file": "php/Accounting/sync.php",
                "x-fm-auth-modes": [
                    "session_cookie",
                    "api_key_signature",
                    "app_session_signature"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "provider": {
                                        "description": "quickbooks, xero, or microsoftbusinesscentral."
                                    }
                                },
                                "additionalProperties": true,
                                "required": [
                                    "provider"
                                ]
                            }
                        }
                    }
                },
                "security": [
                    {
                        "fmSessionCookie": [],
                        "fmCsrfHeader": []
                    },
                    {
                        "fmApiKeyId": [],
                        "fmApiKeySignature": [],
                        "fmApiKeyNow": []
                    },
                    {
                        "fmAppCid": [],
                        "fmAppSid": [],
                        "fmAppMd5": [],
                        "fmAppJson": []
                    }
                ]
            }
        },
        "/a/Assets_getDataTable": {
            "post": {
                "operationId": "Assets_getDataTable",
                "summary": "List Assets with optional Job creation eligibility filtering",
                "description": "Source: `php/Assets/getDataTable.php`",
                "tags": [
                    "Assets"
                ],
                "responses": {
                    "200": {
                        "description": "Successful response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "additionalProperties": true
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Error response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": "request failed"
                                }
                            }
                        }
                    }
                },
                "x-fm-route": "Assets_getDataTable",
                "x-fm-source-file": "php/Assets/getDataTable.php",
                "x-fm-auth-modes": [
                    "session_cookie",
                    "api_key_signature",
                    "app_session_signature"
                ],
                "requestBody": {
                    "required": false,
                    "content": {
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "jobCreate": {
                                        "type": "integer",
                                        "description": "Set to 1 in CRM2 Job creation pickers to intersect existing filters with the actor role Programme Contract restriction. Creation validates independently."
                                    }
                                },
                                "additionalProperties": true
                            }
                        }
                    }
                },
                "security": [
                    {
                        "fmSessionCookie": [],
                        "fmCsrfHeader": []
                    },
                    {
                        "fmApiKeyId": [],
                        "fmApiKeySignature": [],
                        "fmApiKeyNow": []
                    },
                    {
                        "fmAppCid": [],
                        "fmAppSid": [],
                        "fmAppMd5": [],
                        "fmAppJson": []
                    }
                ]
            }
        },
        "/a/ContractProgrammeImport_upsert": {
            "post": {
                "operationId": "ContractProgrammeImport_upsert",
                "summary": "Receive a Citedel master-data batch",
                "description": "Signed API key, client-admin permission and contractProgrammeImport are required. data contains source, request_key and at most 500 records. The complete batch is atomic; stable source IDs and monotonic revisions prevent duplicates. See ContractProgramme/README.md.",
                "tags": [
                    "ContractProgrammeImport"
                ],
                "responses": {
                    "200": {
                        "description": "Successful response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "additionalProperties": true
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Error response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": "request failed"
                                }
                            }
                        }
                    }
                },
                "x-fm-route": "ContractProgrammeImport_upsert",
                "x-fm-source-file": "php/ContractProgrammeImport/upsert.php",
                "x-fm-auth-modes": [],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "data": {
                                        "type": "string"
                                    }
                                },
                                "additionalProperties": true,
                                "required": [
                                    "data"
                                ]
                            }
                        }
                    }
                },
                "security": []
            }
        },
        "/a/ContractProgramme_addJob": {
            "post": {
                "operationId": "ContractProgramme_addJob",
                "summary": "Programme Contracts: addJob",
                "description": "Requires the manually enabled Programme Contracts capability and Contracts role access. Complex input is JSON in data. See ContractProgramme/README.md.",
                "tags": [
                    "ContractProgramme"
                ],
                "responses": {
                    "200": {
                        "description": "Successful response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "additionalProperties": true
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Error response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": "request failed"
                                }
                            }
                        }
                    }
                },
                "x-fm-route": "ContractProgramme_addJob",
                "x-fm-source-file": "php/ContractProgramme/addJob.php",
                "x-fm-auth-modes": [],
                "requestBody": {
                    "required": false,
                    "content": {
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "data": {
                                        "type": "string"
                                    }
                                },
                                "additionalProperties": true
                            }
                        }
                    }
                },
                "security": []
            }
        },
        "/a/ContractProgramme_bootstrap": {
            "post": {
                "operationId": "ContractProgramme_bootstrap",
                "summary": "Programme Contracts: bootstrap",
                "description": "Requires the manually enabled Programme Contracts capability and Contracts role access. Complex input is JSON in data. See ContractProgramme/README.md.",
                "tags": [
                    "ContractProgramme"
                ],
                "responses": {
                    "200": {
                        "description": "Successful response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "additionalProperties": true
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Error response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": "request failed"
                                }
                            }
                        }
                    }
                },
                "x-fm-route": "ContractProgramme_bootstrap",
                "x-fm-source-file": "php/ContractProgramme/bootstrap.php",
                "x-fm-auth-modes": [],
                "requestBody": {
                    "required": false,
                    "content": {
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "data": {
                                        "type": "string"
                                    }
                                },
                                "additionalProperties": true
                            }
                        }
                    }
                },
                "security": []
            }
        },
        "/a/ContractProgramme_branding": {
            "post": {
                "operationId": "ContractProgramme_branding",
                "summary": "Programme Contracts: branding",
                "description": "Requires the manually enabled Programme Contracts capability and Contracts role access. Complex input is JSON in data. See ContractProgramme/README.md.",
                "tags": [
                    "ContractProgramme"
                ],
                "responses": {
                    "200": {
                        "description": "Successful response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "additionalProperties": true
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Error response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": "request failed"
                                }
                            }
                        }
                    }
                },
                "x-fm-route": "ContractProgramme_branding",
                "x-fm-source-file": "php/ContractProgramme/branding.php",
                "x-fm-auth-modes": [],
                "requestBody": {
                    "required": false,
                    "content": {
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "data": {
                                        "type": "string"
                                    }
                                },
                                "additionalProperties": true
                            }
                        }
                    }
                },
                "security": []
            }
        },
        "/a/ContractProgramme_contract": {
            "post": {
                "operationId": "ContractProgramme_contract",
                "summary": "Programme Contracts: contract",
                "description": "Requires the manually enabled Programme Contracts capability and Contracts role access. Complex input is JSON in data. See ContractProgramme/README.md.",
                "tags": [
                    "ContractProgramme"
                ],
                "responses": {
                    "200": {
                        "description": "Successful response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "additionalProperties": true
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Error response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": "request failed"
                                }
                            }
                        }
                    }
                },
                "x-fm-route": "ContractProgramme_contract",
                "x-fm-source-file": "php/ContractProgramme/contract.php",
                "x-fm-auth-modes": [],
                "requestBody": {
                    "required": false,
                    "content": {
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "data": {
                                        "type": "string"
                                    }
                                },
                                "additionalProperties": true
                            }
                        }
                    }
                },
                "security": []
            }
        },
        "/a/ContractProgramme_createContract": {
            "post": {
                "operationId": "ContractProgramme_createContract",
                "summary": "Create a Programme Contract",
                "description": "Requires Programme Contracts and Contracts View/Add permission. Creates a manual Contract, its programme configuration and Customer/Site links atomically. Source integration may remain enabled.",
                "tags": [
                    "ContractProgramme"
                ],
                "responses": {
                    "200": {
                        "description": "Successful response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "additionalProperties": true
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Error response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": "request failed"
                                }
                            }
                        }
                    }
                },
                "x-fm-route": "ContractProgramme_createContract",
                "x-fm-source-file": "php/ContractProgramme/createContract.php",
                "x-fm-auth-modes": [],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "data": {
                                        "type": "string",
                                        "description": "JSON object: name, customer_id, site_ids (child Customer IDs), optional number, manager_id, area_id, sector, active (0/1/2), date_started, expiry_date, budget, address, notes and type_id."
                                    }
                                },
                                "additionalProperties": true,
                                "required": [
                                    "data"
                                ]
                            }
                        }
                    }
                },
                "security": []
            }
        },
        "/a/ContractProgramme_deleteProgramme": {
            "post": {
                "operationId": "ContractProgramme_deleteProgramme",
                "summary": "Programme Contracts: deleteProgramme",
                "description": "Requires the manually enabled Programme Contracts capability and Contracts role access. Complex input is JSON in data. See ContractProgramme/README.md.",
                "tags": [
                    "ContractProgramme"
                ],
                "responses": {
                    "200": {
                        "description": "Successful response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "additionalProperties": true
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Error response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": "request failed"
                                }
                            }
                        }
                    }
                },
                "x-fm-route": "ContractProgramme_deleteProgramme",
                "x-fm-source-file": "php/ContractProgramme/deleteProgramme.php",
                "x-fm-auth-modes": [],
                "requestBody": {
                    "required": false,
                    "content": {
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "data": {
                                        "type": "string"
                                    }
                                },
                                "additionalProperties": true
                            }
                        }
                    }
                },
                "security": []
            }
        },
        "/a/ContractProgramme_getDataTable": {
            "post": {
                "operationId": "ContractProgramme_getDataTable",
                "summary": "Programme Contracts: getDataTable",
                "description": "Requires the manually enabled Programme Contracts capability and Contracts role access. Complex input is JSON in data. See ContractProgramme/README.md.",
                "tags": [
                    "ContractProgramme"
                ],
                "responses": {
                    "200": {
                        "description": "Successful response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "additionalProperties": true
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Error response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": "request failed"
                                }
                            }
                        }
                    }
                },
                "x-fm-route": "ContractProgramme_getDataTable",
                "x-fm-source-file": "php/ContractProgramme/getDataTable.php",
                "x-fm-auth-modes": [],
                "requestBody": {
                    "required": false,
                    "content": {
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "data": {
                                        "type": "string"
                                    }
                                },
                                "additionalProperties": true
                            }
                        }
                    }
                },
                "security": []
            }
        },
        "/a/ContractProgramme_grades": {
            "post": {
                "operationId": "ContractProgramme_grades",
                "summary": "Programme Contracts: grades",
                "description": "Requires the manually enabled Programme Contracts capability and Contracts role access. Complex input is JSON in data. See ContractProgramme/README.md.",
                "tags": [
                    "ContractProgramme"
                ],
                "responses": {
                    "200": {
                        "description": "Successful response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "additionalProperties": true
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Error response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": "request failed"
                                }
                            }
                        }
                    }
                },
                "x-fm-route": "ContractProgramme_grades",
                "x-fm-source-file": "php/ContractProgramme/grades.php",
                "x-fm-auth-modes": [],
                "requestBody": {
                    "required": false,
                    "content": {
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "data": {
                                        "type": "string"
                                    }
                                },
                                "additionalProperties": true
                            }
                        }
                    }
                },
                "security": []
            }
        },
        "/a/ContractProgramme_holidays": {
            "post": {
                "operationId": "ContractProgramme_holidays",
                "summary": "Programme Contracts: holidays",
                "description": "Requires the manually enabled Programme Contracts capability and Contracts role access. Complex input is JSON in data. See ContractProgramme/README.md.",
                "tags": [
                    "ContractProgramme"
                ],
                "responses": {
                    "200": {
                        "description": "Successful response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "additionalProperties": true
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Error response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": "request failed"
                                }
                            }
                        }
                    }
                },
                "x-fm-route": "ContractProgramme_holidays",
                "x-fm-source-file": "php/ContractProgramme/holidays.php",
                "x-fm-auth-modes": [],
                "requestBody": {
                    "required": false,
                    "content": {
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "data": {
                                        "type": "string"
                                    }
                                },
                                "additionalProperties": true
                            }
                        }
                    }
                },
                "security": []
            }
        },
        "/a/ContractProgramme_move": {
            "post": {
                "operationId": "ContractProgramme_move",
                "summary": "Programme Contracts: move",
                "description": "Requires the manually enabled Programme Contracts capability and Contracts role access. Complex input is JSON in data. See ContractProgramme/README.md.",
                "tags": [
                    "ContractProgramme"
                ],
                "responses": {
                    "200": {
                        "description": "Successful response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "additionalProperties": true
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Error response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": "request failed"
                                }
                            }
                        }
                    }
                },
                "x-fm-route": "ContractProgramme_move",
                "x-fm-source-file": "php/ContractProgramme/move.php",
                "x-fm-auth-modes": [],
                "requestBody": {
                    "required": false,
                    "content": {
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "data": {
                                        "type": "string"
                                    }
                                },
                                "additionalProperties": true
                            }
                        }
                    }
                },
                "security": []
            }
        },
        "/a/ContractProgramme_newRun": {
            "post": {
                "operationId": "ContractProgramme_newRun",
                "summary": "Programme Contracts: newRun",
                "description": "Requires the manually enabled Programme Contracts capability and Contracts role access. Complex input is JSON in data. See ContractProgramme/README.md.",
                "tags": [
                    "ContractProgramme"
                ],
                "responses": {
                    "200": {
                        "description": "Successful response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "additionalProperties": true
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Error response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": "request failed"
                                }
                            }
                        }
                    }
                },
                "x-fm-route": "ContractProgramme_newRun",
                "x-fm-source-file": "php/ContractProgramme/newRun.php",
                "x-fm-auth-modes": [],
                "requestBody": {
                    "required": false,
                    "content": {
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "data": {
                                        "type": "string"
                                    }
                                },
                                "additionalProperties": true
                            }
                        }
                    }
                },
                "security": []
            }
        },
        "/a/ContractProgramme_portalAccess": {
            "post": {
                "operationId": "ContractProgramme_portalAccess",
                "summary": "Programme Contracts: portalAccess",
                "description": "Requires the manually enabled Programme Contracts capability and Contracts role access. Complex input is JSON in data. See ContractProgramme/README.md.",
                "tags": [
                    "ContractProgramme"
                ],
                "responses": {
                    "200": {
                        "description": "Successful response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "additionalProperties": true
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Error response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": "request failed"
                                }
                            }
                        }
                    }
                },
                "x-fm-route": "ContractProgramme_portalAccess",
                "x-fm-source-file": "php/ContractProgramme/portalAccess.php",
                "x-fm-auth-modes": [],
                "requestBody": {
                    "required": false,
                    "content": {
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "data": {
                                        "type": "string"
                                    }
                                },
                                "additionalProperties": true
                            }
                        }
                    }
                },
                "security": []
            }
        },
        "/a/ContractProgramme_preview": {
            "post": {
                "operationId": "ContractProgramme_preview",
                "summary": "Programme Contracts: preview",
                "description": "Requires the manually enabled Programme Contracts capability and Contracts role access. Complex input is JSON in data. See ContractProgramme/README.md.",
                "tags": [
                    "ContractProgramme"
                ],
                "responses": {
                    "200": {
                        "description": "Successful response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "additionalProperties": true
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Error response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": "request failed"
                                }
                            }
                        }
                    }
                },
                "x-fm-route": "ContractProgramme_preview",
                "x-fm-source-file": "php/ContractProgramme/preview.php",
                "x-fm-auth-modes": [],
                "requestBody": {
                    "required": false,
                    "content": {
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "data": {
                                        "type": "string"
                                    }
                                },
                                "additionalProperties": true
                            }
                        }
                    }
                },
                "security": []
            }
        },
        "/a/ContractProgramme_progress": {
            "post": {
                "operationId": "ContractProgramme_progress",
                "summary": "Programme Contracts: progress",
                "description": "Requires the manually enabled Programme Contracts capability and Contracts role access. Complex input is JSON in data. See ContractProgramme/README.md.",
                "tags": [
                    "ContractProgramme"
                ],
                "responses": {
                    "200": {
                        "description": "Successful response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "additionalProperties": true
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Error response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": "request failed"
                                }
                            }
                        }
                    }
                },
                "x-fm-route": "ContractProgramme_progress",
                "x-fm-source-file": "php/ContractProgramme/progress.php",
                "x-fm-auth-modes": [],
                "requestBody": {
                    "required": false,
                    "content": {
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "data": {
                                        "type": "string"
                                    }
                                },
                                "additionalProperties": true
                            }
                        }
                    }
                },
                "security": []
            }
        },
        "/a/ContractProgramme_publish": {
            "post": {
                "operationId": "ContractProgramme_publish",
                "summary": "Programme Contracts: publish",
                "description": "Requires the manually enabled Programme Contracts capability and Contracts role access. Complex input is JSON in data. See ContractProgramme/README.md.",
                "tags": [
                    "ContractProgramme"
                ],
                "responses": {
                    "200": {
                        "description": "Successful response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "additionalProperties": true
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Error response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": "request failed"
                                }
                            }
                        }
                    }
                },
                "x-fm-route": "ContractProgramme_publish",
                "x-fm-source-file": "php/ContractProgramme/publish.php",
                "x-fm-auth-modes": [],
                "requestBody": {
                    "required": false,
                    "content": {
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "data": {
                                        "type": "string"
                                    }
                                },
                                "additionalProperties": true
                            }
                        }
                    }
                },
                "security": []
            }
        },
        "/a/ContractProgramme_qi": {
            "post": {
                "operationId": "ContractProgramme_qi",
                "summary": "Programme Contracts: qi",
                "description": "Requires the manually enabled Programme Contracts capability and Contracts role access. Complex input is JSON in data. See ContractProgramme/README.md.",
                "tags": [
                    "ContractProgramme"
                ],
                "responses": {
                    "200": {
                        "description": "Successful response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "additionalProperties": true
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Error response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": "request failed"
                                }
                            }
                        }
                    }
                },
                "x-fm-route": "ContractProgramme_qi",
                "x-fm-source-file": "php/ContractProgramme/qi.php",
                "x-fm-auth-modes": [],
                "requestBody": {
                    "required": false,
                    "content": {
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "data": {
                                        "type": "string"
                                    }
                                },
                                "additionalProperties": true
                            }
                        }
                    }
                },
                "security": []
            }
        },
        "/a/ContractProgramme_report": {
            "post": {
                "operationId": "ContractProgramme_report",
                "summary": "Programme Contracts: report",
                "description": "Requires the manually enabled Programme Contracts capability and Contracts role access. Complex input is JSON in data. See ContractProgramme/README.md.",
                "tags": [
                    "ContractProgramme"
                ],
                "responses": {
                    "200": {
                        "description": "Successful response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "additionalProperties": true
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Error response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": "request failed"
                                }
                            }
                        }
                    }
                },
                "x-fm-route": "ContractProgramme_report",
                "x-fm-source-file": "php/ContractProgramme/report.php",
                "x-fm-auth-modes": [],
                "requestBody": {
                    "required": false,
                    "content": {
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "data": {
                                        "type": "string"
                                    }
                                },
                                "additionalProperties": true
                            }
                        }
                    }
                },
                "security": []
            }
        },
        "/a/ContractProgramme_route": {
            "post": {
                "operationId": "ContractProgramme_route",
                "summary": "Programme Contracts: route",
                "description": "Requires the manually enabled Programme Contracts capability and Contracts role access. Complex input is JSON in data. See ContractProgramme/README.md.",
                "tags": [
                    "ContractProgramme"
                ],
                "responses": {
                    "200": {
                        "description": "Successful response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "additionalProperties": true
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Error response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": "request failed"
                                }
                            }
                        }
                    }
                },
                "x-fm-route": "ContractProgramme_route",
                "x-fm-source-file": "php/ContractProgramme/route.php",
                "x-fm-auth-modes": [],
                "requestBody": {
                    "required": false,
                    "content": {
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "data": {
                                        "type": "string"
                                    }
                                },
                                "additionalProperties": true
                            }
                        }
                    }
                },
                "security": []
            }
        },
        "/a/ContractProgramme_saveBranding": {
            "post": {
                "operationId": "ContractProgramme_saveBranding",
                "summary": "Programme Contracts: saveBranding",
                "description": "Requires the manually enabled Programme Contracts capability and Contracts role access. Complex input is JSON in data. See ContractProgramme/README.md.",
                "tags": [
                    "ContractProgramme"
                ],
                "responses": {
                    "200": {
                        "description": "Successful response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "additionalProperties": true
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Error response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": "request failed"
                                }
                            }
                        }
                    }
                },
                "x-fm-route": "ContractProgramme_saveBranding",
                "x-fm-source-file": "php/ContractProgramme/saveBranding.php",
                "x-fm-auth-modes": [],
                "requestBody": {
                    "required": false,
                    "content": {
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "data": {
                                        "type": "string"
                                    }
                                },
                                "additionalProperties": true
                            }
                        }
                    }
                },
                "security": []
            }
        },
        "/a/ContractProgramme_saveConfig": {
            "post": {
                "operationId": "ContractProgramme_saveConfig",
                "summary": "Programme Contracts: saveConfig",
                "description": "Requires the manually enabled Programme Contracts capability and Contracts role access. Complex input is JSON in data. See ContractProgramme/README.md.",
                "tags": [
                    "ContractProgramme"
                ],
                "responses": {
                    "200": {
                        "description": "Successful response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "additionalProperties": true
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Error response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": "request failed"
                                }
                            }
                        }
                    }
                },
                "x-fm-route": "ContractProgramme_saveConfig",
                "x-fm-source-file": "php/ContractProgramme/saveConfig.php",
                "x-fm-auth-modes": [],
                "requestBody": {
                    "required": false,
                    "content": {
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "data": {
                                        "type": "string"
                                    }
                                },
                                "additionalProperties": true
                            }
                        }
                    }
                },
                "security": []
            }
        },
        "/a/ContractProgramme_saveGrades": {
            "post": {
                "operationId": "ContractProgramme_saveGrades",
                "summary": "Programme Contracts: saveGrades",
                "description": "Requires the manually enabled Programme Contracts capability and Contracts role access. Complex input is JSON in data. See ContractProgramme/README.md.",
                "tags": [
                    "ContractProgramme"
                ],
                "responses": {
                    "200": {
                        "description": "Successful response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "additionalProperties": true
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Error response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": "request failed"
                                }
                            }
                        }
                    }
                },
                "x-fm-route": "ContractProgramme_saveGrades",
                "x-fm-source-file": "php/ContractProgramme/saveGrades.php",
                "x-fm-auth-modes": [],
                "requestBody": {
                    "required": false,
                    "content": {
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "data": {
                                        "type": "string"
                                    }
                                },
                                "additionalProperties": true
                            }
                        }
                    }
                },
                "security": []
            }
        },
        "/a/ContractProgramme_saveHoliday": {
            "post": {
                "operationId": "ContractProgramme_saveHoliday",
                "summary": "Programme Contracts: saveHoliday",
                "description": "Requires the manually enabled Programme Contracts capability and Contracts role access. Complex input is JSON in data. See ContractProgramme/README.md.",
                "tags": [
                    "ContractProgramme"
                ],
                "responses": {
                    "200": {
                        "description": "Successful response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "additionalProperties": true
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Error response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": "request failed"
                                }
                            }
                        }
                    }
                },
                "x-fm-route": "ContractProgramme_saveHoliday",
                "x-fm-source-file": "php/ContractProgramme/saveHoliday.php",
                "x-fm-auth-modes": [],
                "requestBody": {
                    "required": false,
                    "content": {
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "data": {
                                        "type": "string"
                                    }
                                },
                                "additionalProperties": true
                            }
                        }
                    }
                },
                "security": []
            }
        },
        "/a/ContractProgramme_savePortalAccess": {
            "post": {
                "operationId": "ContractProgramme_savePortalAccess",
                "summary": "Programme Contracts: savePortalAccess",
                "description": "Requires the manually enabled Programme Contracts capability and Contracts role access. Complex input is JSON in data. See ContractProgramme/README.md.",
                "tags": [
                    "ContractProgramme"
                ],
                "responses": {
                    "200": {
                        "description": "Successful response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "additionalProperties": true
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Error response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": "request failed"
                                }
                            }
                        }
                    }
                },
                "x-fm-route": "ContractProgramme_savePortalAccess",
                "x-fm-source-file": "php/ContractProgramme/savePortalAccess.php",
                "x-fm-auth-modes": [],
                "requestBody": {
                    "required": false,
                    "content": {
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "data": {
                                        "type": "string"
                                    }
                                },
                                "additionalProperties": true
                            }
                        }
                    }
                },
                "security": []
            }
        },
        "/a/ContractProgramme_saveProgramme": {
            "post": {
                "operationId": "ContractProgramme_saveProgramme",
                "summary": "Programme Contracts: saveProgramme",
                "description": "Requires the manually enabled Programme Contracts capability and Contracts role access. Complex input is JSON in data. See ContractProgramme/README.md.",
                "tags": [
                    "ContractProgramme"
                ],
                "responses": {
                    "200": {
                        "description": "Successful response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "additionalProperties": true
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Error response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": "request failed"
                                }
                            }
                        }
                    }
                },
                "x-fm-route": "ContractProgramme_saveProgramme",
                "x-fm-source-file": "php/ContractProgramme/saveProgramme.php",
                "x-fm-auth-modes": [],
                "requestBody": {
                    "required": false,
                    "content": {
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "data": {
                                        "type": "string"
                                    }
                                },
                                "additionalProperties": true
                            }
                        }
                    }
                },
                "security": []
            }
        },
        "/a/ContractProgramme_saveRoute": {
            "post": {
                "operationId": "ContractProgramme_saveRoute",
                "summary": "Programme Contracts: saveRoute",
                "description": "Requires the manually enabled Programme Contracts capability and Contracts role access. Complex input is JSON in data. See ContractProgramme/README.md.",
                "tags": [
                    "ContractProgramme"
                ],
                "responses": {
                    "200": {
                        "description": "Successful response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "additionalProperties": true
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Error response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": "request failed"
                                }
                            }
                        }
                    }
                },
                "x-fm-route": "ContractProgramme_saveRoute",
                "x-fm-source-file": "php/ContractProgramme/saveRoute.php",
                "x-fm-auth-modes": [],
                "requestBody": {
                    "required": false,
                    "content": {
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "data": {
                                        "type": "string"
                                    }
                                },
                                "additionalProperties": true
                            }
                        }
                    }
                },
                "security": []
            }
        },
        "/a/ContractProgramme_saveSectors": {
            "post": {
                "operationId": "ContractProgramme_saveSectors",
                "summary": "Maintain Programme Contract sectors (client administrator only)",
                "description": "Source: `php/ContractProgramme/saveSectors.php`",
                "tags": [
                    "ContractProgramme"
                ],
                "responses": {
                    "200": {
                        "description": "Successful response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "additionalProperties": true
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Error response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": "request failed"
                                }
                            }
                        }
                    }
                },
                "x-fm-route": "ContractProgramme_saveSectors",
                "x-fm-source-file": "php/ContractProgramme/saveSectors.php",
                "x-fm-auth-modes": [],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "data": {
                                        "description": "JSON object with entries (up to 200 objects with stable id and name; id 0 creates) or legacy sectors names, plus revision from bootstrap.sector_settings. Omitted active entries are retired; renames preserve linked sector labels"
                                    }
                                },
                                "additionalProperties": true,
                                "required": [
                                    "data"
                                ]
                            }
                        }
                    }
                },
                "security": []
            }
        },
        "/a/ContractProgramme_saveTasks": {
            "post": {
                "operationId": "ContractProgramme_saveTasks",
                "summary": "Programme Contracts: saveTasks",
                "description": "Requires the manually enabled Programme Contracts capability and Contracts role access. Complex input is JSON in data. See ContractProgramme/README.md.",
                "tags": [
                    "ContractProgramme"
                ],
                "responses": {
                    "200": {
                        "description": "Successful response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "additionalProperties": true
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Error response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": "request failed"
                                }
                            }
                        }
                    }
                },
                "x-fm-route": "ContractProgramme_saveTasks",
                "x-fm-source-file": "php/ContractProgramme/saveTasks.php",
                "x-fm-auth-modes": [],
                "requestBody": {
                    "required": false,
                    "content": {
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "data": {
                                        "type": "string"
                                    }
                                },
                                "additionalProperties": true
                            }
                        }
                    }
                },
                "security": []
            }
        },
        "/a/ContractProgramme_setStart": {
            "post": {
                "operationId": "ContractProgramme_setStart",
                "summary": "Programme Contracts: setStart",
                "description": "Requires the manually enabled Programme Contracts capability and Contracts role access. Complex input is JSON in data. See ContractProgramme/README.md.",
                "tags": [
                    "ContractProgramme"
                ],
                "responses": {
                    "200": {
                        "description": "Successful response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "additionalProperties": true
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Error response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": "request failed"
                                }
                            }
                        }
                    }
                },
                "x-fm-route": "ContractProgramme_setStart",
                "x-fm-source-file": "php/ContractProgramme/setStart.php",
                "x-fm-auth-modes": [],
                "requestBody": {
                    "required": false,
                    "content": {
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "data": {
                                        "type": "string"
                                    }
                                },
                                "additionalProperties": true
                            }
                        }
                    }
                },
                "security": []
            }
        },
        "/a/Customer_get": {
            "post": {
                "operationId": "Customer_get",
                "summary": "Fetch a customer by id.",
                "description": "Returns a customer row from the current tenant, or an outsourced customer row when the `o<uid>i<id>` external id format is used. If `fields` is omitted, the endpoint returns the default API-safe field set.",
                "tags": [
                    "Customer"
                ],
                "responses": {
                    "200": {
                        "description": "Successful response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "id": {
                                            "type": "integer"
                                        },
                                        "name": {
                                            "type": "string"
                                        },
                                        "email": {
                                            "type": "string"
                                        },
                                        "mobile": {
                                            "type": "string"
                                        }
                                    },
                                    "additionalProperties": true
                                },
                                "example": {
                                    "id": 8842,
                                    "name": "Acme Boilers Ltd",
                                    "email": "ops@acme.example",
                                    "mobile": "07700111222"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Error response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": "requested customer does not exist"
                                }
                            }
                        }
                    }
                },
                "x-fm-route": "Customer_get",
                "x-fm-source-file": "php/Customer/get.php",
                "x-fm-auth-modes": [
                    "session_cookie",
                    "api_key_signature",
                    "app_session_signature"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "Customer id or outsourced customer id in `o<uid>i<id>` format.",
                                        "example": "8842"
                                    },
                                    "fields": {
                                        "type": "array",
                                        "description": "JSON array of allowed customer field names to return.",
                                        "example": "[\"id\",\"name\",\"email\"]"
                                    }
                                },
                                "additionalProperties": true,
                                "required": [
                                    "id"
                                ]
                            },
                            "examples": {
                                "default": {
                                    "summary": "Load a customer with a limited field list.",
                                    "value": {
                                        "id": "8842",
                                        "fields": "[\"id\",\"name\",\"email\",\"mobile\"]"
                                    }
                                }
                            }
                        }
                    }
                },
                "security": [
                    {
                        "fmSessionCookie": [],
                        "fmCsrfHeader": []
                    },
                    {
                        "fmApiKeyId": [],
                        "fmApiKeySignature": [],
                        "fmApiKeyNow": []
                    },
                    {
                        "fmAppCid": [],
                        "fmAppSid": [],
                        "fmAppMd5": [],
                        "fmAppJson": []
                    }
                ]
            }
        },
        "/a/Customers_getDataTable": {
            "post": {
                "operationId": "Customers_getDataTable",
                "summary": "List Customers with optional Job creation eligibility filtering",
                "description": "Source: `php/Customers/getDataTable.php`",
                "tags": [
                    "Customers"
                ],
                "responses": {
                    "200": {
                        "description": "Successful response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "additionalProperties": true
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Error response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": "request failed"
                                }
                            }
                        }
                    }
                },
                "x-fm-route": "Customers_getDataTable",
                "x-fm-source-file": "php/Customers/getDataTable.php",
                "x-fm-auth-modes": [
                    "session_cookie",
                    "api_key_signature",
                    "app_session_signature"
                ],
                "requestBody": {
                    "required": false,
                    "content": {
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "jobCreate": {
                                        "type": "integer",
                                        "description": "Set to 1 in CRM2 Job creation pickers to intersect existing filters with the actor role Programme Contract restriction. Creation validates independently."
                                    }
                                },
                                "additionalProperties": true
                            }
                        }
                    }
                },
                "security": [
                    {
                        "fmSessionCookie": [],
                        "fmCsrfHeader": []
                    },
                    {
                        "fmApiKeyId": [],
                        "fmApiKeySignature": [],
                        "fmApiKeyNow": []
                    },
                    {
                        "fmAppCid": [],
                        "fmAppSid": [],
                        "fmAppMd5": [],
                        "fmAppJson": []
                    }
                ]
            }
        },
        "/a/Customers_search": {
            "post": {
                "operationId": "Customers_search",
                "summary": "Find customer IDs by customer details, including primary telephone numbers.",
                "description": "Read-only search in the authenticated tenant. All nonblank filters are combined with AND; phone groups landline OR mobile. Excludes deleted customers, includes inactive customers, and orders IDs ascending. Phone formatting is significant; no number normalization or Telephony feature is required. Fetch returned IDs through Customers_getById for contact details.",
                "tags": [
                    "Customers"
                ],
                "responses": {
                    "200": {
                        "description": "Successful response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "ids": {
                                            "type": "array",
                                            "items": {}
                                        }
                                    },
                                    "additionalProperties": true
                                },
                                "example": {
                                    "ids": [
                                        1042,
                                        1088
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Error response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": "invalid parameter: results-per-page"
                                }
                            }
                        }
                    }
                },
                "x-fm-route": "Customers_search",
                "x-fm-source-file": "php/Customers/search.php",
                "x-fm-auth-modes": [
                    "session_cookie",
                    "api_key_signature",
                    "app_session_signature"
                ],
                "requestBody": {
                    "required": false,
                    "content": {
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "name": {
                                        "type": "string",
                                        "description": "Customer name. Trimmed, case-insensitive exact match unless a leading or trailing % enables wildcard matching. Blank values are ignored."
                                    },
                                    "email": {
                                        "type": "string",
                                        "description": "Primary email. Trimmed, case-insensitive exact match unless a leading or trailing % enables wildcard matching. Blank values are ignored."
                                    },
                                    "postcode": {
                                        "type": "string",
                                        "description": "Postcode. Trimmed, case-insensitive exact match unless a leading or trailing % enables wildcard matching. Blank values are ignored."
                                    },
                                    "contacts": {
                                        "type": "string",
                                        "description": "Stored contacts column; structured contacts are not decoded. Trimmed, case-insensitive exact match unless a leading or trailing % enables wildcard matching. Blank values are ignored."
                                    },
                                    "landline": {
                                        "type": "string",
                                        "description": "Primary landline. Trimmed, case-insensitive exact match unless a leading or trailing % enables wildcard matching. Blank values are ignored."
                                    },
                                    "mobile": {
                                        "type": "string",
                                        "description": "Primary mobile. Trimmed, case-insensitive exact match unless a leading or trailing % enables wildcard matching. Blank values are ignored."
                                    },
                                    "phone": {
                                        "type": "string",
                                        "description": "Match primary landline OR mobile; does not search Key Contacts. Trimmed, case-insensitive exact match unless a leading or trailing % enables wildcard matching. Blank values are ignored."
                                    },
                                    "parent_id": {
                                        "type": "integer",
                                        "description": "Parent customer ID; 0 selects top-level customers."
                                    },
                                    "custom": {
                                        "type": "string",
                                        "description": "JSON object mapping custom-field keys to exact or wildcard values; blank and zero-string values are ignored."
                                    },
                                    "results-per-page": {
                                        "type": "integer",
                                        "description": "Maximum IDs per page; defaults to 100, must be positive."
                                    },
                                    "current-page": {
                                        "type": "integer",
                                        "description": "Zero-based page index; defaults to 0, must be non-negative."
                                    }
                                },
                                "additionalProperties": true
                            },
                            "examples": {
                                "default": {
                                    "summary": "Example request",
                                    "value": {
                                        "phone": "07700111222",
                                        "results-per-page": "50",
                                        "current-page": "0"
                                    }
                                }
                            }
                        }
                    }
                },
                "security": [
                    {
                        "fmSessionCookie": [],
                        "fmCsrfHeader": []
                    },
                    {
                        "fmApiKeyId": [],
                        "fmApiKeySignature": [],
                        "fmApiKeyNow": []
                    },
                    {
                        "fmAppCid": [],
                        "fmAppSid": [],
                        "fmAppMd5": [],
                        "fmAppJson": []
                    }
                ]
            }
        },
        "/a/Departments_import": {
            "post": {
                "operationId": "Departments_import",
                "summary": "Import Departments and optional parent relationships (client administrator only)",
                "description": "Source: `php/Departments/import.php`",
                "tags": [
                    "Departments"
                ],
                "responses": {
                    "200": {
                        "description": "Successful response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "additionalProperties": true
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Error response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": "request failed"
                                }
                            }
                        }
                    }
                },
                "x-fm-route": "Departments_import",
                "x-fm-source-file": "php/Departments/import.php",
                "x-fm-auth-modes": [
                    "session_cookie",
                    "api_key_signature",
                    "app_session_signature"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "map": {
                                        "description": "JSON array of mapping objects with to=name or parentDepartmentID"
                                    },
                                    "rows": {
                                        "description": "JSON array of rows in mapping order"
                                    }
                                },
                                "additionalProperties": true,
                                "required": [
                                    "map",
                                    "rows"
                                ]
                            }
                        }
                    }
                },
                "security": [
                    {
                        "fmSessionCookie": [],
                        "fmCsrfHeader": []
                    },
                    {
                        "fmApiKeyId": [],
                        "fmApiKeySignature": [],
                        "fmApiKeyNow": []
                    },
                    {
                        "fmAppCid": [],
                        "fmAppSid": [],
                        "fmAppMd5": [],
                        "fmAppJson": []
                    }
                ]
            }
        },
        "/a/DigitalWasteTracking_readiness": {
            "post": {
                "operationId": "DigitalWasteTracking_readiness",
                "summary": "Check Digital Waste Tracking software setup.",
                "description": "Client administrators only; requires the UK Digital Waste Tracking account feature. Returns credential-presence booleans, private storage status, profile requirements, form mapping gaps, active notification recipient count and PAT availability. Does not contact Defra or verify government approval. Credentials and API codes are never returned.",
                "tags": [
                    "DigitalWasteTracking"
                ],
                "responses": {
                    "200": {
                        "description": "Successful response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "additionalProperties": true
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Error response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": "request failed"
                                }
                            }
                        }
                    }
                },
                "x-fm-route": "DigitalWasteTracking_readiness",
                "x-fm-source-file": "php/DigitalWasteTracking/readiness.php",
                "x-fm-auth-modes": [],
                "security": []
            }
        },
        "/a/Form_contractChecklistFields": {
            "post": {
                "operationId": "Form_contractChecklistFields",
                "summary": "List individual Contract checklist question and answer mappings for a Job AutoDoc",
                "description": "Source: `php/Form/contractChecklistFields.php`",
                "tags": [
                    "Form"
                ],
                "responses": {
                    "200": {
                        "description": "Successful response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "additionalProperties": true
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Error response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": "request failed"
                                }
                            }
                        }
                    }
                },
                "x-fm-route": "Form_contractChecklistFields",
                "x-fm-source-file": "php/Form/contractChecklistFields.php",
                "x-fm-auth-modes": [
                    "session_cookie",
                    "api_key_signature",
                    "app_session_signature"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "id": {
                                        "description": "Job Form ID"
                                    }
                                },
                                "additionalProperties": true,
                                "required": [
                                    "id"
                                ]
                            }
                        }
                    }
                },
                "security": [
                    {
                        "fmSessionCookie": [],
                        "fmCsrfHeader": []
                    },
                    {
                        "fmApiKeyId": [],
                        "fmApiKeySignature": [],
                        "fmApiKeyNow": []
                    },
                    {
                        "fmAppCid": [],
                        "fmAppSid": [],
                        "fmAppMd5": [],
                        "fmAppJson": []
                    }
                ]
            }
        },
        "/a/GoodReturned_delete": {
            "post": {
                "operationId": "GoodReturned_delete",
                "summary": "Delete goods-return notes",
                "description": "Requires tenant upgrade 797. Soft-deletes matching active headers and their active lines together. Writes checked history and tenant deletion audits in one transaction. Does not reverse stock or recalculate totals. Accepts mapped scalar or native-array field filters; at least one filter is required. No matches returns ok without another audit.",
                "tags": [
                    "GoodReturned"
                ],
                "responses": {
                    "200": {
                        "description": "Success or application error; deletion failures roll back the transaction.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "oneOf": [
                                        {
                                            "type": "object",
                                            "required": [
                                                "ok"
                                            ],
                                            "properties": {
                                                "ok": {
                                                    "type": "integer",
                                                    "enum": [
                                                        1
                                                    ]
                                                }
                                            }
                                        },
                                        {
                                            "$ref": "#/components/schemas/Error"
                                        }
                                    ]
                                },
                                "examples": {
                                    "success": {
                                        "value": {
                                            "ok": 1
                                        }
                                    },
                                    "error": {
                                        "value": {
                                            "error": "goods return operation failed"
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "x-fm-route": "GoodReturned_delete",
                "x-fm-source-file": "php/GoodReturned/delete.php",
                "x-fm-auth-modes": [
                    "session_cookie",
                    "api_key_signature",
                    "app_session_signature"
                ],
                "requestBody": {
                    "required": false,
                    "content": {
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "id": {
                                        "oneOf": [
                                            {
                                                "type": "integer",
                                                "minimum": 1
                                            },
                                            {
                                                "type": "array",
                                                "items": {
                                                    "type": "integer",
                                                    "minimum": 1
                                                }
                                            }
                                        ]
                                    }
                                },
                                "additionalProperties": true
                            },
                            "examples": {
                                "default": {
                                    "summary": "Example request",
                                    "value": {
                                        "id": 123
                                    }
                                }
                            }
                        }
                    }
                },
                "security": [
                    {
                        "fmSessionCookie": [],
                        "fmCsrfHeader": []
                    },
                    {
                        "fmApiKeyId": [],
                        "fmApiKeySignature": [],
                        "fmApiKeyNow": []
                    },
                    {
                        "fmAppCid": [],
                        "fmAppSid": [],
                        "fmAppMd5": [],
                        "fmAppJson": []
                    }
                ]
            }
        },
        "/a/GoodsReturnedEntry_deleteData": {
            "post": {
                "operationId": "GoodsReturnedEntry_deleteData",
                "summary": "Delete goods-return lines",
                "description": "Requires tenant upgrade 797. Soft-deletes matching active lines; the header and sibling lines remain active. Writes checked history and tenant deletion audits in one transaction. Does not reverse stock or recalculate totals. Accepts mapped scalar or native-array field filters; at least one filter is required. No matches returns ok without another audit.",
                "tags": [
                    "GoodsReturnedEntry"
                ],
                "responses": {
                    "200": {
                        "description": "Success or application error; deletion failures roll back the transaction.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "oneOf": [
                                        {
                                            "type": "object",
                                            "required": [
                                                "ok"
                                            ],
                                            "properties": {
                                                "ok": {
                                                    "type": "integer",
                                                    "enum": [
                                                        1
                                                    ]
                                                }
                                            }
                                        },
                                        {
                                            "$ref": "#/components/schemas/Error"
                                        }
                                    ]
                                },
                                "examples": {
                                    "success": {
                                        "value": {
                                            "ok": 1
                                        }
                                    },
                                    "error": {
                                        "value": {
                                            "error": "goods return operation failed"
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "x-fm-route": "GoodsReturnedEntry_deleteData",
                "x-fm-source-file": "php/GoodsReturnedEntry/deleteData.php",
                "x-fm-auth-modes": [
                    "session_cookie",
                    "api_key_signature",
                    "app_session_signature"
                ],
                "requestBody": {
                    "required": false,
                    "content": {
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "id": {
                                        "oneOf": [
                                            {
                                                "type": "integer",
                                                "minimum": 1
                                            },
                                            {
                                                "type": "array",
                                                "items": {
                                                    "type": "integer",
                                                    "minimum": 1
                                                }
                                            }
                                        ]
                                    }
                                },
                                "additionalProperties": true
                            },
                            "examples": {
                                "default": {
                                    "summary": "Example request",
                                    "value": {
                                        "id": 123
                                    }
                                }
                            }
                        }
                    }
                },
                "security": [
                    {
                        "fmSessionCookie": [],
                        "fmCsrfHeader": []
                    },
                    {
                        "fmApiKeyId": [],
                        "fmApiKeySignature": [],
                        "fmApiKeyNow": []
                    },
                    {
                        "fmAppCid": [],
                        "fmAppSid": [],
                        "fmAppMd5": [],
                        "fmAppJson": []
                    }
                ]
            }
        },
        "/a/GoodsReturnedNote_delete": {
            "post": {
                "operationId": "GoodsReturnedNote_delete",
                "summary": "Delete goods-return notes",
                "description": "Requires tenant upgrade 797. Soft-deletes matching active headers and their active lines together. Writes checked history and tenant deletion audits in one transaction. Does not reverse stock or recalculate totals.Accepts one positive id; missing or already-deleted records return the legacy error.",
                "tags": [
                    "GoodsReturnedNote"
                ],
                "responses": {
                    "200": {
                        "description": "Success or application error; deletion failures roll back the transaction.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "oneOf": [
                                        {
                                            "type": "object",
                                            "required": [
                                                "ok"
                                            ],
                                            "properties": {
                                                "ok": {
                                                    "type": "integer",
                                                    "enum": [
                                                        1
                                                    ]
                                                }
                                            }
                                        },
                                        {
                                            "$ref": "#/components/schemas/Error"
                                        }
                                    ]
                                },
                                "examples": {
                                    "success": {
                                        "value": {
                                            "ok": 1
                                        }
                                    },
                                    "error": {
                                        "value": {
                                            "error": "goods return operation failed"
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "x-fm-route": "GoodsReturnedNote_delete",
                "x-fm-source-file": "php/GoodsReturnedNote/delete.php",
                "x-fm-auth-modes": [
                    "session_cookie",
                    "api_key_signature",
                    "app_session_signature"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "id": {
                                        "type": "integer",
                                        "description": "Positive record ID."
                                    }
                                },
                                "additionalProperties": true,
                                "required": [
                                    "id"
                                ]
                            },
                            "examples": {
                                "default": {
                                    "summary": "Example request",
                                    "value": {
                                        "id": 123
                                    }
                                }
                            }
                        }
                    }
                },
                "security": [
                    {
                        "fmSessionCookie": [],
                        "fmCsrfHeader": []
                    },
                    {
                        "fmApiKeyId": [],
                        "fmApiKeySignature": [],
                        "fmApiKeyNow": []
                    },
                    {
                        "fmAppCid": [],
                        "fmAppSid": [],
                        "fmAppMd5": [],
                        "fmAppJson": []
                    }
                ]
            }
        },
        "/a/GoodsReturned_delete": {
            "post": {
                "operationId": "GoodsReturned_delete",
                "summary": "Delete goods-return notes",
                "description": "Requires tenant upgrade 797. Soft-deletes matching active headers and their active lines together. Writes checked history and tenant deletion audits in one transaction. Does not reverse stock or recalculate totals.Accepts one positive id; missing or already-deleted records return the legacy error.",
                "tags": [
                    "GoodsReturned"
                ],
                "responses": {
                    "200": {
                        "description": "Success or application error; deletion failures roll back the transaction.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "oneOf": [
                                        {
                                            "type": "object",
                                            "required": [
                                                "ok"
                                            ],
                                            "properties": {
                                                "ok": {
                                                    "type": "integer",
                                                    "enum": [
                                                        1
                                                    ]
                                                }
                                            }
                                        },
                                        {
                                            "$ref": "#/components/schemas/Error"
                                        }
                                    ]
                                },
                                "examples": {
                                    "success": {
                                        "value": {
                                            "ok": 1
                                        }
                                    },
                                    "error": {
                                        "value": {
                                            "error": "goods return operation failed"
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "x-fm-route": "GoodsReturned_delete",
                "x-fm-source-file": "php/GoodsReturned/delete.php",
                "x-fm-auth-modes": [
                    "session_cookie",
                    "api_key_signature",
                    "app_session_signature"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "id": {
                                        "type": "integer",
                                        "description": "Positive record ID."
                                    }
                                },
                                "additionalProperties": true,
                                "required": [
                                    "id"
                                ]
                            },
                            "examples": {
                                "default": {
                                    "summary": "Example request",
                                    "value": {
                                        "id": 123
                                    }
                                }
                            }
                        }
                    }
                },
                "security": [
                    {
                        "fmSessionCookie": [],
                        "fmCsrfHeader": []
                    },
                    {
                        "fmApiKeyId": [],
                        "fmApiKeySignature": [],
                        "fmApiKeyNow": []
                    },
                    {
                        "fmAppCid": [],
                        "fmAppSid": [],
                        "fmAppMd5": [],
                        "fmAppJson": []
                    }
                ]
            }
        },
        "/a/InvoiceRow_add": {
            "post": {
                "operationId": "InvoiceRow_add",
                "summary": "Add one invoice row.",
                "description": "Creates a single line item without requiring callers to submit the full invoice `rows` payload.",
                "tags": [
                    "InvoiceRow"
                ],
                "responses": {
                    "200": {
                        "description": "Successful response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "additionalProperties": true
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Error response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": "request failed"
                                }
                            }
                        }
                    }
                },
                "x-fm-route": "InvoiceRow_add",
                "x-fm-source-file": "php/InvoiceRow/add.php",
                "x-fm-auth-modes": [
                    "session_cookie",
                    "api_key_signature",
                    "app_session_signature"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "invoice_id": {
                                        "type": "integer",
                                        "description": "Invoice id."
                                    },
                                    "row": {
                                        "type": "object",
                                        "description": "Invoice line item data."
                                    },
                                    "position": {
                                        "type": "integer",
                                        "description": "Optional row position. Defaults to append."
                                    }
                                },
                                "additionalProperties": true,
                                "required": [
                                    "invoice_id",
                                    "row"
                                ]
                            }
                        }
                    }
                },
                "security": [
                    {
                        "fmSessionCookie": [],
                        "fmCsrfHeader": []
                    },
                    {
                        "fmApiKeyId": [],
                        "fmApiKeySignature": [],
                        "fmApiKeyNow": []
                    },
                    {
                        "fmAppCid": [],
                        "fmAppSid": [],
                        "fmAppMd5": [],
                        "fmAppJson": []
                    }
                ]
            }
        },
        "/a/InvoiceRow_appendMany": {
            "post": {
                "operationId": "InvoiceRow_appendMany",
                "summary": "Append multiple invoice rows.",
                "description": "Adds line items without requiring callers to submit the existing invoice `rows` payload.",
                "tags": [
                    "InvoiceRow"
                ],
                "responses": {
                    "200": {
                        "description": "Successful response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "additionalProperties": true
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Error response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": "request failed"
                                }
                            }
                        }
                    }
                },
                "x-fm-route": "InvoiceRow_appendMany",
                "x-fm-source-file": "php/InvoiceRow/appendMany.php",
                "x-fm-auth-modes": [
                    "session_cookie",
                    "api_key_signature",
                    "app_session_signature"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "invoice_id": {
                                        "type": "integer",
                                        "description": "Invoice id."
                                    },
                                    "rows": {
                                        "type": "array",
                                        "description": "Invoice line item rows to append."
                                    }
                                },
                                "additionalProperties": true,
                                "required": [
                                    "invoice_id",
                                    "rows"
                                ]
                            }
                        }
                    }
                },
                "security": [
                    {
                        "fmSessionCookie": [],
                        "fmCsrfHeader": []
                    },
                    {
                        "fmApiKeyId": [],
                        "fmApiKeySignature": [],
                        "fmApiKeyNow": []
                    },
                    {
                        "fmAppCid": [],
                        "fmAppSid": [],
                        "fmAppMd5": [],
                        "fmAppJson": []
                    }
                ]
            }
        },
        "/a/InvoiceRow_delete": {
            "post": {
                "operationId": "InvoiceRow_delete",
                "summary": "Delete one invoice row.",
                "description": "Soft-deletes a single invoice line item and refreshes invoice and linked job totals.",
                "tags": [
                    "InvoiceRow"
                ],
                "responses": {
                    "200": {
                        "description": "Successful response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "additionalProperties": true
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Error response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": "request failed"
                                }
                            }
                        }
                    }
                },
                "x-fm-route": "InvoiceRow_delete",
                "x-fm-source-file": "php/InvoiceRow/delete.php",
                "x-fm-auth-modes": [
                    "session_cookie",
                    "api_key_signature",
                    "app_session_signature"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "invoice_id": {
                                        "type": "integer",
                                        "description": "Invoice id."
                                    },
                                    "row_id": {
                                        "type": "integer",
                                        "description": "Invoice row id."
                                    }
                                },
                                "additionalProperties": true,
                                "required": [
                                    "invoice_id",
                                    "row_id"
                                ]
                            }
                        }
                    }
                },
                "security": [
                    {
                        "fmSessionCookie": [],
                        "fmCsrfHeader": []
                    },
                    {
                        "fmApiKeyId": [],
                        "fmApiKeySignature": [],
                        "fmApiKeyNow": []
                    },
                    {
                        "fmAppCid": [],
                        "fmAppSid": [],
                        "fmAppMd5": [],
                        "fmAppJson": []
                    }
                ]
            }
        },
        "/a/InvoiceRow_edit": {
            "post": {
                "operationId": "InvoiceRow_edit",
                "summary": "Update one invoice row.",
                "description": "Updates a single line item without requiring callers to submit the full invoice `rows` payload. An existing job-owned row cannot be reassigned or unassigned through this endpoint; an unassigned row may adopt only a job already linked to the invoice.",
                "tags": [
                    "InvoiceRow"
                ],
                "responses": {
                    "200": {
                        "description": "Successful response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "additionalProperties": true
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Error response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": "request failed"
                                }
                            }
                        }
                    }
                },
                "x-fm-route": "InvoiceRow_edit",
                "x-fm-source-file": "php/InvoiceRow/edit.php",
                "x-fm-auth-modes": [
                    "session_cookie",
                    "api_key_signature",
                    "app_session_signature"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "invoice_id": {
                                        "type": "integer",
                                        "description": "Invoice id."
                                    },
                                    "row": {
                                        "type": "object",
                                        "description": "Invoice line item data."
                                    },
                                    "row_id": {
                                        "type": "integer",
                                        "description": "Existing invoice row id. Legacy callers may pass position when no row id is available."
                                    }
                                },
                                "additionalProperties": true,
                                "required": [
                                    "invoice_id",
                                    "row"
                                ]
                            }
                        }
                    }
                },
                "security": [
                    {
                        "fmSessionCookie": [],
                        "fmCsrfHeader": []
                    },
                    {
                        "fmApiKeyId": [],
                        "fmApiKeySignature": [],
                        "fmApiKeyNow": []
                    },
                    {
                        "fmAppCid": [],
                        "fmAppSid": [],
                        "fmAppMd5": [],
                        "fmAppJson": []
                    }
                ]
            }
        },
        "/a/InvoiceRow_list": {
            "post": {
                "operationId": "InvoiceRow_list",
                "summary": "List editable invoice rows.",
                "description": "Returns invoice rows from the row table when available, lazily hydrating the table from the legacy invoice `rows` payload for this invoice.",
                "tags": [
                    "InvoiceRow"
                ],
                "responses": {
                    "200": {
                        "description": "Successful response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "additionalProperties": true
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Error response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": "request failed"
                                }
                            }
                        }
                    }
                },
                "x-fm-route": "InvoiceRow_list",
                "x-fm-source-file": "php/InvoiceRow/list.php",
                "x-fm-auth-modes": [
                    "session_cookie",
                    "api_key_signature",
                    "app_session_signature"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "invoice_id": {
                                        "type": "integer",
                                        "description": "Invoice id."
                                    },
                                    "job_id": {
                                        "type": "integer",
                                        "description": "Optional linked job filter."
                                    }
                                },
                                "additionalProperties": true,
                                "required": [
                                    "invoice_id"
                                ]
                            }
                        }
                    }
                },
                "security": [
                    {
                        "fmSessionCookie": [],
                        "fmCsrfHeader": []
                    },
                    {
                        "fmApiKeyId": [],
                        "fmApiKeySignature": [],
                        "fmApiKeyNow": []
                    },
                    {
                        "fmAppCid": [],
                        "fmAppSid": [],
                        "fmAppMd5": [],
                        "fmAppJson": []
                    }
                ]
            }
        },
        "/a/Invoice_get": {
            "post": {
                "operationId": "Invoice_get",
                "summary": "Fetch an invoice by id.",
                "description": "Returns a single invoice row and normalizes the `rows` payload through `Invoice_lineItems(...)` before returning it.",
                "tags": [
                    "Invoice"
                ],
                "responses": {
                    "200": {
                        "description": "Successful response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "id": {
                                            "type": "integer"
                                        },
                                        "appointment_id": {
                                            "type": "integer"
                                        },
                                        "customer_id": {
                                            "type": "integer"
                                        },
                                        "total": {
                                            "type": "string"
                                        },
                                        "paid": {
                                            "type": "string"
                                        },
                                        "status": {
                                            "type": "string"
                                        },
                                        "invoice_no": {
                                            "type": "string"
                                        },
                                        "rows": {
                                            "type": "string"
                                        }
                                    },
                                    "additionalProperties": true
                                },
                                "example": {
                                    "id": 91021,
                                    "appointment_id": 5977924,
                                    "customer_id": 8842,
                                    "total": "120.00",
                                    "paid": "0.00",
                                    "status": "unpaid",
                                    "invoice_no": "INV-91021",
                                    "rows": "[{\"name\":\"Boiler Service\",\"qty\":1,\"total\":120}]"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Error response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": "invoice does not exist"
                                }
                            }
                        }
                    }
                },
                "x-fm-route": "Invoice_get",
                "x-fm-source-file": "php/Invoice/get.php",
                "x-fm-auth-modes": [
                    "session_cookie",
                    "api_key_signature",
                    "app_session_signature"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "id": {
                                        "type": "integer",
                                        "description": "Invoice id.",
                                        "example": 91021
                                    }
                                },
                                "additionalProperties": true,
                                "required": [
                                    "id"
                                ]
                            },
                            "examples": {
                                "default": {
                                    "summary": "Load one invoice.",
                                    "value": {
                                        "id": "91021"
                                    }
                                }
                            }
                        }
                    }
                },
                "security": [
                    {
                        "fmSessionCookie": [],
                        "fmCsrfHeader": []
                    },
                    {
                        "fmApiKeyId": [],
                        "fmApiKeySignature": [],
                        "fmApiKeyNow": []
                    },
                    {
                        "fmAppCid": [],
                        "fmAppSid": [],
                        "fmAppMd5": [],
                        "fmAppJson": []
                    }
                ]
            }
        },
        "/a/Jobs_getDT": {
            "post": {
                "operationId": "Jobs_getDT",
                "summary": "Return appointment grid rows for DataTables.",
                "description": "Provides the CRM jobs table payload, including packed row arrays, DataTables counts, and many optional filters used by the CRM1 UI.",
                "tags": [
                    "Jobs"
                ],
                "responses": {
                    "200": {
                        "description": "Successful response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "draw": {
                                            "type": "integer"
                                        },
                                        "recordsTotal": {
                                            "type": "integer"
                                        },
                                        "recordsFiltered": {
                                            "type": "integer"
                                        },
                                        "data": {
                                            "type": "array",
                                            "items": {}
                                        }
                                    },
                                    "additionalProperties": true
                                },
                                "example": {
                                    "draw": 1,
                                    "recordsTotal": 4821,
                                    "recordsFiltered": 138,
                                    "data": [
                                        [
                                            [
                                                5977924,
                                                3,
                                                0,
                                                1771802400,
                                                0
                                            ],
                                            "2026-02-25 17:00:00",
                                            [
                                                "2026-02-24 09:00:00",
                                                "",
                                                "2026-02-24 09:00:00",
                                                1771923600
                                            ],
                                            "Annual Service",
                                            "Check boiler pressure and safety valve.",
                                            "42|42|0|John Smith",
                                            [
                                                "J-10441",
                                                0,
                                                "FM-CUST-884",
                                                "",
                                                {
                                                    "source": "manual",
                                                    "user_id": 42
                                                }
                                            ],
                                            "0|8842",
                                            {
                                                "name": "Acme Boilers Ltd",
                                                "street_address1": "12 River Road",
                                                "town": "Leeds",
                                                "postcode": "LS1 4AB"
                                            },
                                            "<p class=\"hide\">17</p><span title=\"Click to view Recorded Form Data for this form\">Service Sheet</span><br/><span class=\"small formnum\" style=\"float:right\" title=\"Form Number\">2211</span>",
                                            1,
                                            "0|0",
                                            2,
                                            "",
                                            5977924,
                                            [
                                                19,
                                                3
                                            ],
                                            [
                                                "1",
                                                {
                                                    "pdf_sent": 1,
                                                    "recurrence_id": 19,
                                                    "recurrence_no": 3
                                                },
                                                [
                                                    {
                                                        "sent_date": "2026-02-23 18:41:05",
                                                        "status": "sent",
                                                        "recipients": "ops@acme.example",
                                                        "customer_id": "8842",
                                                        "customer_type": "0",
                                                        "job_id": "5977924"
                                                    }
                                                ]
                                            ],
                                            "",
                                            "",
                                            "3/12 jobs completed",
                                            9912,
                                            [
                                                {
                                                    "id": "772",
                                                    "po_num": "PO-77421"
                                                }
                                            ],
                                            "Q-20441",
                                            [
                                                44,
                                                "Planned Maintenance Contract 2026"
                                            ],
                                            [
                                                {
                                                    "id": "1201",
                                                    "user_id": "42",
                                                    "status": "0",
                                                    "expiry_date": "2026-03-01 23:59:59",
                                                    "cdate": "2026-02-23 18:12:00",
                                                    "meta": "{}",
                                                    "recipient_email": "ops@acme.example",
                                                    "sig_field": "customer_signature"
                                                }
                                            ],
                                            1,
                                            0,
                                            1,
                                            [
                                                501,
                                                502
                                            ],
                                            "3/12 jobs completed",
                                            "[{\"user_id\":42,\"name\":\"John Smith\"}]",
                                            "",
                                            "Take combustion reading before leaving."
                                        ]
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Error response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": "function called with no parameters"
                                }
                            }
                        }
                    }
                },
                "x-fm-route": "Jobs_getDT",
                "x-fm-source-file": "php/Jobs/getDT.php",
                "x-fm-auth-modes": [
                    "session_cookie",
                    "api_key_signature",
                    "app_session_signature"
                ],
                "x-fm-row-map": [
                    {
                        "index": 0,
                        "name": "job_meta",
                        "type": "array",
                        "description": "Job identifiers and outsource flags.",
                        "shape": "[job_id, department_id, meta.outsourcing, cdate, meta.outsourced]"
                    },
                    {
                        "index": 1,
                        "name": "due_date",
                        "type": "string",
                        "description": "Job due date/time."
                    },
                    {
                        "index": 2,
                        "name": "meeting_time",
                        "type": "array",
                        "description": "Scheduled time and epoch values.",
                        "shape": "[meeting_time_local, '', original_meeting_time, meeting_time_e]"
                    },
                    {
                        "index": 3,
                        "name": "appointment_type",
                        "type": "string",
                        "description": "Job type name."
                    },
                    {
                        "index": 4,
                        "name": "notes",
                        "type": "string",
                        "description": "Job notes."
                    },
                    {
                        "index": 5,
                        "name": "user_assignment",
                        "type": "string-packed",
                        "description": "Assigned/current user and type.",
                        "shape": "user_id|current_user_id|user_type|username"
                    },
                    {
                        "index": 6,
                        "name": "job_ref",
                        "type": "array",
                        "description": "Job reference values and creation metadata.",
                        "shape": "[job_ref, form_type, job_ref_customer, job_ref_reason, creation_meta]"
                    },
                    {
                        "index": 7,
                        "name": "target_ref",
                        "type": "string-packed",
                        "description": "Customer/asset reference.",
                        "shape": "customer_type|customer_id[|outsource_customer_name]"
                    },
                    {
                        "index": 8,
                        "name": "customer_details",
                        "type": "object-like",
                        "description": "Customer/address structure returned by Job_getCustomerDetails."
                    },
                    {
                        "index": 9,
                        "name": "form_display_html",
                        "type": "string",
                        "description": "Rendered form HTML snippet shown in grid."
                    },
                    {
                        "index": 10,
                        "name": "on_app",
                        "type": "int",
                        "description": "Sync-to-device flag."
                    },
                    {
                        "index": 11,
                        "name": "status",
                        "type": "string-packed",
                        "description": "Completion and user status.",
                        "shape": "is_complete|user_status"
                    },
                    {
                        "index": 12,
                        "name": "priority",
                        "type": "int",
                        "description": "Priority value."
                    },
                    {
                        "index": 13,
                        "name": "actions_placeholder",
                        "type": "string",
                        "description": "Reserved/placeholder actions column."
                    },
                    {
                        "index": 14,
                        "name": "job_id",
                        "type": "int",
                        "description": "Job ID (duplicate for table behavior)."
                    },
                    {
                        "index": 15,
                        "name": "recurrence",
                        "type": "array",
                        "description": "Recurring IDs for the job.",
                        "shape": "[recurrence_id, recurrence_no]"
                    },
                    {
                        "index": 16,
                        "name": "pdf_sent",
                        "type": "array",
                        "description": "PDF sent state, meta and mail history.",
                        "shape": "[pdf_sent_flag, meta, mails[]]"
                    },
                    {
                        "index": 17,
                        "name": "deprecated",
                        "type": "string",
                        "description": "Deprecated blank column."
                    },
                    {
                        "index": 18,
                        "name": "asset_owner",
                        "type": "string",
                        "description": "Asset owner customer name (when asset job)."
                    },
                    {
                        "index": 19,
                        "name": "recurring_notes",
                        "type": "string",
                        "description": "Recurring series notes."
                    },
                    {
                        "index": 20,
                        "name": "quote_id",
                        "type": "int|string",
                        "description": "Linked quote ID, or empty string."
                    },
                    {
                        "index": 21,
                        "name": "purchase_orders",
                        "type": "list",
                        "description": "Linked purchase order records."
                    },
                    {
                        "index": 22,
                        "name": "quote_num",
                        "type": "string",
                        "description": "Linked quote number, or empty string."
                    },
                    {
                        "index": 23,
                        "name": "contract",
                        "type": "array",
                        "description": "Linked contract pair.",
                        "shape": "[contract_id, contract_name]"
                    },
                    {
                        "index": 24,
                        "name": "signature_requests",
                        "type": "list",
                        "description": "Signature request rows for the job."
                    },
                    {
                        "index": 25,
                        "name": "signature_pending",
                        "type": "int",
                        "description": "Count of pending signature requests."
                    },
                    {
                        "index": 26,
                        "name": "signature_completed",
                        "type": "int",
                        "description": "Count of completed signature requests."
                    },
                    {
                        "index": 27,
                        "name": "has_files",
                        "type": "int",
                        "description": "1 if related files exist, else 0."
                    },
                    {
                        "index": 28,
                        "name": "task_links",
                        "type": "list",
                        "description": "Linked task IDs."
                    },
                    {
                        "index": 29,
                        "name": "recurrence_progress",
                        "type": "string",
                        "description": "Recurring completion summary text."
                    },
                    {
                        "index": 30,
                        "name": "attendees",
                        "type": "string",
                        "description": "Attendees payload from meetings.attendees."
                    },
                    {
                        "index": 31,
                        "name": "date_completed_e",
                        "type": "int|string",
                        "description": "Completion epoch timestamp, or empty string when unset."
                    },
                    {
                        "index": 32,
                        "name": "internal_notes",
                        "type": "string",
                        "description": "Internal notes from job meta."
                    }
                ],
                "requestBody": {
                    "required": false,
                    "content": {
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "start": {
                                        "description": "Zero-based row offset for pagination."
                                    },
                                    "length": {
                                        "description": "Page size (number of rows to return)."
                                    },
                                    "draw": {
                                        "description": "DataTables draw counter echoed in response."
                                    },
                                    "search.value": {
                                        "description": "Free-text search term."
                                    },
                                    "search.fields": {
                                        "description": "JSON array of search scopes (or 'all')."
                                    },
                                    "order.0.column": {
                                        "description": "DataTables column index for sort mapping."
                                    },
                                    "order.0.dir": {
                                        "description": "Sort direction: asc or desc."
                                    },
                                    "dateFrom": {
                                        "description": "Start date filter (local date string)."
                                    },
                                    "dateTo": {
                                        "description": "End date filter (local date string)."
                                    },
                                    "daysFrom": {
                                        "description": "Relative day offset start from today."
                                    },
                                    "daysTo": {
                                        "description": "Relative day offset end from today."
                                    },
                                    "appointment-time": {
                                        "description": "Hour-of-day filter (0-23, timezone adjusted)."
                                    },
                                    "actions": {
                                        "description": "Action-state filter (e.g. signature requested/obtained)."
                                    },
                                    "id": {
                                        "description": "Exact job ID filter."
                                    },
                                    "o_jobid": {
                                        "description": "Outsourced job ID filter from job meta."
                                    },
                                    "on_app": {
                                        "description": "Filter by app visibility flag."
                                    },
                                    "recurs": {
                                        "description": "Filter recurring vs non-recurring jobs."
                                    },
                                    "hide_secondary": {
                                        "description": "Exclude secondary jobs when truthy."
                                    },
                                    "user_id": {
                                        "description": "Assigned/current user filter (-1 for unassigned)."
                                    },
                                    "user_type": {
                                        "description": "Internal vs outsourced user filter."
                                    },
                                    "parent_id": {
                                        "description": "Parent customer filter (includes descendants)."
                                    },
                                    "include": {
                                        "description": "With parent_id=2, include parent only."
                                    },
                                    "department_id": {
                                        "description": "Department filter."
                                    },
                                    "job_ref": {
                                        "description": "Job reference contains filter."
                                    },
                                    "job_ref_customer": {
                                        "description": "Customer job reference contains filter."
                                    },
                                    "overdue": {
                                        "description": "Due-state filter: overdue or duesoon."
                                    },
                                    "report_sent": {
                                        "description": "Filter by report/PDF sent metadata."
                                    },
                                    "invoice_sent": {
                                        "description": "Filter by invoice sent state."
                                    },
                                    "client": {
                                        "description": "Client/customer/asset name search filter."
                                    },
                                    "address": {
                                        "description": "Address text search filter."
                                    },
                                    "job_type_ids": {
                                        "description": "JSON array of type IDs; negatives exclude those types while retaining jobs with no type."
                                    },
                                    "contract_ids": {
                                        "description": "JSON array of contract IDs to include."
                                    },
                                    "form_ids": {
                                        "description": "JSON array of form IDs to include."
                                    },
                                    "form_num": {
                                        "description": "Exact form number filter."
                                    },
                                    "form_name": {
                                        "description": "Form name/number text filter."
                                    },
                                    "priority": {
                                        "description": "Priority equals filter."
                                    },
                                    "date_completed": {
                                        "description": "Completion date text match filter."
                                    },
                                    "status": {
                                        "description": "Job status filter, optional user status suffix."
                                    }
                                },
                                "additionalProperties": true
                            },
                            "examples": {
                                "default": {
                                    "summary": "Retrieve the first page of open jobs for the next 7 days, sorted by scheduled date/time.",
                                    "value": {
                                        "draw": "1",
                                        "start": "0",
                                        "length": "25",
                                        "daysFrom": "0",
                                        "daysTo": "7",
                                        "status": "0",
                                        "order.0.column": "0",
                                        "order.0.dir": "asc",
                                        "search.value": "",
                                        "search.fields": "[\"all\"]"
                                    }
                                }
                            }
                        }
                    }
                },
                "security": [
                    {
                        "fmSessionCookie": [],
                        "fmCsrfHeader": []
                    },
                    {
                        "fmApiKeyId": [],
                        "fmApiKeySignature": [],
                        "fmApiKeyNow": []
                    },
                    {
                        "fmAppCid": [],
                        "fmAppSid": [],
                        "fmAppMd5": [],
                        "fmAppJson": []
                    }
                ]
            }
        },
        "/a/QuoteRecurring_delete": {
            "post": {
                "operationId": "QuoteRecurring_delete",
                "summary": "Soft-delete a quote recurrence while retaining its quotes.",
                "description": "Source: `php/QuoteRecurring/delete.php`",
                "tags": [
                    "QuoteRecurring"
                ],
                "responses": {
                    "200": {
                        "description": "Successful response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "additionalProperties": true
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Error response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": "request failed"
                                }
                            }
                        }
                    }
                },
                "x-fm-route": "QuoteRecurring_delete",
                "x-fm-source-file": "php/QuoteRecurring/delete.php",
                "x-fm-auth-modes": [
                    "session_cookie",
                    "api_key_signature",
                    "app_session_signature"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "id": {
                                        "type": "integer"
                                    }
                                },
                                "additionalProperties": true,
                                "required": [
                                    "id"
                                ]
                            }
                        }
                    }
                },
                "security": [
                    {
                        "fmSessionCookie": [],
                        "fmCsrfHeader": []
                    },
                    {
                        "fmApiKeyId": [],
                        "fmApiKeySignature": [],
                        "fmApiKeyNow": []
                    },
                    {
                        "fmAppCid": [],
                        "fmAppSid": [],
                        "fmAppMd5": [],
                        "fmAppJson": []
                    }
                ]
            }
        },
        "/a/QuoteRecurring_get": {
            "post": {
                "operationId": "QuoteRecurring_get",
                "summary": "Read an accessible quote recurrence.",
                "description": "Source: `php/QuoteRecurring/get.php`",
                "tags": [
                    "QuoteRecurring"
                ],
                "responses": {
                    "200": {
                        "description": "Successful response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "additionalProperties": true
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Error response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": "request failed"
                                }
                            }
                        }
                    }
                },
                "x-fm-route": "QuoteRecurring_get",
                "x-fm-source-file": "php/QuoteRecurring/get.php",
                "x-fm-auth-modes": [],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "id": {
                                        "type": "integer"
                                    }
                                },
                                "additionalProperties": true,
                                "required": [
                                    "id"
                                ]
                            }
                        }
                    }
                },
                "security": []
            }
        },
        "/a/QuoteRecurring_getRequestedDetails": {
            "post": {
                "operationId": "QuoteRecurring_getRequestedDetails",
                "summary": "Read mapped quote recurrence fields within Quotes visibility.",
                "description": "Source: `php/QuoteRecurring/getRequestedDetails.php`",
                "tags": [
                    "QuoteRecurring"
                ],
                "responses": {
                    "200": {
                        "description": "Successful response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "additionalProperties": true
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Error response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": "request failed"
                                }
                            }
                        }
                    }
                },
                "x-fm-route": "QuoteRecurring_getRequestedDetails",
                "x-fm-source-file": "php/QuoteRecurring/getRequestedDetails.php",
                "x-fm-auth-modes": [],
                "requestBody": {
                    "required": false,
                    "content": {
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "ids": {
                                        "type": "array"
                                    },
                                    "fields": {
                                        "type": "array"
                                    }
                                },
                                "additionalProperties": true
                            }
                        }
                    }
                },
                "security": []
            }
        },
        "/a/QuoteRecurring_save": {
            "post": {
                "operationId": "QuoteRecurring_save",
                "summary": "Create or edit a tenant-enabled quote recurrence.",
                "description": "Source: `php/QuoteRecurring/save.php`",
                "tags": [
                    "QuoteRecurring"
                ],
                "responses": {
                    "200": {
                        "description": "Successful response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "additionalProperties": true
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Error response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": "request failed"
                                }
                            }
                        }
                    }
                },
                "x-fm-route": "QuoteRecurring_save",
                "x-fm-source-file": "php/QuoteRecurring/save.php",
                "x-fm-auth-modes": [
                    "session_cookie",
                    "api_key_signature",
                    "app_session_signature"
                ],
                "requestBody": {
                    "required": false,
                    "content": {
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "quote_id": {
                                        "type": "integer",
                                        "description": "Seed quote for creation."
                                    },
                                    "id": {
                                        "type": "integer",
                                        "description": "Recurrence ID for editing."
                                    },
                                    "name": {
                                        "type": "string"
                                    },
                                    "next_date": {
                                        "type": "string",
                                        "description": "Account-local YYYY-MM-DD first/next occurrence."
                                    },
                                    "every": {
                                        "type": "integer",
                                        "description": "0 week, 1 month, 2 year, 3 days, 4 weeks, 5 months, 6 years."
                                    },
                                    "on": {
                                        "type": "string",
                                        "description": "JSON day selection or positive interval."
                                    },
                                    "expiry": {
                                        "type": "string"
                                    },
                                    "active": {
                                        "type": "integer"
                                    },
                                    "copy_items": {
                                        "type": "integer"
                                    }
                                },
                                "additionalProperties": true
                            }
                        }
                    }
                },
                "security": [
                    {
                        "fmSessionCookie": [],
                        "fmCsrfHeader": []
                    },
                    {
                        "fmApiKeyId": [],
                        "fmApiKeySignature": [],
                        "fmApiKeyNow": []
                    },
                    {
                        "fmAppCid": [],
                        "fmAppSid": [],
                        "fmAppMd5": [],
                        "fmAppJson": []
                    }
                ]
            }
        },
        "/a/QuotesRecurring_getDataTable": {
            "post": {
                "operationId": "QuotesRecurring_getDataTable",
                "summary": "List accessible recurring quotation rules in the standard table format.",
                "description": "Source: `php/QuotesRecurring/getDataTable.php`",
                "tags": [
                    "QuotesRecurring"
                ],
                "responses": {
                    "200": {
                        "description": "Successful response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "additionalProperties": true
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Error response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": "request failed"
                                }
                            }
                        }
                    }
                },
                "x-fm-route": "QuotesRecurring_getDataTable",
                "x-fm-source-file": "php/QuotesRecurring/getDataTable.php",
                "x-fm-auth-modes": [],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "fields": {
                                        "type": "array"
                                    },
                                    "start": {
                                        "type": "integer"
                                    },
                                    "length": {
                                        "type": "integer"
                                    },
                                    "advanceSearch": {
                                        "type": "array"
                                    }
                                },
                                "additionalProperties": true,
                                "required": [
                                    "fields"
                                ]
                            }
                        }
                    }
                },
                "security": []
            }
        },
        "/a/QuotesRecurring_getExportData": {
            "post": {
                "operationId": "QuotesRecurring_getExportData",
                "summary": "Export recurring quotation definitions with a saved map.",
                "description": "Use _ids=1 to select accessible IDs, then send _ids and fields as JSON arrays. Rows contain id and positional f0, f1 values.",
                "tags": [
                    "QuotesRecurring"
                ],
                "responses": {
                    "200": {
                        "description": "Successful response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "additionalProperties": true
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Error response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": "request failed"
                                }
                            }
                        }
                    }
                },
                "x-fm-route": "QuotesRecurring_getExportData",
                "x-fm-source-file": "php/QuotesRecurring/getExportData.php",
                "x-fm-auth-modes": [],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "_ids": {
                                        "type": "string"
                                    },
                                    "fields": {
                                        "type": "string"
                                    }
                                },
                                "additionalProperties": true,
                                "required": [
                                    "_ids"
                                ]
                            }
                        }
                    }
                },
                "security": []
            }
        },
        "/a/Report_exportJobDurationComparison": {
            "post": {
                "operationId": "Report_exportJobDurationComparison",
                "summary": "Return CSV-ready current-period job duration details for one job type.",
                "description": "Source: `php/Report/exportJobDurationComparison.php`",
                "tags": [
                    "Reports"
                ],
                "responses": {
                    "200": {
                        "description": "Successful response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "additionalProperties": true
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Error response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": "request failed"
                                }
                            }
                        }
                    }
                },
                "x-fm-route": "Report_exportJobDurationComparison",
                "x-fm-source-file": "php/Report/exportJobDurationComparison.php",
                "x-fm-auth-modes": [
                    "session_cookie",
                    "api_key_signature"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "jobTypeID": {
                                        "description": "Exact job type ID."
                                    },
                                    "daysFrom": {
                                        "description": "Relative start day or fixed start timestamp."
                                    },
                                    "daysTo": {
                                        "description": "Relative end day or fixed end timestamp."
                                    }
                                },
                                "additionalProperties": true,
                                "required": [
                                    "jobTypeID",
                                    "daysFrom",
                                    "daysTo"
                                ]
                            }
                        }
                    }
                },
                "security": [
                    {
                        "fmSessionCookie": [],
                        "fmCsrfHeader": []
                    },
                    {
                        "fmApiKeyId": [],
                        "fmApiKeySignature": [],
                        "fmApiKeyNow": []
                    }
                ]
            }
        },
        "/a/Report_getJobDurationComparison": {
            "post": {
                "operationId": "Report_getJobDurationComparison",
                "summary": "Compare actual and expected job durations by job type.",
                "description": "Source: `php/Report/getJobDurationComparison.php`",
                "tags": [
                    "Reports"
                ],
                "responses": {
                    "200": {
                        "description": "Successful response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "additionalProperties": true
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Error response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": "request failed"
                                }
                            }
                        }
                    }
                },
                "x-fm-route": "Report_getJobDurationComparison",
                "x-fm-source-file": "php/Report/getJobDurationComparison.php",
                "x-fm-auth-modes": [
                    "session_cookie",
                    "api_key_signature"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "daysFrom": {
                                        "description": "Relative start day or fixed start timestamp."
                                    },
                                    "daysTo": {
                                        "description": "Relative end day or fixed end timestamp."
                                    },
                                    "durationType": {
                                        "description": "Use 1 for fixed timestamps; other values use relative days."
                                    },
                                    "user": {
                                        "description": "Assigned internal user IDs."
                                    },
                                    "customer": {
                                        "description": "Customer IDs, including descendants and owned assets."
                                    },
                                    "jobType": {
                                        "description": "Exact job type IDs."
                                    }
                                },
                                "additionalProperties": true,
                                "required": [
                                    "daysFrom",
                                    "daysTo"
                                ]
                            }
                        }
                    }
                },
                "security": [
                    {
                        "fmSessionCookie": [],
                        "fmCsrfHeader": []
                    },
                    {
                        "fmApiKeyId": [],
                        "fmApiKeySignature": [],
                        "fmApiKeyNow": []
                    }
                ]
            }
        },
        "/a/Report_getJobDurationComparisonDetails": {
            "post": {
                "operationId": "Report_getJobDurationComparisonDetails",
                "summary": "Return paginated current-period job duration details for one job type.",
                "description": "Source: `php/Report/getJobDurationComparisonDetails.php`",
                "tags": [
                    "Reports"
                ],
                "responses": {
                    "200": {
                        "description": "Successful response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "additionalProperties": true
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Error response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": "request failed"
                                }
                            }
                        }
                    }
                },
                "x-fm-route": "Report_getJobDurationComparisonDetails",
                "x-fm-source-file": "php/Report/getJobDurationComparisonDetails.php",
                "x-fm-auth-modes": [
                    "session_cookie",
                    "api_key_signature"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "jobTypeID": {
                                        "description": "Exact job type ID."
                                    },
                                    "daysFrom": {
                                        "description": "Relative start day or fixed start timestamp."
                                    },
                                    "daysTo": {
                                        "description": "Relative end day or fixed end timestamp."
                                    },
                                    "page": {
                                        "description": "One-based page number."
                                    },
                                    "pageSize": {
                                        "description": "Rows per page, up to 100."
                                    }
                                },
                                "additionalProperties": true,
                                "required": [
                                    "jobTypeID",
                                    "daysFrom",
                                    "daysTo"
                                ]
                            }
                        }
                    }
                },
                "security": [
                    {
                        "fmSessionCookie": [],
                        "fmCsrfHeader": []
                    },
                    {
                        "fmApiKeyId": [],
                        "fmApiKeySignature": [],
                        "fmApiKeyNow": []
                    }
                ]
            }
        },
        "/a/Stock_getDT": {
            "post": {
                "operationId": "Stock_getDT",
                "summary": "Return stock grid rows for DataTables.",
                "description": "Provides paginated stock records for the CRM stock table, including DataTables draw metadata and the packed row arrays expected by the UI.",
                "tags": [
                    "Stock"
                ],
                "responses": {
                    "200": {
                        "description": "Successful response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "draw": {
                                            "type": "integer"
                                        },
                                        "recordsTotal": {
                                            "type": "integer"
                                        },
                                        "recordsFiltered": {
                                            "type": "integer"
                                        },
                                        "data": {
                                            "type": "array",
                                            "items": {}
                                        }
                                    },
                                    "additionalProperties": true
                                },
                                "example": {
                                    "draw": 1,
                                    "recordsTotal": 1021,
                                    "recordsFiltered": 43,
                                    "data": [
                                        [
                                            1204,
                                            "Gas Valve",
                                            "GV-2",
                                            "Replacement gas valve",
                                            "",
                                            [
                                                33,
                                                "Main Supplier Ltd"
                                            ],
                                            27.5,
                                            45,
                                            "4000",
                                            20,
                                            14,
                                            2,
                                            "5",
                                            0,
                                            [
                                                "Heating",
                                                [
                                                    "Heating"
                                                ]
                                            ],
                                            [
                                                "Warehouse A"
                                            ],
                                            ""
                                        ]
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Error response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": "missing or invalid parameter: draw"
                                }
                            }
                        }
                    }
                },
                "x-fm-route": "Stock_getDT",
                "x-fm-source-file": "php/Stock/getDT.php",
                "x-fm-auth-modes": [
                    "session_cookie",
                    "api_key_signature",
                    "app_session_signature"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "draw": {
                                        "type": "integer",
                                        "description": "DataTables draw counter.",
                                        "example": 1
                                    },
                                    "length": {
                                        "type": "integer",
                                        "description": "Page size.",
                                        "example": 25
                                    },
                                    "order": {
                                        "type": "array",
                                        "description": "DataTables order array.",
                                        "example": "[{\"column\":\"1\",\"dir\":\"asc\"}]"
                                    },
                                    "start": {
                                        "type": "integer",
                                        "description": "Zero-based row offset.",
                                        "example": 0
                                    },
                                    "order.0.column": {
                                        "type": "integer",
                                        "description": "Column index to sort by.",
                                        "example": 1
                                    },
                                    "order.0.dir": {
                                        "type": "string",
                                        "description": "Sort direction.",
                                        "example": "asc"
                                    },
                                    "search.value": {
                                        "type": "string",
                                        "description": "Global search value."
                                    },
                                    "fId": {
                                        "type": "integer",
                                        "description": "Exact stock id filter."
                                    },
                                    "fName": {
                                        "type": "string",
                                        "description": "Name contains filter."
                                    },
                                    "fDescription": {
                                        "type": "string",
                                        "description": "Description contains filter."
                                    },
                                    "fCategory": {
                                        "type": "integer",
                                        "description": "Category id filter."
                                    },
                                    "fNotes": {
                                        "type": "string",
                                        "description": "Notes contains filter."
                                    },
                                    "fCode": {
                                        "type": "string",
                                        "description": "Stock code contains filter."
                                    },
                                    "fSupplier": {
                                        "type": "string",
                                        "description": "Supplier name contains filter."
                                    },
                                    "fIsTriggered": {
                                        "type": "integer",
                                        "description": "When truthy, limit to items at or below the trigger level."
                                    },
                                    "fLocation": {
                                        "type": "string",
                                        "description": "Location tag contains filter."
                                    },
                                    "fIsArchived": {
                                        "type": "integer",
                                        "description": "When truthy, return archived stock instead of active stock."
                                    }
                                },
                                "additionalProperties": true,
                                "required": [
                                    "draw",
                                    "length",
                                    "order",
                                    "start"
                                ]
                            },
                            "examples": {
                                "default": {
                                    "summary": "Load the first page of active stock sorted by name.",
                                    "value": {
                                        "draw": "1",
                                        "start": "0",
                                        "length": "25",
                                        "order.0.column": "1",
                                        "order.0.dir": "asc",
                                        "search.value": "",
                                        "fIsArchived": "0"
                                    }
                                }
                            }
                        }
                    }
                },
                "security": [
                    {
                        "fmSessionCookie": [],
                        "fmCsrfHeader": []
                    },
                    {
                        "fmApiKeyId": [],
                        "fmApiKeySignature": [],
                        "fmApiKeyNow": []
                    },
                    {
                        "fmAppCid": [],
                        "fmAppSid": [],
                        "fmAppMd5": [],
                        "fmAppJson": []
                    }
                ]
            }
        },
        "/a/TeamAccess_bootstrap": {
            "post": {
                "operationId": "TeamAccess_bootstrap",
                "summary": "Read current generic team-access configuration and scoped scheduling choices.",
                "description": "Source: `php/TeamAccess/bootstrap.php`",
                "tags": [
                    "TeamAccess"
                ],
                "responses": {
                    "200": {
                        "description": "Successful response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "additionalProperties": true
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Error response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": "request failed"
                                }
                            }
                        }
                    }
                },
                "x-fm-route": "TeamAccess_bootstrap",
                "x-fm-source-file": "php/TeamAccess/bootstrap.php",
                "x-fm-auth-modes": [
                    "session_cookie",
                    "api_key_signature",
                    "app_session_signature"
                ],
                "requestBody": {
                    "required": false,
                    "content": {
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "table": {
                                        "type": "string"
                                    },
                                    "id": {
                                        "type": "string"
                                    },
                                    "contract_id": {
                                        "type": "string"
                                    }
                                },
                                "additionalProperties": true
                            }
                        }
                    }
                },
                "security": [
                    {
                        "fmSessionCookie": [],
                        "fmCsrfHeader": []
                    },
                    {
                        "fmApiKeyId": [],
                        "fmApiKeySignature": [],
                        "fmApiKeyNow": []
                    },
                    {
                        "fmAppCid": [],
                        "fmAppSid": [],
                        "fmAppMd5": [],
                        "fmAppJson": []
                    }
                ]
            }
        },
        "/a/TeamAccess_saveLink": {
            "post": {
                "operationId": "TeamAccess_saveLink",
                "summary": "Set a department parent, user Parent Manager, or Contract department.",
                "description": "Source: `php/TeamAccess/saveLink.php`",
                "tags": [
                    "TeamAccess"
                ],
                "responses": {
                    "200": {
                        "description": "Successful response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "additionalProperties": true
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Error response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": "request failed"
                                }
                            }
                        }
                    }
                },
                "x-fm-route": "TeamAccess_saveLink",
                "x-fm-source-file": "php/TeamAccess/saveLink.php",
                "x-fm-auth-modes": [
                    "session_cookie",
                    "api_key_signature",
                    "app_session_signature"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "kind": {
                                        "description": "department, user or contract"
                                    },
                                    "id": {
                                        "type": "string"
                                    },
                                    "value": {
                                        "type": "string"
                                    }
                                },
                                "additionalProperties": true,
                                "required": [
                                    "kind",
                                    "id",
                                    "value"
                                ]
                            }
                        }
                    }
                },
                "security": [
                    {
                        "fmSessionCookie": [],
                        "fmCsrfHeader": []
                    },
                    {
                        "fmApiKeyId": [],
                        "fmApiKeySignature": [],
                        "fmApiKeyNow": []
                    },
                    {
                        "fmAppCid": [],
                        "fmAppSid": [],
                        "fmAppMd5": [],
                        "fmAppJson": []
                    }
                ]
            }
        },
        "/a/Timesheet_history": {
            "post": {
                "operationId": "Timesheet_history",
                "summary": "Read retained Timesheet revisions",
                "description": "Requires the Timesheets tenant feature and Clockins View permission. Return and resolution require Clockins Edit. Submission is restricted to the authenticated employee. Dates use the account timezone.",
                "tags": [
                    "Timesheet"
                ],
                "responses": {
                    "200": {
                        "description": "Successful response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "additionalProperties": true
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Error response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": "request failed"
                                }
                            }
                        }
                    }
                },
                "x-fm-route": "Timesheet_history",
                "x-fm-source-file": "php/Timesheet/history.php",
                "x-fm-auth-modes": [
                    "session_cookie",
                    "api_key_signature"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "data": {
                                        "type": "string",
                                        "description": "JSON operation parameters; see Timesheet/README.md for fields and lifecycle."
                                    }
                                },
                                "additionalProperties": true,
                                "required": [
                                    "data"
                                ]
                            }
                        }
                    }
                },
                "security": [
                    {
                        "fmSessionCookie": [],
                        "fmCsrfHeader": []
                    },
                    {
                        "fmApiKeyId": [],
                        "fmApiKeySignature": [],
                        "fmApiKeyNow": []
                    }
                ]
            }
        },
        "/a/Timesheet_resolve": {
            "post": {
                "operationId": "Timesheet_resolve",
                "summary": "Record resolution of a retained sync conflict",
                "description": "Requires the Timesheets tenant feature and Clockins View permission. Return and resolution require Clockins Edit. Submission is restricted to the authenticated employee. Dates use the account timezone.",
                "tags": [
                    "Timesheet"
                ],
                "responses": {
                    "200": {
                        "description": "Successful response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "additionalProperties": true
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Error response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": "request failed"
                                }
                            }
                        }
                    }
                },
                "x-fm-route": "Timesheet_resolve",
                "x-fm-source-file": "php/Timesheet/resolve.php",
                "x-fm-auth-modes": [
                    "session_cookie",
                    "api_key_signature"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "data": {
                                        "type": "string",
                                        "description": "JSON operation parameters; see Timesheet/README.md for fields and lifecycle."
                                    }
                                },
                                "additionalProperties": true,
                                "required": [
                                    "data"
                                ]
                            }
                        }
                    }
                },
                "security": [
                    {
                        "fmSessionCookie": [],
                        "fmCsrfHeader": []
                    },
                    {
                        "fmApiKeyId": [],
                        "fmApiKeySignature": [],
                        "fmApiKeyNow": []
                    }
                ]
            }
        },
        "/a/Timesheet_returnPeriod": {
            "post": {
                "operationId": "Timesheet_returnPeriod",
                "summary": "Return a submitted Timesheet for correction",
                "description": "Requires the Timesheets tenant feature and Clockins View permission. Return and resolution require Clockins Edit. Submission is restricted to the authenticated employee. Dates use the account timezone.",
                "tags": [
                    "Timesheet"
                ],
                "responses": {
                    "200": {
                        "description": "Successful response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "additionalProperties": true
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Error response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": "request failed"
                                }
                            }
                        }
                    }
                },
                "x-fm-route": "Timesheet_returnPeriod",
                "x-fm-source-file": "php/Timesheet/returnPeriod.php",
                "x-fm-auth-modes": [
                    "session_cookie",
                    "api_key_signature"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "data": {
                                        "type": "string",
                                        "description": "JSON operation parameters; see Timesheet/README.md for fields and lifecycle."
                                    }
                                },
                                "additionalProperties": true,
                                "required": [
                                    "data"
                                ]
                            }
                        }
                    }
                },
                "security": [
                    {
                        "fmSessionCookie": [],
                        "fmCsrfHeader": []
                    },
                    {
                        "fmApiKeyId": [],
                        "fmApiKeySignature": [],
                        "fmApiKeyNow": []
                    }
                ]
            }
        },
        "/a/Timesheet_review": {
            "post": {
                "operationId": "Timesheet_review",
                "summary": "Review an employee Timesheet period",
                "description": "Requires the Timesheets tenant feature and Clockins View permission. Return and resolution require Clockins Edit. Submission is restricted to the authenticated employee. Dates use the account timezone.",
                "tags": [
                    "Timesheet"
                ],
                "responses": {
                    "200": {
                        "description": "Successful response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "additionalProperties": true
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Error response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": "request failed"
                                }
                            }
                        }
                    }
                },
                "x-fm-route": "Timesheet_review",
                "x-fm-source-file": "php/Timesheet/review.php",
                "x-fm-auth-modes": [
                    "session_cookie",
                    "api_key_signature"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "data": {
                                        "type": "string",
                                        "description": "JSON operation parameters; see Timesheet/README.md for fields and lifecycle."
                                    }
                                },
                                "additionalProperties": true,
                                "required": [
                                    "data"
                                ]
                            }
                        }
                    }
                },
                "security": [
                    {
                        "fmSessionCookie": [],
                        "fmCsrfHeader": []
                    },
                    {
                        "fmApiKeyId": [],
                        "fmApiKeySignature": [],
                        "fmApiKeyNow": []
                    }
                ]
            }
        },
        "/a/Timesheet_submit": {
            "post": {
                "operationId": "Timesheet_submit",
                "summary": "Submit your Timesheet period",
                "description": "Requires the Timesheets tenant feature and Clockins View permission. Return and resolution require Clockins Edit. Submission is restricted to the authenticated employee. Dates use the account timezone.",
                "tags": [
                    "Timesheet"
                ],
                "responses": {
                    "200": {
                        "description": "Successful response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "additionalProperties": true
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Error response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": "request failed"
                                }
                            }
                        }
                    }
                },
                "x-fm-route": "Timesheet_submit",
                "x-fm-source-file": "php/Timesheet/submit.php",
                "x-fm-auth-modes": [
                    "session_cookie",
                    "api_key_signature"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "data": {
                                        "type": "string",
                                        "description": "JSON operation parameters; see Timesheet/README.md for fields and lifecycle."
                                    }
                                },
                                "additionalProperties": true,
                                "required": [
                                    "data"
                                ]
                            }
                        }
                    }
                },
                "security": [
                    {
                        "fmSessionCookie": [],
                        "fmCsrfHeader": []
                    },
                    {
                        "fmApiKeyId": [],
                        "fmApiKeySignature": [],
                        "fmApiKeyNow": []
                    }
                ]
            }
        },
        "/a/Training_cancelRegistration": {
            "post": {
                "operationId": "Training_cancelRegistration",
                "summary": "Cancel the authenticated user's provider booking.",
                "description": "Cancels a future WebinarGeek subscription; preserves local records and viewing history. An uncertain provider reply leaves the booking unchanged until reconciliation.",
                "tags": [
                    "Training"
                ],
                "responses": {
                    "200": {
                        "description": "Successful response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "additionalProperties": true
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Error response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": "request failed"
                                }
                            }
                        }
                    }
                },
                "x-fm-route": "Training_cancelRegistration",
                "x-fm-source-file": "php/Training/cancelRegistration.php",
                "x-fm-auth-modes": [
                    "session_cookie",
                    "api_key_signature",
                    "app_session_signature"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "session_id": {
                                        "type": "integer"
                                    }
                                },
                                "additionalProperties": true,
                                "required": [
                                    "session_id"
                                ]
                            }
                        }
                    }
                },
                "security": [
                    {
                        "fmSessionCookie": [],
                        "fmCsrfHeader": []
                    },
                    {
                        "fmApiKeyId": [],
                        "fmApiKeySignature": [],
                        "fmApiKeyNow": []
                    },
                    {
                        "fmAppCid": [],
                        "fmAppSid": [],
                        "fmAppMd5": [],
                        "fmAppJson": []
                    }
                ]
            }
        },
        "/a/Training_get": {
            "post": {
                "operationId": "Training_get",
                "summary": "Get one customer-visible Training session.",
                "description": "Returns a published webinar session with registration, interest, live-join, and recording actions filtered for the authenticated user and current time.",
                "tags": [
                    "Training"
                ],
                "responses": {
                    "200": {
                        "description": "Successful response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "additionalProperties": true
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Error response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": "request failed"
                                }
                            }
                        }
                    }
                },
                "x-fm-route": "Training_get",
                "x-fm-source-file": "php/Training/get.php",
                "x-fm-auth-modes": [
                    "session_cookie",
                    "api_key_signature",
                    "app_session_signature"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "session_id": {
                                        "type": "integer"
                                    }
                                },
                                "additionalProperties": true,
                                "required": [
                                    "session_id"
                                ]
                            }
                        }
                    }
                },
                "security": [
                    {
                        "fmSessionCookie": [],
                        "fmCsrfHeader": []
                    },
                    {
                        "fmApiKeyId": [],
                        "fmApiKeySignature": [],
                        "fmApiKeyNow": []
                    },
                    {
                        "fmAppCid": [],
                        "fmAppSid": [],
                        "fmAppMd5": [],
                        "fmAppJson": []
                    }
                ]
            }
        },
        "/a/Training_interestUpdate": {
            "post": {
                "operationId": "Training_interestUpdate",
                "summary": "Record or withdraw interest in a Training session.",
                "description": "Uses the authenticated tenant and user identity. Recording interest is separate from completion of registration with the external webinar provider.",
                "tags": [
                    "Training"
                ],
                "responses": {
                    "200": {
                        "description": "Successful response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "additionalProperties": true
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Error response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": "request failed"
                                }
                            }
                        }
                    }
                },
                "x-fm-route": "Training_interestUpdate",
                "x-fm-source-file": "php/Training/interestUpdate.php",
                "x-fm-auth-modes": [
                    "session_cookie",
                    "api_key_signature",
                    "app_session_signature"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "session_id": {
                                        "type": "integer"
                                    },
                                    "interested": {
                                        "type": "integer"
                                    }
                                },
                                "additionalProperties": true,
                                "required": [
                                    "session_id",
                                    "interested"
                                ]
                            }
                        }
                    }
                },
                "security": [
                    {
                        "fmSessionCookie": [],
                        "fmCsrfHeader": []
                    },
                    {
                        "fmApiKeyId": [],
                        "fmApiKeySignature": [],
                        "fmApiKeyNow": []
                    },
                    {
                        "fmAppCid": [],
                        "fmAppSid": [],
                        "fmAppMd5": [],
                        "fmAppJson": []
                    }
                ]
            }
        },
        "/a/Training_list": {
            "post": {
                "operationId": "Training_list",
                "summary": "List customer-visible Training sessions.",
                "description": "Authenticated CRM users can list upcoming sessions, a bounded calendar range, or explicitly published on-demand recordings. Shared live join URLs remain hidden until their protected window.",
                "tags": [
                    "Training"
                ],
                "responses": {
                    "200": {
                        "description": "Successful response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "additionalProperties": true
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Error response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": "request failed"
                                }
                            }
                        }
                    }
                },
                "x-fm-route": "Training_list",
                "x-fm-source-file": "php/Training/list.php",
                "x-fm-auth-modes": [
                    "session_cookie",
                    "api_key_signature",
                    "app_session_signature"
                ],
                "requestBody": {
                    "required": false,
                    "content": {
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "view": {
                                        "type": "string"
                                    },
                                    "category": {
                                        "type": "string"
                                    },
                                    "from": {
                                        "type": "integer"
                                    },
                                    "to": {
                                        "type": "integer"
                                    },
                                    "sort": {
                                        "type": "string",
                                        "description": "Recording order: az, za or newest."
                                    },
                                    "page": {
                                        "type": "integer",
                                        "description": "Zero-based recording page."
                                    },
                                    "page_length": {
                                        "type": "integer",
                                        "description": "Recording rows per page, capped at 200."
                                    }
                                },
                                "additionalProperties": true
                            }
                        }
                    }
                },
                "security": [
                    {
                        "fmSessionCookie": [],
                        "fmCsrfHeader": []
                    },
                    {
                        "fmApiKeyId": [],
                        "fmApiKeySignature": [],
                        "fmApiKeyNow": []
                    },
                    {
                        "fmAppCid": [],
                        "fmAppSid": [],
                        "fmAppMd5": [],
                        "fmAppJson": []
                    }
                ]
            }
        },
        "/a/Training_mySessions": {
            "post": {
                "operationId": "Training_mySessions",
                "summary": "List the current user's Training interests or provider bookings.",
                "description": "By default returns active interests for upcoming sessions and the previous 90 days. With booked=1 returns upcoming confirmed or pending WebinarGeek subscriptions, scoped to the authenticated user.",
                "tags": [
                    "Training"
                ],
                "responses": {
                    "200": {
                        "description": "Successful response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "additionalProperties": true
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Error response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": "request failed"
                                }
                            }
                        }
                    }
                },
                "x-fm-route": "Training_mySessions",
                "x-fm-source-file": "php/Training/mySessions.php",
                "x-fm-auth-modes": [
                    "session_cookie",
                    "api_key_signature",
                    "app_session_signature"
                ],
                "requestBody": {
                    "required": false,
                    "content": {
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "booked": {
                                        "type": "boolean",
                                        "description": "List provider confirmed/pending bookings instead of legacy interests."
                                    }
                                },
                                "additionalProperties": true
                            }
                        }
                    }
                },
                "security": [
                    {
                        "fmSessionCookie": [],
                        "fmCsrfHeader": []
                    },
                    {
                        "fmApiKeyId": [],
                        "fmApiKeySignature": [],
                        "fmApiKeyNow": []
                    },
                    {
                        "fmAppCid": [],
                        "fmAppSid": [],
                        "fmAppMd5": [],
                        "fmAppJson": []
                    }
                ]
            }
        },
        "/a/Training_progress": {
            "post": {
                "operationId": "Training_progress",
                "summary": "Read authenticated user's recording progress.",
                "description": "Synchronises WebinarGeek statistics with a five-minute cache. Completion requires 90 percent of known recording duration; live attendance does not count. Percentages use currently published recordings.",
                "tags": [
                    "Training"
                ],
                "responses": {
                    "200": {
                        "description": "Successful response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "additionalProperties": true
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Error response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": "request failed"
                                }
                            }
                        }
                    }
                },
                "x-fm-route": "Training_progress",
                "x-fm-source-file": "php/Training/progress.php",
                "x-fm-auth-modes": [
                    "session_cookie",
                    "api_key_signature",
                    "app_session_signature"
                ],
                "security": [
                    {
                        "fmSessionCookie": [],
                        "fmCsrfHeader": []
                    },
                    {
                        "fmApiKeyId": [],
                        "fmApiKeySignature": [],
                        "fmApiKeyNow": []
                    },
                    {
                        "fmAppCid": [],
                        "fmAppSid": [],
                        "fmAppMd5": [],
                        "fmAppJson": []
                    }
                ]
            }
        },
        "/a/Training_register": {
            "post": {
                "operationId": "Training_register",
                "summary": "Register the authenticated user with WebinarGeek.",
                "description": "Without submit, returns required fields and consent statements. With submit, creates or reconciles a provider registration. Only verified provider evidence confirms bookings.",
                "tags": [
                    "Training"
                ],
                "responses": {
                    "200": {
                        "description": "Successful response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "additionalProperties": true
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Error response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": "request failed"
                                }
                            }
                        }
                    }
                },
                "x-fm-route": "Training_register",
                "x-fm-source-file": "php/Training/register.php",
                "x-fm-auth-modes": [],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "session_id": {
                                        "type": "integer"
                                    },
                                    "submit": {
                                        "type": "integer"
                                    },
                                    "values": {
                                        "type": "string",
                                        "description": "JSON field values"
                                    },
                                    "consents": {
                                        "type": "string",
                                        "description": "JSON explicitly accepted consent labels"
                                    }
                                },
                                "additionalProperties": true,
                                "required": [
                                    "session_id"
                                ]
                            }
                        }
                    }
                },
                "security": []
            }
        },
        "/a/Training_suggestTopic": {
            "post": {
                "operationId": "Training_suggestTopic",
                "summary": "Suggest a future Training topic.",
                "description": "Creates and sends a Training suggestion from the authenticated CRM user without requesting permission to access or edit the account.",
                "tags": [
                    "Training"
                ],
                "responses": {
                    "200": {
                        "description": "Successful response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "additionalProperties": true
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Error response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": "request failed"
                                }
                            }
                        }
                    }
                },
                "x-fm-route": "Training_suggestTopic",
                "x-fm-source-file": "php/Training/suggestTopic.php",
                "x-fm-auth-modes": [
                    "session_cookie",
                    "api_key_signature",
                    "app_session_signature"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "subject": {
                                        "type": "string"
                                    },
                                    "description": {
                                        "type": "string"
                                    }
                                },
                                "additionalProperties": true,
                                "required": [
                                    "subject",
                                    "description"
                                ]
                            }
                        }
                    }
                },
                "security": [
                    {
                        "fmSessionCookie": [],
                        "fmCsrfHeader": []
                    },
                    {
                        "fmApiKeyId": [],
                        "fmApiKeySignature": [],
                        "fmApiKeyNow": []
                    },
                    {
                        "fmAppCid": [],
                        "fmAppSid": [],
                        "fmAppMd5": [],
                        "fmAppJson": []
                    }
                ]
            }
        },
        "/a/Training_videosTable": {
            "post": {
                "operationId": "Training_videosTable",
                "summary": "Read the published recording catalogue through the CRM2 table interface.",
                "description": "Source: `php/Training/videosTable.php`",
                "tags": [
                    "Training"
                ],
                "responses": {
                    "200": {
                        "description": "Successful response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "additionalProperties": true
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Error response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": "request failed"
                                }
                            }
                        }
                    }
                },
                "x-fm-route": "Training_videosTable",
                "x-fm-source-file": "php/Training/videosTable.php",
                "x-fm-auth-modes": [],
                "requestBody": {
                    "required": false,
                    "content": {
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "category": {
                                        "type": "string"
                                    },
                                    "sort": {
                                        "type": "string"
                                    },
                                    "start": {
                                        "type": "integer"
                                    },
                                    "length": {
                                        "type": "integer"
                                    }
                                },
                                "additionalProperties": true
                            }
                        }
                    }
                },
                "security": []
            }
        },
        "/a/Training_watch": {
            "post": {
                "operationId": "Training_watch",
                "summary": "Get personal WebinarGeek recording access.",
                "description": "Collects required registration fields and consent before creating or reconciling personal access. Opening a watch link never records completion.",
                "tags": [
                    "Training"
                ],
                "responses": {
                    "200": {
                        "description": "Successful response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "additionalProperties": true
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Error response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": "request failed"
                                }
                            }
                        }
                    }
                },
                "x-fm-route": "Training_watch",
                "x-fm-source-file": "php/Training/watch.php",
                "x-fm-auth-modes": [],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "session_id": {
                                        "type": "integer"
                                    },
                                    "submit": {
                                        "type": "integer"
                                    },
                                    "values": {
                                        "type": "string"
                                    },
                                    "consents": {
                                        "type": "string"
                                    }
                                },
                                "additionalProperties": true,
                                "required": [
                                    "session_id"
                                ]
                            }
                        }
                    }
                },
                "security": []
            }
        },
        "/a/UserClockin_closeEarlierOpenSessions": {
            "post": {
                "operationId": "UserClockin_closeEarlierOpenSessions",
                "summary": "Close earlier open clock-in sessions before clocking out or clocking in again.",
                "description": "Calculates each earlier session's effective workday end from client/user work shifts and approved Availability rules. Pass the current session id when clocking out, or the proposed clock-in timestamp before creating a new session. The operation makes no changes if any proposed clock-out would overlap another session or the proposed clock-in.",
                "tags": [
                    "UserClockin"
                ],
                "responses": {
                    "200": {
                        "description": "Successful response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "additionalProperties": true
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Error response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": "request failed"
                                }
                            }
                        }
                    }
                },
                "x-fm-route": "UserClockin_closeEarlierOpenSessions",
                "x-fm-source-file": "php/UserClockin/closeEarlierOpenSessions.php",
                "x-fm-auth-modes": [
                    "session_cookie",
                    "api_key_signature",
                    "app_session_signature"
                ],
                "requestBody": {
                    "required": false,
                    "content": {
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "id": {
                                        "type": "integer",
                                        "description": "Current open clock-in session id. Takes precedence over clockin."
                                    },
                                    "clockin": {
                                        "type": "integer",
                                        "description": "Proposed clock-in timestamp when no current session exists."
                                    }
                                },
                                "additionalProperties": true
                            }
                        }
                    }
                },
                "security": [
                    {
                        "fmSessionCookie": [],
                        "fmCsrfHeader": []
                    },
                    {
                        "fmApiKeyId": [],
                        "fmApiKeySignature": [],
                        "fmApiKeyNow": []
                    },
                    {
                        "fmAppCid": [],
                        "fmAppSid": [],
                        "fmAppMd5": [],
                        "fmAppJson": []
                    }
                ]
            }
        },
        "/a/UserClockins_calendar": {
            "post": {
                "operationId": "UserClockins_calendar",
                "summary": "Return daily clock-in totals for a calendar date range.",
                "description": "Returns one row per date that has clock-in records, counting distinct users with a recorded clock-in and the number of flagged clock-in rows.",
                "tags": [
                    "UserClockins"
                ],
                "responses": {
                    "200": {
                        "description": "Successful response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "additionalProperties": true
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Error response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": "request failed"
                                }
                            }
                        }
                    }
                },
                "x-fm-route": "UserClockins_calendar",
                "x-fm-source-file": "php/UserClockins/calendar.php",
                "x-fm-auth-modes": [
                    "session_cookie",
                    "api_key_signature",
                    "app_session_signature"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "from": {
                                        "type": "string",
                                        "description": "Inclusive start date in YYYY-MM-DD format."
                                    },
                                    "to": {
                                        "type": "string",
                                        "description": "Inclusive end date in YYYY-MM-DD format."
                                    }
                                },
                                "additionalProperties": true,
                                "required": [
                                    "from",
                                    "to"
                                ]
                            }
                        }
                    }
                },
                "security": [
                    {
                        "fmSessionCookie": [],
                        "fmCsrfHeader": []
                    },
                    {
                        "fmApiKeyId": [],
                        "fmApiKeySignature": [],
                        "fmApiKeyNow": []
                    },
                    {
                        "fmAppCid": [],
                        "fmAppSid": [],
                        "fmAppMd5": [],
                        "fmAppJson": []
                    }
                ]
            }
        },
        "/a/Util_findAddressesByPostcode": {
            "post": {
                "operationId": "Util_findAddressesByPostcode",
                "summary": "Find customer address candidates from a postcode or Eircode.",
                "description": "Uses the existing server-side geocoding providers to return best-effort address candidates. Results are cached server-side and are intended for user-triggered customer address completion, not autocomplete.",
                "tags": [
                    "Util"
                ],
                "responses": {
                    "200": {
                        "description": "Successful response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "array",
                                    "items": {}
                                },
                                "example": [
                                    {
                                        "label": "15 Latlorcan Glen, Monaghan, Ireland",
                                        "street_address1": "15 Latlorcan Glen",
                                        "street_address2": "",
                                        "town": "Monaghan",
                                        "city": "",
                                        "county": "County Monaghan",
                                        "state": "",
                                        "country": "IRL",
                                        "postcode": "H18 E023",
                                        "latitude": "54.243709",
                                        "longitude": "-6.9487759",
                                        "source": "nominatim"
                                    }
                                ]
                            }
                        }
                    },
                    "400": {
                        "description": "Error response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                },
                                "example": {
                                    "error": "missing or invalid parameter: postcode"
                                }
                            }
                        }
                    }
                },
                "x-fm-route": "Util_findAddressesByPostcode",
                "x-fm-source-file": "php/Util/findAddressesByPostcode.php",
                "x-fm-auth-modes": [
                    "session_cookie",
                    "api_key_signature",
                    "app_session_signature"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "postcode": {
                                        "type": "string",
                                        "description": "Postcode, Eircode, or ZIP code to look up.",
                                        "example": "H18 E023"
                                    },
                                    "country": {
                                        "type": "string",
                                        "description": "Customer country as ISO alpha-3, ISO alpha-2, or country name. Defaults through the customer country geocode setting.",
                                        "example": "IRL"
                                    },
                                    "limit": {
                                        "type": "integer",
                                        "description": "Maximum number of candidates to return. Defaults to 5 and is capped at 10.",
                                        "example": "5"
                                    }
                                },
                                "additionalProperties": true,
                                "required": [
                                    "postcode"
                                ]
                            },
                            "examples": {
                                "default": {
                                    "summary": "Find address candidates for an Eircode.",
                                    "value": {
                                        "postcode": "H18 E023",
                                        "country": "IRL"
                                    }
                                }
                            }
                        }
                    }
                },
                "security": [
                    {
                        "fmSessionCookie": [],
                        "fmCsrfHeader": []
                    },
                    {
                        "fmApiKeyId": [],
                        "fmApiKeySignature": [],
                        "fmApiKeyNow": []
                    },
                    {
                        "fmAppCid": [],
                        "fmAppSid": [],
                        "fmAppMd5": [],
                        "fmAppJson": []
                    }
                ]
            }
        }
    },
    "components": {
        "schemas": {
            "Error": {
                "type": "object",
                "properties": {
                    "error": {
                        "type": "string",
                        "description": "Human-readable error message."
                    }
                },
                "required": [
                    "error"
                ],
                "additionalProperties": true,
                "example": {
                    "error": "missing parameter: id"
                }
            }
        },
        "securitySchemes": {
            "fmSessionCookie": {
                "type": "apiKey",
                "in": "cookie",
                "name": "PHPSESSID",
                "description": "Browser/session authentication. Most authenticated calls also require `X-FMCSRF`."
            },
            "fmCsrfHeader": {
                "type": "apiKey",
                "in": "header",
                "name": "X-FMCSRF",
                "description": "CSRF token required for most authenticated browser requests."
            },
            "fmApiKeyId": {
                "type": "apiKey",
                "in": "query",
                "name": "_api_id",
                "description": "API key id for signed requests."
            },
            "fmApiKeySignature": {
                "type": "apiKey",
                "in": "query",
                "name": "_api_md5",
                "description": "MD5 signature of the request payload and API key secret."
            },
            "fmApiKeyNow": {
                "type": "apiKey",
                "in": "query",
                "name": "_api_now",
                "description": "Request timestamp included in the signature flow."
            },
            "fmAppCid": {
                "type": "apiKey",
                "in": "query",
                "name": "_cid",
                "description": "Tenant id for app-signed requests."
            },
            "fmAppSid": {
                "type": "apiKey",
                "in": "query",
                "name": "_sid",
                "description": "Login session id for app-signed requests."
            },
            "fmAppMd5": {
                "type": "apiKey",
                "in": "query",
                "name": "_md5",
                "description": "MD5 signature for the JSON request payload."
            },
            "fmAppJson": {
                "type": "apiKey",
                "in": "query",
                "name": "_json",
                "description": "JSON request payload for app-signed requests."
            }
        }
    },
    "x-generatedAt": "2026-11-03T13:25:41Z",
    "x-routeConvention": "/a/Object_action -> php/Object/action.php -> Object_action()",
    "x-undocumentedRouteCount": 2082
}
