{
  "openapi": "3.1.0",
  "info": {
    "title": "Emplorea HR API",
    "version": "1.3.0",
    "description": "Emplorea is an HR-as-a-Service platform for businesses of every size in Australia, New Zealand and the United Kingdom. This API gives AI agents and integrations programmatic access to the live platform: company details; employee management (update, terminate and invite - creating an employee is web-only); leave management (request, approve, decline, cancel, balances, leave types and public holidays; sensitive family-violence leave is never returned); documents with in-house e-sign; the compliance engine (items, results, policies, training and incidents, including WHS); managed payroll (reads plus set the pay schedule); the performance area (probation reviews, performance reviews, goals and 1:1s); recruitment (pipeline, roles, application stages and offers - candidate personal details are never returned); offboarding (plans and tasks); permissions (presets and overrides, read-only); advisor-conversation metadata (message content is never returned); company branding; engagement (surveys and recognition, with aggregate, k-anonymous results only); wellbeing (aggregate team and company scores and the EAP directory - individual data is web-only); the Learn training library (courses, assignments, completions and verifiable certificates; quiz answer keys are never returned); and webhooks. Some operations are intentionally web-only for safety (creating employees, managed payroll processing, compliance award and rule ingestion, career-affecting performance writes, terminations, and anonymity- or individual-sensitive engagement and wellbeing writes) and are not on this surface by construction.\n\nFOR AI AGENTS: authenticate every request with an API key as a Bearer token (Authorization: Bearer emp_live_...). Keys are created by a company admin in Settings -> Integrations and are scoped (read / write / admin / webhooks). Start with GET /company to understand the company context, then GET /employees and GET /leave-types before creating resources. Money is always integer cents. Dates are ISO YYYY-MM-DD. List endpoints paginate with ?page and ?limit and return a meta object. Errors always have the shape {error: {code, message, field?}}. Rate limit: 100 requests/minute per key, reported on every response in X-RateLimit-* headers.\n\nMore: https://app.emplorea.com/docs and /llms.txt. MCP server: https://app.emplorea.com/mcp (manifest at /.well-known/mcp.json).",
    "contact": {
      "name": "Emplorea support",
      "email": "hr@emplorea.com"
    }
  },
  "servers": [
    {
      "url": "https://app.emplorea.com/api/v1"
    }
  ],
  "security": [
    {
      "BearerAuth": []
    }
  ],
  "components": {
    "securitySchemes": {
      "BearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "API key from Settings -> Integrations, e.g. emp_live_..."
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "properties": {
          "error": {
            "type": "object",
            "properties": {
              "code": {
                "type": "string",
                "enum": [
                  "UNAUTHORISED",
                  "FORBIDDEN",
                  "NOT_FOUND",
                  "VALIDATION_ERROR",
                  "CONFLICT",
                  "RATE_LIMITED",
                  "NOT_IMPLEMENTED",
                  "INTERNAL_ERROR"
                ]
              },
              "message": {
                "type": "string"
              },
              "field": {
                "type": "string"
              }
            },
            "required": [
              "code",
              "message"
            ]
          }
        },
        "required": [
          "error"
        ]
      },
      "ListMeta": {
        "type": "object",
        "properties": {
          "total": {
            "type": "integer"
          },
          "page": {
            "type": "integer"
          },
          "limit": {
            "type": "integer"
          },
          "has_more": {
            "type": "boolean"
          }
        },
        "required": [
          "total",
          "page",
          "limit",
          "has_more"
        ]
      },
      "Employee": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "first_name": {
            "type": "string"
          },
          "last_name": {
            "type": "string"
          },
          "email": {
            "type": "string",
            "format": "email"
          },
          "job_title": {
            "type": [
              "string",
              "null"
            ]
          },
          "department": {
            "type": [
              "string",
              "null"
            ]
          },
          "employment_type": {
            "type": "string",
            "enum": [
              "full_time",
              "part_time",
              "casual",
              "contractor"
            ]
          },
          "start_date": {
            "type": "string",
            "format": "date"
          },
          "base_salary": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Integer cents - 9200000 = $92,000."
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "on_leave",
              "probation",
              "terminated"
            ]
          },
          "probation_end_date": {
            "type": [
              "string",
              "null"
            ],
            "format": "date"
          },
          "manager_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "jurisdiction": {
            "type": "string",
            "enum": [
              "AU",
              "NZ",
              "UK"
            ]
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "EmployeeCreate": {
        "type": "object",
        "required": [
          "first_name",
          "last_name",
          "email",
          "employment_type",
          "start_date",
          "jurisdiction",
          "role"
        ],
        "properties": {
          "first_name": {
            "type": "string"
          },
          "last_name": {
            "type": "string"
          },
          "email": {
            "type": "string",
            "format": "email"
          },
          "job_title": {
            "type": "string"
          },
          "department": {
            "type": "string"
          },
          "employment_type": {
            "type": "string",
            "enum": [
              "full_time",
              "part_time",
              "casual",
              "contractor"
            ]
          },
          "start_date": {
            "type": "string",
            "format": "date"
          },
          "jurisdiction": {
            "type": "string",
            "enum": [
              "AU",
              "NZ",
              "UK"
            ]
          },
          "base_salary": {
            "type": "integer",
            "description": "Integer cents."
          },
          "manager_id": {
            "type": "string",
            "format": "uuid"
          },
          "role": {
            "type": "string",
            "enum": [
              "employee",
              "manager",
              "company_admin"
            ],
            "description": "Portal role. Takes effect when the person is invited via POST /employees/{id}/invite."
          }
        }
      },
      "LeaveRequest": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "employeeId": {
            "type": "string",
            "format": "uuid"
          },
          "employeeName": {
            "type": "string"
          },
          "typeId": {
            "type": "string",
            "format": "uuid"
          },
          "typeName": {
            "type": "string"
          },
          "startDate": {
            "type": "string",
            "format": "date"
          },
          "endDate": {
            "type": "string",
            "format": "date"
          },
          "days": {
            "type": "number",
            "description": "Working days - weekends and public holidays excluded; half days are 0.5."
          },
          "halfDay": {
            "type": "boolean"
          },
          "halfDayPeriod": {
            "type": [
              "string",
              "null"
            ]
          },
          "notes": {
            "type": [
              "string",
              "null"
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "approved",
              "declined",
              "cancelled",
              "auto_approved"
            ]
          },
          "declineReason": {
            "type": [
              "string",
              "null"
            ]
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "LeaveCreate": {
        "type": "object",
        "required": [
          "employee_id",
          "leave_type_id",
          "start_date",
          "end_date"
        ],
        "properties": {
          "employee_id": {
            "type": "string",
            "format": "uuid"
          },
          "leave_type_id": {
            "type": "string",
            "format": "uuid",
            "description": "From GET /leave-types."
          },
          "start_date": {
            "type": "string",
            "format": "date"
          },
          "end_date": {
            "type": "string",
            "format": "date"
          },
          "half_day": {
            "type": "boolean",
            "default": false
          },
          "half_day_period": {
            "type": "string",
            "enum": [
              "morning",
              "afternoon"
            ]
          },
          "notes": {
            "type": "string",
            "maxLength": 500
          }
        }
      },
      "LeaveBalance": {
        "type": "object",
        "properties": {
          "employee_id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string"
          },
          "annual_available": {
            "type": "number"
          },
          "sick_available": {
            "type": "number"
          },
          "pending_days": {
            "type": "number"
          },
          "taken_days": {
            "type": "number"
          }
        }
      },
      "LeaveType": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string"
          },
          "is_paid": {
            "type": "boolean"
          },
          "requires_approval": {
            "type": "boolean",
            "description": "When false, requests of this type are approved automatically on submission."
          },
          "allow_half_days": {
            "type": "boolean"
          },
          "min_notice_days": {
            "type": "integer"
          },
          "max_days_per_year": {
            "type": [
              "integer",
              "null"
            ]
          },
          "is_default": {
            "type": "boolean"
          }
        }
      },
      "PublicHoliday": {
        "type": "object",
        "properties": {
          "date": {
            "type": "string",
            "format": "date"
          },
          "name": {
            "type": "string"
          }
        }
      },
      "Webhook": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "url": {
            "type": "string",
            "format": "uri"
          },
          "events": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "is_active": {
            "type": "boolean"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "secret": {
            "type": "string",
            "description": "Returned ONCE on creation - used to verify the X-Emplorea-Signature header (HMAC-SHA256, format sha256=<hex>)."
          }
        }
      },
      "Document": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "employee_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "type": {
            "type": "string",
            "enum": [
              "contract",
              "payslip",
              "policy",
              "certificate",
              "other"
            ]
          },
          "title": {
            "type": "string"
          },
          "file_size": {
            "type": "integer",
            "description": "Bytes."
          },
          "mime_type": {
            "type": "string"
          },
          "signed": {
            "type": "boolean"
          },
          "signed_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "awaiting_signature": {
            "type": "boolean",
            "description": "True while an unexpired one-time signing link is out."
          },
          "version": {
            "type": "integer"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      }
    }
  },
  "tags": [
    { "name": "Employees", "description": "Team member records, profiles and invitations." },
    { "name": "Leave", "description": "Leave requests, balances, leave types and public holidays." },
    { "name": "Documents", "description": "Document storage, downloads and built-in e-signature." },
    { "name": "Payroll", "description": "Pay schedule, pay runs and payslips (read access; managed figures are entered by Emplorea)." },
    { "name": "Performance", "description": "Probation, reviews, goals and one-on-ones." },
    { "name": "Recruitment", "description": "Roles, candidates, pipeline stages, offers and public job listings." },
    { "name": "Onboarding", "description": "New-hire onboarding plans and their tasks." },
    { "name": "Offboarding", "description": "Offboarding plans and their tasks." },
    { "name": "Compliance", "description": "Compliance score, results, policies, training and incidents." },
    { "name": "Engage", "description": "Surveys, survey programmes, eNPS and recognition." },
    { "name": "Wellbeing", "description": "Team wellbeing scores, absence patterns, WHS incidents and the EAP directory." },
    { "name": "Learn", "description": "Courses, lessons, assignments, completions, certificates and learning paths." },
    { "name": "Ask HR", "description": "Ask Vera an HR question and read past answers." },
    { "name": "Advisor messaging", "description": "Conversation with the company named HR advisor." },
    { "name": "Company & settings", "description": "Company profile, branding and setup completeness." },
    { "name": "Permissions", "description": "Permission presets and per-user overrides." },
    { "name": "Billing", "description": "Plan, add-ons and subscription status (read only)." },
    { "name": "Analytics", "description": "People-analytics summary and exports." },
    { "name": "Authentication", "description": "Company SSO and MFA policy (read only)." },
    { "name": "Webhooks", "description": "Manage webhook endpoints and the events they receive." }
  ],
  "paths": {
    "/billing": {
      "get": {
        "tags": ["Billing"],
        "summary": "Get billing status",
        "operationId": "getBillingStatus",
        "x-agent-hints": "Read-only billing status: plan, subscription status, billing interval, trial info, seat counts (active/billed/minimum) and active add-ons. Plan changes are web-only - there is no checkout/portal or write endpoint here. Read scope.",
        "responses": {
          "200": { "description": "Success", "content": { "application/json": { "schema": { "type": "object", "properties": { "data": { "type": "object" } } } } } },
          "401": { "description": "Missing or invalid API key" }
        }
      }
    },
    "/onboarding": {
      "get": {
        "tags": ["Company & settings"],
        "summary": "Get setup completeness",
        "operationId": "getSetupStatus",
        "x-agent-hints": "Read-only company setup completeness: onboarding_complete, employee_count, and whether the team is invited, leave types configured, a document uploaded and (where the plan includes payroll) a pay schedule set, plus setup_complete for the core tasks. Any plan. Per-user walkthrough state is not exposed (a key carries no user). Read scope.",
        "responses": {
          "200": { "description": "Success", "content": { "application/json": { "schema": { "type": "object", "properties": { "data": { "type": "object" } } } } } },
          "401": { "description": "Missing or invalid API key" }
        }
      }
    },
    "/analytics": {
      "get": {
        "tags": ["Analytics"],
        "summary": "Get people-analytics summary",
        "operationId": "getAnalyticsSummary",
        "x-agent-hints": "Read-only aggregate people analytics (Growth+): current headcount + the active/on_leave/probation split, the 12-month headcount trend, average tenure, and per-jurisdiction turnover (rate, leavers, voluntary/involuntary mix) + department headcount, plus mandatory-training completion with a per-department breakdown under `training.byDepartment`. AGGREGATES ONLY - department cells below the anonymity floor (5 people) are suppressed (with a complementary cell so a hidden one cannot be back-solved), and turnover is never blended across jurisdictions. The same suppressed figures the dashboard and export show. Read scope.",
        "responses": {
          "200": { "description": "Success", "content": { "application/json": { "schema": { "type": "object", "properties": { "data": { "type": "object" } } } } } },
          "401": { "description": "Missing or invalid API key" },
          "403": { "description": "People analytics is available on the Growth plan and above" }
        }
      }
    },
    "/analytics/export": {
      "get": {
        "tags": ["Analytics"],
        "summary": "Export people-analytics summary as CSV",
        "operationId": "exportAnalyticsCsv",
        "x-agent-hints": "Read-only CSV download of the same people-analytics summary (Growth+). The cohort floor carries through identically: a suppressed department cell exports as the literal '<5 - hidden', never blank and never the number. Returns text/csv. Read scope.",
        "responses": {
          "200": { "description": "CSV download", "content": { "text/csv": { "schema": { "type": "string" } } } },
          "401": { "description": "Missing or invalid API key" },
          "403": { "description": "People analytics is available on the Growth plan and above" }
        }
      }
    },
    "/learning-paths": {
      "get": {
        "tags": ["Learn"],
        "summary": "List published learning paths",
        "operationId": "listLearningPaths",
        "x-agent-hints": "Read-only: the company's PUBLISHED Vera Plus learning paths (ordered course sets). Building and publishing are web-only - a company-scoped key cannot generate or publish. Read scope.",
        "responses": {
          "200": { "description": "Success", "content": { "application/json": { "schema": { "type": "object", "properties": { "data": { "type": "array", "items": { "type": "object" } } } } } } },
          "401": { "description": "Missing or invalid API key" }
        }
      }
    },
    "/survey-programmes": {
      "get": {
        "tags": ["Engage"],
        "summary": "List published survey programmes",
        "operationId": "listSurveyProgrammes",
        "x-agent-hints": "Read-only: the company's PUBLISHED Vera Plus survey programmes (ordered survey sets plus a cadence). Building and publishing are web-only. Read scope.",
        "responses": {
          "200": { "description": "Success", "content": { "application/json": { "schema": { "type": "object", "properties": { "data": { "type": "array", "items": { "type": "object" } } } } } } },
          "401": { "description": "Missing or invalid API key" }
        }
      }
    },
    "/recruitment/roles": {
      "get": {
        "tags": ["Recruitment"],
        "summary": "List job roles",
        "operationId": "listJobRoles",
        "x-agent-hints": "Lists open roles with status and active candidate counts. No candidate personal details. Read scope.",
        "responses": {
          "200": { "description": "Success", "content": { "application/json": { "schema": { "type": "object", "properties": { "data": { "type": "object" } } } } } },
          "401": { "description": "Missing or invalid API key" }
        }
      },
      "post": {
        "tags": ["Recruitment"],
        "summary": "Create a job role",
        "operationId": "createJobRole",
        "x-agent-hints": "Creates an open role. Required: title, employment_type, jurisdiction. Write scope.",
        "responses": {
          "200": { "description": "Success", "content": { "application/json": { "schema": { "type": "object", "properties": { "data": { "type": "object", "properties": { "id": { "type": "string" } } } } } } } },
          "401": { "description": "Missing or invalid API key" }
        }
      }
    },
    "/recruitment/roles/{id}": {
      "get": {
        "tags": ["Recruitment"],
        "summary": "Get a job role",
        "operationId": "getJobRole",
        "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "string", "format": "uuid" } } ],
        "x-agent-hints": "One role + per-stage candidate counts. No candidate personal details. Read scope.",
        "responses": {
          "200": { "description": "Success", "content": { "application/json": { "schema": { "type": "object", "properties": { "data": { "type": "object" } } } } } },
          "401": { "description": "Missing or invalid API key" }
        }
      },
      "patch": {
        "tags": ["Recruitment"],
        "summary": "Update a job role status",
        "operationId": "updateJobRole",
        "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "string", "format": "uuid" } } ],
        "x-agent-hints": "Updates the role status (draft/open/on_hold/closed/filled). Write scope.",
        "responses": {
          "200": { "description": "Success", "content": { "application/json": { "schema": { "type": "object", "properties": { "data": { "type": "object" } } } } } },
          "401": { "description": "Missing or invalid API key" }
        }
      }
    },
    "/recruitment/roles/{id}/pipeline": {
      "get": {
        "tags": ["Recruitment"],
        "summary": "Get a role pipeline",
        "operationId": "getRolePipeline",
        "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "string", "format": "uuid" } } ],
        "x-agent-hints": "Stages + each application as an opaque candidate_ref with stage, status and days in stage. Candidate names, emails and CVs are NEVER returned. Read scope.",
        "responses": {
          "200": { "description": "Success", "content": { "application/json": { "schema": { "type": "object", "properties": { "data": { "type": "object" } } } } } },
          "401": { "description": "Missing or invalid API key" }
        }
      }
    },
    "/recruitment/stages": {
      "get": {
        "tags": ["Recruitment"],
        "summary": "List pipeline stages",
        "operationId": "listPipelineStages",
        "x-agent-hints": "The company's configurable pipeline stages. Read scope.",
        "responses": {
          "200": { "description": "Success", "content": { "application/json": { "schema": { "type": "object", "properties": { "data": { "type": "object" } } } } } },
          "401": { "description": "Missing or invalid API key" }
        }
      }
    },
    "/recruitment/candidates": {
      "post": {
        "tags": ["Recruitment"],
        "summary": "Create a candidate",
        "operationId": "createCandidate",
        "x-agent-hints": "Creates a candidate + application. PII is input only; the response returns just { id } and never echoes it. No GET, no CV endpoint (web-only). Write scope.",
        "responses": {
          "200": { "description": "Success", "content": { "application/json": { "schema": { "type": "object", "properties": { "data": { "type": "object", "properties": { "id": { "type": "string" } } } } } } } },
          "401": { "description": "Missing or invalid API key" }
        }
      }
    },
    "/recruitment/applications/{id}/stage": {
      "patch": {
        "tags": ["Recruitment"],
        "summary": "Move an application stage",
        "operationId": "moveApplicationStage",
        "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "string", "format": "uuid" } } ],
        "x-agent-hints": "Moves an application to another active or rejected stage. Cannot move to Hired (hiring is web-only). Write scope.",
        "responses": {
          "200": { "description": "Success", "content": { "application/json": { "schema": { "type": "object", "properties": { "data": { "type": "object" } } } } } },
          "401": { "description": "Missing or invalid API key" }
        }
      }
    },
    "/recruitment/offers": {
      "post": {
        "tags": ["Recruitment"],
        "summary": "Create an offer",
        "operationId": "createOffer",
        "x-agent-hints": "Creates a structured offer (salary in integer cents). Sending and accepting are web-only. Write scope.",
        "responses": {
          "200": { "description": "Success", "content": { "application/json": { "schema": { "type": "object", "properties": { "data": { "type": "object", "properties": { "id": { "type": "string" } } } } } } } },
          "401": { "description": "Missing or invalid API key" }
        }
      }
    },
    "/onboarding/plans": {
      "get": {
        "tags": ["Onboarding"],
        "summary": "List onboarding plans",
        "operationId": "listOnboardingPlans",
        "x-agent-hints": "Lists new-hire onboarding plans with the starter's name, start date, status and task progress. Plans are created automatically when an employee is added (web-only). Growth plan and above. Read scope.",
        "responses": {
          "200": { "description": "Success", "content": { "application/json": { "schema": { "type": "object", "properties": { "data": { "type": "object", "properties": { "plans": { "type": "array", "items": { "type": "object" } } } } } } } } },
          "401": { "description": "Missing or invalid API key" }
        }
      }
    },
    "/onboarding/plans/{id}": {
      "get": {
        "tags": ["Onboarding"],
        "summary": "Get an onboarding plan",
        "operationId": "getOnboardingPlan",
        "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "string", "format": "uuid" } } ],
        "x-agent-hints": "One plan: its tasks (title, category, whether required or Emplorea-managed, completed flag, due date). Read scope.",
        "responses": {
          "200": { "description": "Success", "content": { "application/json": { "schema": { "type": "object", "properties": { "data": { "type": "object" } } } } } },
          "401": { "description": "Missing or invalid API key" }
        }
      }
    },
    "/onboarding/plans/{id}/tasks/{taskId}": {
      "patch": {
        "tags": ["Onboarding"],
        "summary": "Complete an onboarding task",
        "operationId": "completeOnboardingTask",
        "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "string", "format": "uuid" } }, { "name": "taskId", "in": "path", "required": true, "schema": { "type": "string", "format": "uuid" } } ],
        "x-agent-hints": "Completes or reopens an ordinary task (body: { completed: boolean }). Emplorea-managed tasks are refused; plan creation is automatic at hire and completing the onboarding itself is web-only. Write scope.",
        "responses": {
          "200": { "description": "Success", "content": { "application/json": { "schema": { "type": "object", "properties": { "data": { "type": "object", "properties": { "id": { "type": "string" } } } } } } } },
          "401": { "description": "Missing or invalid API key" }
        }
      }
    },
    "/offboarding/plans": {
      "get": {
        "tags": ["Offboarding"],
        "summary": "List offboarding plans",
        "operationId": "listOffboardingPlans",
        "x-agent-hints": "Lists offboarding plans with the leaver's name, last working day, status and task progress. Exit-interview responses are never returned. Initiating a plan is web-only. Read scope.",
        "responses": {
          "200": { "description": "Success", "content": { "application/json": { "schema": { "type": "object", "properties": { "data": { "type": "object", "properties": { "plans": { "type": "array", "items": { "type": "object" } } } } } } } } },
          "401": { "description": "Missing or invalid API key" }
        }
      }
    },
    "/offboarding/plans/{id}": {
      "get": {
        "tags": ["Offboarding"],
        "summary": "Get an offboarding plan",
        "operationId": "getOffboardingPlan",
        "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "string", "format": "uuid" } } ],
        "x-agent-hints": "One plan: its tasks and the exit-interview STATUS only. Exit-interview responses are private and never returned. Read scope.",
        "responses": {
          "200": { "description": "Success", "content": { "application/json": { "schema": { "type": "object", "properties": { "data": { "type": "object" } } } } } },
          "401": { "description": "Missing or invalid API key" }
        }
      }
    },
    "/offboarding/plans/{id}/tasks/{taskId}": {
      "patch": {
        "tags": ["Offboarding"],
        "summary": "Complete an offboarding task",
        "operationId": "completeOffboardingTask",
        "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "string", "format": "uuid" } }, { "name": "taskId", "in": "path", "required": true, "schema": { "type": "string", "format": "uuid" } } ],
        "x-agent-hints": "Completes or reopens an ordinary task (body: { completed: boolean }). Emplorea-managed tasks are refused; completing the offboarding itself (which terminates the employee) is web-only. Write scope.",
        "responses": {
          "200": { "description": "Success", "content": { "application/json": { "schema": { "type": "object", "properties": { "data": { "type": "object", "properties": { "id": { "type": "string" } } } } } } } },
          "401": { "description": "Missing or invalid API key" }
        }
      }
    },
    "/surveys": {
      "post": {
        "tags": ["Engage"],
        "summary": "Create a survey",
        "operationId": "createSurvey",
        "x-agent-hints": "Creates a DRAFT engagement survey (eNPS, pulse or check-in). Required: title, type, anonymity. Publishing it to the audience is a separate web step. Growth plan and above. Write scope.",
        "responses": {
          "201": { "description": "Created", "content": { "application/json": { "schema": { "type": "object", "properties": { "data": { "type": "object", "properties": { "id": { "type": "string" } } } } } } } },
          "401": { "description": "Missing or invalid API key" }
        }
      }
    },
    "/surveys/{id}/results": {
      "get": {
        "tags": ["Engage"],
        "summary": "Get survey results",
        "operationId": "getSurveyResults",
        "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "string", "format": "uuid" } } ],
        "x-agent-hints": "AGGREGATES ONLY: response rate, eNPS and per-question summaries. Never an individual response or a respondent id; below the k-anonymity floor no breakdown is returned at all. Read scope.",
        "responses": {
          "200": { "description": "Success", "content": { "application/json": { "schema": { "type": "object", "properties": { "data": { "type": "object" } } } } } },
          "401": { "description": "Missing or invalid API key" }
        }
      }
    },
    "/surveys/{id}/respond": {
      "post": {
        "tags": ["Engage"],
        "summary": "Submit a survey response",
        "operationId": "submitSurveyResponse",
        "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "string", "format": "uuid" } } ],
        "x-agent-hints": "Submits a response to an open survey. ANONYMOUS surveys are refused over the API - they can only be answered in the app (a company-scoped key must never fabricate anonymous responses at scale). An attributed survey requires employee_id in the body. Write scope.",
        "responses": {
          "201": { "description": "Created", "content": { "application/json": { "schema": { "type": "object", "properties": { "data": { "type": "object", "properties": { "id": { "type": "string" } } } } } } } },
          "401": { "description": "Missing or invalid API key" }
        }
      }
    },
    "/recognition": {
      "get": {
        "tags": ["Engage"],
        "summary": "List recognition",
        "operationId": "listRecognition",
        "x-agent-hints": "The recognition feed - PUBLIC posts only for a roleless API key (private posts are never returned). Each carries giver, recipient, message, value tag, kind and reaction count. Read scope.",
        "responses": {
          "200": { "description": "Success", "content": { "application/json": { "schema": { "type": "object", "properties": { "data": { "type": "array", "items": { "type": "object" } } } } } } },
          "401": { "description": "Missing or invalid API key" }
        }
      },
      "post": {
        "tags": ["Engage"],
        "summary": "Post recognition",
        "operationId": "postRecognition",
        "x-agent-hints": "Posts recognition from one team member to a colleague. Required: from_employee_id, to_employee_id, message. Manager-kind requires the author to be the recipient's manager. You cannot recognise yourself. Write scope.",
        "responses": {
          "201": { "description": "Created", "content": { "application/json": { "schema": { "type": "object", "properties": { "data": { "type": "object", "properties": { "id": { "type": "string" } } } } } } } },
          "401": { "description": "Missing or invalid API key" }
        }
      }
    },
    "/messaging/conversation": {
      "get": {
        "tags": ["Advisor messaging"],
        "summary": "Get advisor conversation metadata",
        "operationId": "getAdvisorConversation",
        "x-agent-hints": "Returns metadata about the company's HR advisor conversation: status, whether an advisor is assigned, advisor name/status, unread count, last message time. Message content is human-to-human and NEVER exposed - no content, no message list, no send. Read scope.",
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "status": { "type": "string" },
                        "advisor_assigned": { "type": "boolean" },
                        "advisor_name": { "type": "string", "nullable": true },
                        "advisor_status": { "type": "string", "nullable": true },
                        "unread_count": { "type": "integer" },
                        "last_message_at": { "type": "string", "nullable": true },
                        "last_message_sender": { "type": "string", "nullable": true }
                      }
                    }
                  }
                }
              }
            }
          },
          "401": { "description": "Missing or invalid API key" }
        }
      }
    },
    "/permissions/presets": {
      "get": {
        "tags": ["Permissions"],
        "summary": "List permission presets",
        "operationId": "listPermissionPresets",
        "x-agent-hints": "Lists the named manager presets (team_lead, hr_manager) and the capability keys each grants. No personal data. Read scope.",
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "presets": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "preset": { "type": "string" },
                              "capabilities": { "type": "array", "items": { "type": "string" } }
                            }
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "401": { "description": "Missing or invalid API key" }
        }
      }
    },
    "/permissions/company": {
      "get": {
        "tags": ["Permissions"],
        "summary": "Get company manager permission overrides",
        "operationId": "getCompanyPermissions",
        "x-agent-hints": "Returns the per-company capability overrides applied to managers (capability key to granted boolean). No personal data. Read scope. Changing permissions is web-only.",
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "manager": { "type": "object", "additionalProperties": { "type": "boolean" } }
                      }
                    }
                  }
                }
              }
            }
          },
          "401": { "description": "Missing or invalid API key" }
        }
      }
    },
    "/permissions/users/{id}": {
      "get": {
        "tags": ["Permissions"],
        "summary": "Get a user's resolved permissions",
        "operationId": "getUserPermissions",
        "x-agent-hints": "Returns one user's role, preset and resolved capability keys plus team scope. Capability keys only, never personal data. Read scope.",
        "parameters": [
          { "name": "id", "in": "path", "required": true, "schema": { "type": "string", "format": "uuid" } }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "user_id": { "type": "string" },
                        "role": { "type": "string" },
                        "preset": { "type": "string", "nullable": true },
                        "capabilities": { "type": "array", "items": { "type": "string" } },
                        "scope": { "type": "string" }
                      }
                    }
                  }
                }
              }
            }
          },
          "401": { "description": "Missing or invalid API key" },
          "404": { "description": "User not found in this company" }
        }
      }
    },
    "/company/branding": {
      "get": {
        "tags": ["Company & settings"],
        "summary": "Get company branding",
        "operationId": "getCompanyBranding",
        "x-agent-hints": "Returns the company's branding: primary_colour, accent_colour, brand_name, logo_url, email_branding and published_at. Growth plan and above (FORBIDDEN below). Company-scoped - a key only reads its own company. Read scope.",
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  },
                  "required": [
                    "error"
                  ]
                }
              }
            }
          },
          "403": {
            "description": "Branding is a Growth-plan feature",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  },
                  "required": [
                    "error"
                  ]
                }
              }
            }
          }
        }
      },
      "put": {
        "tags": ["Company & settings"],
        "summary": "Update company branding",
        "operationId": "updateCompanyBranding",
        "x-agent-hints": "Sets primary_colour / accent_colour (6-digit hex like #1B6CA8), brand_name (null = use the company name) and email_branding, then publishes immediately. The logo is uploaded at /company/branding/logo. Growth plan and above. Write scope.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "primary_colour": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "accent_colour": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "brand_name": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "email_branding": {
                    "type": "boolean"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  },
                  "required": [
                    "error"
                  ]
                }
              }
            }
          },
          "403": {
            "description": "Branding is a Growth-plan feature",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  },
                  "required": [
                    "error"
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/company/branding/logo": {
      "post": {
        "tags": ["Company & settings"],
        "summary": "Upload a branding logo",
        "operationId": "uploadCompanyBrandingLogo",
        "x-agent-hints": "multipart/form-data with a 'file' field (PNG, JPEG, WEBP or SVG; 2MB max; SVG is sanitised server-side). Publishes immediately. Growth plan and above. Write scope.",
        "requestBody": {
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "properties": {
                  "file": {
                    "type": "string",
                    "format": "binary"
                  }
                },
                "required": [
                  "file"
                ]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Logo stored",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  },
                  "required": [
                    "error"
                  ]
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": ["Company & settings"],
        "summary": "Remove the branding logo",
        "operationId": "removeCompanyBrandingLogo",
        "x-agent-hints": "Removes the logo and reverts to the Emplorea mark. Colours are kept. Growth plan and above. Write scope.",
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  },
                  "required": [
                    "error"
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/company/branding/reset": {
      "post": {
        "tags": ["Company & settings"],
        "summary": "Reset company branding",
        "operationId": "resetCompanyBranding",
        "x-agent-hints": "Clears all branding (colours, brand name and logo) back to Emplorea defaults. Growth plan and above. Write scope.",
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Branding is a Growth-plan feature",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  },
                  "required": [
                    "error"
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/company": {
      "get": {
        "tags": ["Company & settings"],
        "summary": "Get the company",
        "operationId": "getCompany",
        "x-agent-hints": "Call this first. It returns the company name, plan, jurisdiction, currency, timezone, financial year start and the read-only Vera company context - the context every other call depends on.",
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "id": { "type": "string", "format": "uuid" },
                        "name": { "type": "string" },
                        "jurisdiction": { "type": "array", "items": { "type": "string" } },
                        "plan": { "type": "string" },
                        "company_size": { "type": "string", "nullable": true },
                        "industry": { "type": "string", "nullable": true },
                        "vera_context": {
                          "type": "string",
                          "nullable": true,
                          "description": "Admin-authored \"About your business\" context that steers Vera Plus generation. Read-only here; edited in company settings (Vera Plus, company_admin). Write is web-only."
                        },
                        "website": { "type": "string", "nullable": true },
                        "currency": { "type": "string" },
                        "timezone": { "type": "string" },
                        "financial_year_start": { "type": "string" },
                        "primary_domain": {
                          "type": "string",
                          "nullable": true,
                          "description": "The company email domain detected at sign-up. Read-only (never writable here)."
                        },
                        "allowed_domains": {
                          "type": "array",
                          "items": { "type": "string" },
                          "description": "The invite domain allowlist. Editable via PATCH; the primary domain is always kept and a blocked personal domain is rejected."
                        },
                        "domain_enforcement_enabled": {
                          "type": "boolean",
                          "description": "When true, a new team member can only be invited on an allowed domain."
                        },
                        "created_at": { "type": "string", "format": "date-time" }
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "UNAUTHORISED",
                            "FORBIDDEN",
                            "NOT_FOUND",
                            "VALIDATION_ERROR",
                            "CONFLICT",
                            "RATE_LIMITED",
                            "NOT_IMPLEMENTED",
                            "INTERNAL_ERROR"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  },
                  "required": [
                    "error"
                  ]
                }
              }
            }
          },
          "429": {
            "description": "Rate limited (100 requests/minute per key)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "UNAUTHORISED",
                            "FORBIDDEN",
                            "NOT_FOUND",
                            "VALIDATION_ERROR",
                            "CONFLICT",
                            "RATE_LIMITED",
                            "NOT_IMPLEMENTED",
                            "INTERNAL_ERROR"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  },
                  "required": [
                    "error"
                  ]
                }
              }
            }
          }
        }
      },
      "patch": {
        "tags": ["Company & settings"],
        "summary": "Update company details",
        "operationId": "updateCompany",
        "x-agent-hints": "Updates name, website, industry, phone, and the domain controls (allowed_domains, domain_enforcement_enabled). primary_domain is detected at sign-up and is not writable. A blocked personal domain in allowed_domains returns VALIDATION_ERROR. Requires the admin scope.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string"
                  },
                  "website": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "industry": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "phone": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "allowed_domains": {
                    "type": "array",
                    "items": { "type": "string" },
                    "description": "The invite domain allowlist. A blocked personal domain returns VALIDATION_ERROR (field allowed_domains); the primary domain is always kept."
                  },
                  "domain_enforcement_enabled": {
                    "type": "boolean",
                    "description": "Turn invite domain enforcement on or off."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "UNAUTHORISED",
                            "FORBIDDEN",
                            "NOT_FOUND",
                            "VALIDATION_ERROR",
                            "CONFLICT",
                            "RATE_LIMITED",
                            "NOT_IMPLEMENTED",
                            "INTERNAL_ERROR"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  },
                  "required": [
                    "error"
                  ]
                }
              }
            }
          },
          "429": {
            "description": "Rate limited (100 requests/minute per key)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "UNAUTHORISED",
                            "FORBIDDEN",
                            "NOT_FOUND",
                            "VALIDATION_ERROR",
                            "CONFLICT",
                            "RATE_LIMITED",
                            "NOT_IMPLEMENTED",
                            "INTERNAL_ERROR"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  },
                  "required": [
                    "error"
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/employees": {
      "get": {
        "tags": ["Employees"],
        "summary": "List employees",
        "operationId": "listEmployees",
        "x-agent-hints": "Lists active employees by default. Use ?status=terminated for former employees or ?status=all for everyone. Filter by ?department. Paginated.",
        "parameters": [
          {
            "name": "page",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 1
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 50,
              "maximum": 100
            }
          },
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "active",
                "terminated",
                "all"
              ]
            }
          },
          {
            "name": "department",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Employee"
                      }
                    },
                    "meta": {
                      "type": "object",
                      "properties": {
                        "total": {
                          "type": "integer"
                        },
                        "page": {
                          "type": "integer"
                        },
                        "limit": {
                          "type": "integer"
                        },
                        "has_more": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "total",
                        "page",
                        "limit",
                        "has_more"
                      ]
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "UNAUTHORISED",
                            "FORBIDDEN",
                            "NOT_FOUND",
                            "VALIDATION_ERROR",
                            "CONFLICT",
                            "RATE_LIMITED",
                            "NOT_IMPLEMENTED",
                            "INTERNAL_ERROR"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  },
                  "required": [
                    "error"
                  ]
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "UNAUTHORISED",
                            "FORBIDDEN",
                            "NOT_FOUND",
                            "VALIDATION_ERROR",
                            "CONFLICT",
                            "RATE_LIMITED",
                            "NOT_IMPLEMENTED",
                            "INTERNAL_ERROR"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  },
                  "required": [
                    "error"
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/employees/{id}": {
      "get": {
        "tags": ["Employees"],
        "summary": "Get an employee",
        "operationId": "getEmployee",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "x-agent-hints": "Full employee record including salary (integer cents) and status.",
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Employee"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "UNAUTHORISED",
                            "FORBIDDEN",
                            "NOT_FOUND",
                            "VALIDATION_ERROR",
                            "CONFLICT",
                            "RATE_LIMITED",
                            "NOT_IMPLEMENTED",
                            "INTERNAL_ERROR"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  },
                  "required": [
                    "error"
                  ]
                }
              }
            }
          },
          "429": {
            "description": "Rate limited (100 requests/minute per key)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "UNAUTHORISED",
                            "FORBIDDEN",
                            "NOT_FOUND",
                            "VALIDATION_ERROR",
                            "CONFLICT",
                            "RATE_LIMITED",
                            "NOT_IMPLEMENTED",
                            "INTERNAL_ERROR"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  },
                  "required": [
                    "error"
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "UNAUTHORISED",
                            "FORBIDDEN",
                            "NOT_FOUND",
                            "VALIDATION_ERROR",
                            "CONFLICT",
                            "RATE_LIMITED",
                            "NOT_IMPLEMENTED",
                            "INTERNAL_ERROR"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  },
                  "required": [
                    "error"
                  ]
                }
              }
            }
          }
        }
      },
      "patch": {
        "tags": ["Employees"],
        "summary": "Update an employee",
        "operationId": "updateEmployee",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "x-agent-hints": "Patch any editable field (job_title, department, employment_type, base_salary in cents, manager_id...). Terminated employees cannot be edited.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "UNAUTHORISED",
                            "FORBIDDEN",
                            "NOT_FOUND",
                            "VALIDATION_ERROR",
                            "CONFLICT",
                            "RATE_LIMITED",
                            "NOT_IMPLEMENTED",
                            "INTERNAL_ERROR"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  },
                  "required": [
                    "error"
                  ]
                }
              }
            }
          },
          "429": {
            "description": "Rate limited (100 requests/minute per key)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "UNAUTHORISED",
                            "FORBIDDEN",
                            "NOT_FOUND",
                            "VALIDATION_ERROR",
                            "CONFLICT",
                            "RATE_LIMITED",
                            "NOT_IMPLEMENTED",
                            "INTERNAL_ERROR"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  },
                  "required": [
                    "error"
                  ]
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": ["Employees"],
        "summary": "Terminate an employee",
        "operationId": "terminateEmployee",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "x-agent-hints": "Terminates the employment - Emplorea never hard-deletes people records (they are kept for compliance). Optional JSON body: termination_date (defaults today) and termination_reason (resignation, redundancy, performance, end_of_contract or other - defaults other).",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "termination_date": {
                    "type": "string",
                    "format": "date"
                  },
                  "termination_reason": {
                    "type": "string",
                    "enum": [
                      "resignation",
                      "redundancy",
                      "performance",
                      "end_of_contract",
                      "other"
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "UNAUTHORISED",
                            "FORBIDDEN",
                            "NOT_FOUND",
                            "VALIDATION_ERROR",
                            "CONFLICT",
                            "RATE_LIMITED",
                            "NOT_IMPLEMENTED",
                            "INTERNAL_ERROR"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  },
                  "required": [
                    "error"
                  ]
                }
              }
            }
          },
          "429": {
            "description": "Rate limited (100 requests/minute per key)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "UNAUTHORISED",
                            "FORBIDDEN",
                            "NOT_FOUND",
                            "VALIDATION_ERROR",
                            "CONFLICT",
                            "RATE_LIMITED",
                            "NOT_IMPLEMENTED",
                            "INTERNAL_ERROR"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  },
                  "required": [
                    "error"
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/employees/{id}/invite": {
      "post": {
        "tags": ["Employees"],
        "operationId": "inviteEmployee",
        "summary": "Send an invite email to an employee",
        "description": "Generates a Supabase invite link and sends the Emplorea welcome email so the employee can set a password and access the portal. Requires write scope.",
        "security": [{ "BearerAuth": [] }],
        "parameters": [
          { "name": "id", "in": "path", "required": true, "schema": { "type": "string", "format": "uuid" } }
        ],
        "responses": {
          "200": {
            "description": "Invite sent",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "employeeId": { "type": "string", "format": "uuid" },
                        "invited": { "type": "boolean" }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/leave": {
      "get": {
        "tags": ["Leave"],
        "summary": "List leave requests",
        "operationId": "listLeave",
        "x-agent-hints": "Pending requests sort first. Filter with ?employee_id, ?status (pending, approved, declined or all) and a ?from / ?to date range.",
        "parameters": [
          {
            "name": "page",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 1
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 50,
              "maximum": 100
            }
          },
          {
            "name": "employee_id",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "pending",
                "approved",
                "declined",
                "all"
              ]
            }
          },
          {
            "name": "from",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "to",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/LeaveRequest"
                      }
                    },
                    "meta": {
                      "type": "object",
                      "properties": {
                        "total": {
                          "type": "integer"
                        },
                        "page": {
                          "type": "integer"
                        },
                        "limit": {
                          "type": "integer"
                        },
                        "has_more": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "total",
                        "page",
                        "limit",
                        "has_more"
                      ]
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "UNAUTHORISED",
                            "FORBIDDEN",
                            "NOT_FOUND",
                            "VALIDATION_ERROR",
                            "CONFLICT",
                            "RATE_LIMITED",
                            "NOT_IMPLEMENTED",
                            "INTERNAL_ERROR"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  },
                  "required": [
                    "error"
                  ]
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "UNAUTHORISED",
                            "FORBIDDEN",
                            "NOT_FOUND",
                            "VALIDATION_ERROR",
                            "CONFLICT",
                            "RATE_LIMITED",
                            "NOT_IMPLEMENTED",
                            "INTERNAL_ERROR"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  },
                  "required": [
                    "error"
                  ]
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": ["Leave"],
        "summary": "Request leave",
        "operationId": "requestLeave",
        "x-agent-hints": "Use this to request leave on behalf of an employee. Check GET /leave/balances first to confirm the employee has sufficient entitlement. Day counts exclude weekends and public holidays automatically. Types with requires_approval=false are approved instantly. The response includes non-blocking warnings (insufficient balance, team overlaps) - the request is saved regardless and the manager is notified.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/LeaveCreate"
              },
              "example": {
                "employee_id": "uuid-here",
                "leave_type_id": "uuid-here",
                "start_date": "2026-07-14",
                "end_date": "2026-07-18",
                "notes": "Family holiday"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created (warnings are non-blocking)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        },
                        "days": {
                          "type": "number"
                        },
                        "status": {
                          "type": "string"
                        }
                      }
                    },
                    "warnings": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "UNAUTHORISED",
                            "FORBIDDEN",
                            "NOT_FOUND",
                            "VALIDATION_ERROR",
                            "CONFLICT",
                            "RATE_LIMITED",
                            "NOT_IMPLEMENTED",
                            "INTERNAL_ERROR"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  },
                  "required": [
                    "error"
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "UNAUTHORISED",
                            "FORBIDDEN",
                            "NOT_FOUND",
                            "VALIDATION_ERROR",
                            "CONFLICT",
                            "RATE_LIMITED",
                            "NOT_IMPLEMENTED",
                            "INTERNAL_ERROR"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  },
                  "required": [
                    "error"
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/leave/{id}": {
      "get": {
        "tags": ["Leave"],
        "summary": "Get a leave request",
        "operationId": "getLeave",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/LeaveRequest"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "UNAUTHORISED",
                            "FORBIDDEN",
                            "NOT_FOUND",
                            "VALIDATION_ERROR",
                            "CONFLICT",
                            "RATE_LIMITED",
                            "NOT_IMPLEMENTED",
                            "INTERNAL_ERROR"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  },
                  "required": [
                    "error"
                  ]
                }
              }
            }
          },
          "429": {
            "description": "Rate limited (100 requests/minute per key)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "UNAUTHORISED",
                            "FORBIDDEN",
                            "NOT_FOUND",
                            "VALIDATION_ERROR",
                            "CONFLICT",
                            "RATE_LIMITED",
                            "NOT_IMPLEMENTED",
                            "INTERNAL_ERROR"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  },
                  "required": [
                    "error"
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "UNAUTHORISED",
                            "FORBIDDEN",
                            "NOT_FOUND",
                            "VALIDATION_ERROR",
                            "CONFLICT",
                            "RATE_LIMITED",
                            "NOT_IMPLEMENTED",
                            "INTERNAL_ERROR"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  },
                  "required": [
                    "error"
                  ]
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": ["Leave"],
        "summary": "Cancel a leave request",
        "operationId": "cancelLeave",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "x-agent-hints": "Cancels (soft-deletes) the request. Optional body: reason.",
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "UNAUTHORISED",
                            "FORBIDDEN",
                            "NOT_FOUND",
                            "VALIDATION_ERROR",
                            "CONFLICT",
                            "RATE_LIMITED",
                            "NOT_IMPLEMENTED",
                            "INTERNAL_ERROR"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  },
                  "required": [
                    "error"
                  ]
                }
              }
            }
          },
          "429": {
            "description": "Rate limited (100 requests/minute per key)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "UNAUTHORISED",
                            "FORBIDDEN",
                            "NOT_FOUND",
                            "VALIDATION_ERROR",
                            "CONFLICT",
                            "RATE_LIMITED",
                            "NOT_IMPLEMENTED",
                            "INTERNAL_ERROR"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  },
                  "required": [
                    "error"
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/leave/{id}/approve": {
      "patch": {
        "tags": ["Leave"],
        "summary": "Approve a pending leave request",
        "operationId": "approveLeave",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "x-agent-hints": "Only pending requests can be approved. The employee is notified and the days deduct from their balance.",
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "UNAUTHORISED",
                            "FORBIDDEN",
                            "NOT_FOUND",
                            "VALIDATION_ERROR",
                            "CONFLICT",
                            "RATE_LIMITED",
                            "NOT_IMPLEMENTED",
                            "INTERNAL_ERROR"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  },
                  "required": [
                    "error"
                  ]
                }
              }
            }
          },
          "429": {
            "description": "Rate limited (100 requests/minute per key)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "UNAUTHORISED",
                            "FORBIDDEN",
                            "NOT_FOUND",
                            "VALIDATION_ERROR",
                            "CONFLICT",
                            "RATE_LIMITED",
                            "NOT_IMPLEMENTED",
                            "INTERNAL_ERROR"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  },
                  "required": [
                    "error"
                  ]
                }
              }
            }
          },
          "409": {
            "description": "Not pending",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "UNAUTHORISED",
                            "FORBIDDEN",
                            "NOT_FOUND",
                            "VALIDATION_ERROR",
                            "CONFLICT",
                            "RATE_LIMITED",
                            "NOT_IMPLEMENTED",
                            "INTERNAL_ERROR"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  },
                  "required": [
                    "error"
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/leave/{id}/decline": {
      "patch": {
        "tags": ["Leave"],
        "summary": "Decline a pending leave request",
        "operationId": "declineLeave",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "x-agent-hints": "A reason is required and is shown to the employee.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "reason"
                ],
                "properties": {
                  "reason": {
                    "type": "string",
                    "maxLength": 500
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "UNAUTHORISED",
                            "FORBIDDEN",
                            "NOT_FOUND",
                            "VALIDATION_ERROR",
                            "CONFLICT",
                            "RATE_LIMITED",
                            "NOT_IMPLEMENTED",
                            "INTERNAL_ERROR"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  },
                  "required": [
                    "error"
                  ]
                }
              }
            }
          },
          "429": {
            "description": "Rate limited (100 requests/minute per key)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "UNAUTHORISED",
                            "FORBIDDEN",
                            "NOT_FOUND",
                            "VALIDATION_ERROR",
                            "CONFLICT",
                            "RATE_LIMITED",
                            "NOT_IMPLEMENTED",
                            "INTERNAL_ERROR"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  },
                  "required": [
                    "error"
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/leave/balances": {
      "get": {
        "tags": ["Leave"],
        "summary": "Leave balances",
        "operationId": "getLeaveBalances",
        "x-agent-hints": "Annual and sick balances for every active employee (or one with ?employee_id). Annual accrues 20 days/year from the start date; sick accrues 10 days/year and resets at the company financial year start. Check this before requesting leave.",
        "parameters": [
          {
            "name": "employee_id",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/LeaveBalance"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "UNAUTHORISED",
                            "FORBIDDEN",
                            "NOT_FOUND",
                            "VALIDATION_ERROR",
                            "CONFLICT",
                            "RATE_LIMITED",
                            "NOT_IMPLEMENTED",
                            "INTERNAL_ERROR"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  },
                  "required": [
                    "error"
                  ]
                }
              }
            }
          },
          "429": {
            "description": "Rate limited (100 requests/minute per key)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "UNAUTHORISED",
                            "FORBIDDEN",
                            "NOT_FOUND",
                            "VALIDATION_ERROR",
                            "CONFLICT",
                            "RATE_LIMITED",
                            "NOT_IMPLEMENTED",
                            "INTERNAL_ERROR"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  },
                  "required": [
                    "error"
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/leave-types": {
      "get": {
        "tags": ["Leave"],
        "summary": "List leave types",
        "operationId": "listLeaveTypes",
        "x-agent-hints": "Get leave_type_id values for POST /leave. requires_approval=false types auto-approve.",
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/LeaveType"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "UNAUTHORISED",
                            "FORBIDDEN",
                            "NOT_FOUND",
                            "VALIDATION_ERROR",
                            "CONFLICT",
                            "RATE_LIMITED",
                            "NOT_IMPLEMENTED",
                            "INTERNAL_ERROR"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  },
                  "required": [
                    "error"
                  ]
                }
              }
            }
          },
          "429": {
            "description": "Rate limited (100 requests/minute per key)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "UNAUTHORISED",
                            "FORBIDDEN",
                            "NOT_FOUND",
                            "VALIDATION_ERROR",
                            "CONFLICT",
                            "RATE_LIMITED",
                            "NOT_IMPLEMENTED",
                            "INTERNAL_ERROR"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  },
                  "required": [
                    "error"
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/public-holidays": {
      "get": {
        "tags": ["Leave"],
        "summary": "List public holidays",
        "operationId": "listPublicHolidays",
        "x-agent-hints": "2026 seed data for AU (national plus state days with ?region=NSW etc), NZ and UK (England/Wales). Leave day counts already exclude these.",
        "parameters": [
          {
            "name": "jurisdiction",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "AU",
                "NZ",
                "UK"
              ],
              "default": "AU"
            }
          },
          {
            "name": "region",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "year",
            "in": "query",
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/PublicHoliday"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "UNAUTHORISED",
                            "FORBIDDEN",
                            "NOT_FOUND",
                            "VALIDATION_ERROR",
                            "CONFLICT",
                            "RATE_LIMITED",
                            "NOT_IMPLEMENTED",
                            "INTERNAL_ERROR"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  },
                  "required": [
                    "error"
                  ]
                }
              }
            }
          },
          "429": {
            "description": "Rate limited (100 requests/minute per key)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "UNAUTHORISED",
                            "FORBIDDEN",
                            "NOT_FOUND",
                            "VALIDATION_ERROR",
                            "CONFLICT",
                            "RATE_LIMITED",
                            "NOT_IMPLEMENTED",
                            "INTERNAL_ERROR"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  },
                  "required": [
                    "error"
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/webhooks": {
      "get": {
        "tags": ["Webhooks"],
        "summary": "List webhook endpoints",
        "operationId": "listWebhooks",
        "x-agent-hints": "Requires the webhooks scope.",
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Webhook"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "UNAUTHORISED",
                            "FORBIDDEN",
                            "NOT_FOUND",
                            "VALIDATION_ERROR",
                            "CONFLICT",
                            "RATE_LIMITED",
                            "NOT_IMPLEMENTED",
                            "INTERNAL_ERROR"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  },
                  "required": [
                    "error"
                  ]
                }
              }
            }
          },
          "429": {
            "description": "Rate limited (100 requests/minute per key)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "UNAUTHORISED",
                            "FORBIDDEN",
                            "NOT_FOUND",
                            "VALIDATION_ERROR",
                            "CONFLICT",
                            "RATE_LIMITED",
                            "NOT_IMPLEMENTED",
                            "INTERNAL_ERROR"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  },
                  "required": [
                    "error"
                  ]
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": ["Webhooks"],
        "summary": "Create a webhook endpoint",
        "operationId": "createWebhook",
        "x-agent-hints": "Subscribe an HTTPS URL to events. Topics: employee, leave, document, hr_question, advisor, compliance, payroll, payslip, performance, permissions, messaging, recruitment, offboarding, branding, engage, wellbeing, learn, vera, email, auth, billing. See the events enum for the full list of subscribable event names. The signing secret is returned ONCE - verify every delivery's X-Emplorea-Signature header (HMAC-SHA256 of the raw body, format sha256=<hex>). Deliveries retry 3 times with exponential backoff.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "url",
                  "events"
                ],
                "properties": {
                  "url": {
                    "type": "string",
                    "format": "uri",
                    "description": "Must be HTTPS."
                  },
                  "events": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "enum": [
                        "employee.created",
                        "employee.updated",
                        "employee.terminated",
                        "leave.requested",
                        "leave.approved",
                        "leave.declined",
                        "leave.cancelled",
                        "document.uploaded",
                        "document.sent_for_signature",
                        "document.signed",
                        "hr_question.asked",
                        "hr_question.answered",
                        "employee.invited",
                        "advisor.assigned",
                        "compliance.item_created",
                        "compliance.item_resolved",
                        "compliance.incident_logged",
                        "compliance.incident_resolved",
                        "compliance.policy_acknowledged",
                        "compliance.score_threshold_crossed",
                        "payroll.run_ready",
                        "payroll.run_paid",
                        "payroll.pay_date_approaching",
                        "payslip.available",
                        "performance.probation_completed",
                        "performance.review_shared",
                        "performance.review_acknowledged",
                        "performance.goal_created",
                        "performance.goal_status_changed",
                        "performance.one_on_one_logged",
                        "performance.goal_overdue",
                        "performance.one_on_one_overdue",
                        "permissions.preset_changed",
                        "permissions.feature_toggled",
                        "messaging.message.sent",
                        "messaging.message.read",
                        "recruitment.role_created",
                        "recruitment.role_closed",
                        "recruitment.candidate_applied",
                        "recruitment.candidate_stage_changed",
                        "recruitment.offer_sent",
                        "recruitment.offer_accepted",
                        "recruitment.offer_declined",
                        "recruitment.employee_created",
                        "offboarding.plan_created",
                        "offboarding.task_completed",
                        "offboarding.plan_completed",
                        "offboarding.exit_interview_completed",
                        "onboarding.created",
                        "onboarding.task_completed",
                        "branding.published",
                        "branding.reset",
                        "engage.survey.sent",
                        "engage.survey.completed",
                        "engage.survey.closed",
                        "engage.recognition.posted",
                        "wellbeing.score.updated",
                        "wellbeing.incident.action_completed",
                        "learn.course.assigned",
                        "learn.lesson.completed",
                        "learn.course.completed",
                        "learn.certificate.issued",
                        "learn.assignment.overdue",
                        "vera.learning_path.published",
                        "vera.survey_programme.published",
                        "email.bounced",
                        "email.complained",
                        "auth.sso.enabled",
                        "auth.mfa.enrolled",
                        "auth.session.revoked",
                        "billing.plan.upgraded",
                        "billing.plan.downgraded",
                        "billing.trial.started",
                        "billing.trial.ending_soon",
                        "billing.trial.expired",
                        "billing.payment.failed",
                        "billing.payment.recovered",
                        "billing.subscription.cancelled"
                      ]
                    }
                  }
                }
              },
              "example": {
                "url": "https://example.com/hooks/emplorea",
                "events": [
                  "employee.created",
                  "leave.approved"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Webhook"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "UNAUTHORISED",
                            "FORBIDDEN",
                            "NOT_FOUND",
                            "VALIDATION_ERROR",
                            "CONFLICT",
                            "RATE_LIMITED",
                            "NOT_IMPLEMENTED",
                            "INTERNAL_ERROR"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  },
                  "required": [
                    "error"
                  ]
                }
              }
            }
          },
          "429": {
            "description": "Rate limited (100 requests/minute per key)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "UNAUTHORISED",
                            "FORBIDDEN",
                            "NOT_FOUND",
                            "VALIDATION_ERROR",
                            "CONFLICT",
                            "RATE_LIMITED",
                            "NOT_IMPLEMENTED",
                            "INTERNAL_ERROR"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  },
                  "required": [
                    "error"
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/webhooks/{id}": {
      "delete": {
        "tags": ["Webhooks"],
        "summary": "Delete a webhook endpoint",
        "operationId": "deleteWebhook",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "UNAUTHORISED",
                            "FORBIDDEN",
                            "NOT_FOUND",
                            "VALIDATION_ERROR",
                            "CONFLICT",
                            "RATE_LIMITED",
                            "NOT_IMPLEMENTED",
                            "INTERNAL_ERROR"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  },
                  "required": [
                    "error"
                  ]
                }
              }
            }
          },
          "429": {
            "description": "Rate limited (100 requests/minute per key)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "UNAUTHORISED",
                            "FORBIDDEN",
                            "NOT_FOUND",
                            "VALIDATION_ERROR",
                            "CONFLICT",
                            "RATE_LIMITED",
                            "NOT_IMPLEMENTED",
                            "INTERNAL_ERROR"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  },
                  "required": [
                    "error"
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/documents": {
      "get": {
        "tags": ["Documents"],
        "summary": "List documents",
        "operationId": "listDocuments",
        "x-agent-hints": "Contracts, payslips, policies and certificates. Filter with employee_id, type or signed=true|false. awaiting_signature means a live sign link is out.",
        "parameters": [
          {
            "name": "employee_id",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "type",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "contract",
                "payslip",
                "policy",
                "certificate",
                "other"
              ]
            }
          },
          {
            "name": "signed",
            "in": "query",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "page",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Documents",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Document"
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/ListMeta"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorised",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": ["Documents"],
        "summary": "Upload a document",
        "operationId": "uploadDocument",
        "x-agent-hints": "multipart/form-data: file (PDF for contracts; PDF/PNG/JPEG otherwise, 10MB max) + type + title. employee_id links it to a person (required for payslips, with pay_period like 'June 2026' - the title is composed for you). Requires the write scope.",
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "required": [
                  "file",
                  "type",
                  "title"
                ],
                "properties": {
                  "file": {
                    "type": "string",
                    "format": "binary"
                  },
                  "type": {
                    "type": "string",
                    "enum": [
                      "contract",
                      "payslip",
                      "policy",
                      "certificate",
                      "other"
                    ]
                  },
                  "title": {
                    "type": "string"
                  },
                  "employee_id": {
                    "type": "string",
                    "format": "uuid"
                  },
                  "pay_period": {
                    "type": "string",
                    "example": "June 2026"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Uploaded",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Document"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Missing write scope",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/auth/policy": {
      "get": {
        "tags": ["Authentication"],
        "summary": "Get the company SSO/MFA policy",
        "operationId": "getAuthPolicy",
        "description": "The company's authentication policy: whether single sign-on is required, the allowed SSO email domain, and whether two-factor is required for all team members. Read scope. Personal security actions (MFA enrolment, SSO linking, session revocation) are deliberately not on the API - a company key carries no user identity.",
        "x-agent-hints": "A read-only company-level fact. There are no auth writes on the API or MCP by design; SSO/MFA setup and session management are web-only, session-authenticated actions.",
        "responses": {
          "200": {
            "description": "The company's SSO and MFA policy",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "sso_required": { "type": "boolean" },
                        "sso_domain": { "type": "string", "nullable": true },
                        "mfa_required": { "type": "boolean" }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/payroll": {
      "get": {
        "tags": ["Payroll"],
        "summary": "Get payroll state",
        "operationId": "getPayroll",
        "description": "The company's managed payroll state: the pay schedule, the current run, upcoming pay dates and recent paid runs. The client sets their own cycle (POST /payroll/schedule); processing runs - figures, status, payslips - is the Emplorea team's job and stays web-only. Available on the Essentials plan and above. Read scope.",
        "x-agent-hints": "Read the company's payroll at a glance: schedule, current run, the next pay dates and recent paid runs. For the full run list use GET /payroll/runs; for one run's per-employee payslip rows use GET /payroll/runs/{id}.",
        "responses": {
          "200": {
            "description": "Payroll schedule, current run, upcoming pay dates and recent paid runs",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "schedule": {
                          "type": "object",
                          "nullable": true,
                          "properties": {
                            "frequency": { "type": "string", "enum": ["weekly", "fortnightly", "monthly"] },
                            "first_pay_date": { "type": "string", "format": "date" }
                          }
                        },
                        "next_pay_date": { "type": "string", "format": "date", "nullable": true },
                        "current_run": {
                          "type": "object",
                          "nullable": true,
                          "properties": {
                            "status": { "type": "string", "enum": ["upcoming", "in_progress", "ready", "paid", "cancelled"] },
                            "pay_date": { "type": "string", "format": "date" },
                            "gross_cents": { "type": "integer" },
                            "net_cents": { "type": "integer" },
                            "employee_count": { "type": "integer" }
                          }
                        },
                        "upcoming": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "pay_date": { "type": "string", "format": "date" },
                              "period_start": { "type": "string", "format": "date" },
                              "period_end": { "type": "string", "format": "date" },
                              "status": { "type": "string" }
                            }
                          }
                        },
                        "recent_paid": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "pay_date": { "type": "string", "format": "date" },
                              "gross_cents": { "type": "integer" },
                              "net_cents": { "type": "integer" }
                            }
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/payroll/schedule": {
      "get": {
        "tags": ["Payroll"],
        "summary": "Get the pay schedule",
        "operationId": "getPaySchedule",
        "description": "The company's pay cycle: frequency, first pay date, pay-day rule and timezone. Null when the client hasn't set their cycle yet. Available on the Essentials plan and above. Read scope.",
        "x-agent-hints": "The client's own pay-cycle setting. Use POST /payroll/schedule to set or reset it; processing runs (figures, status, payslips) is the Emplorea team's job and is web-only.",
        "responses": {
          "200": {
            "description": "The active pay schedule, or null",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "schedule": {
                          "type": "object",
                          "nullable": true,
                          "properties": {
                            "frequency": { "type": "string", "enum": ["weekly", "fortnightly", "monthly"] },
                            "first_pay_date": { "type": "string", "format": "date" },
                            "pay_day_rule": { "type": "string" },
                            "timezone": { "type": "string" }
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": ["Payroll"],
        "summary": "Set the pay schedule",
        "operationId": "setPaySchedule",
        "description": "Sets (or resets) the company's pay cycle and generates the upcoming pay calendar. The one client-writable payroll op - the schedule is the client's own setting. Available on the Essentials plan and above. Write scope.",
        "x-agent-hints": "The only payroll write on the API. Provide frequency and first_pay_date (YYYY-MM-DD); optional pay_day_rule. Resetting rebuilds the upcoming calendar. Entering figures, advancing a run and uploading payslips are the Emplorea team's job and stay web-only.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["frequency", "first_pay_date"],
                "properties": {
                  "frequency": { "type": "string", "enum": ["weekly", "fortnightly", "monthly"] },
                  "first_pay_date": { "type": "string", "format": "date" },
                  "pay_day_rule": { "type": "string", "enum": ["on_period_end", "fixed_weekday", "last_business_day"] }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Schedule created; the calendar is generated",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "schedule_id": { "type": "string" },
                        "periods": { "type": "integer" }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Validation error",
            "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } }
          },
          "403": {
            "description": "Payroll requires the Essentials plan or above",
            "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } }
          }
        }
      }
    },
    "/payroll/runs": {
      "get": {
        "tags": ["Payroll"],
        "summary": "List pay runs",
        "operationId": "listPayRuns",
        "description": "Every pay run in the calendar (earliest first) with status and figures in integer cents. Read only - the Emplorea team processes runs in the web app. Available on the Essentials plan and above. Read scope.",
        "x-agent-hints": "The full calendar of runs, not the capped slices on GET /payroll. Each run carries gross/tax/super/deductions/net in integer cents plus status and employee_count.",
        "responses": {
          "200": {
            "description": "All pay runs with figures",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "runs": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "run_id": { "type": "string" },
                              "pay_date": { "type": "string", "format": "date" },
                              "period_start": { "type": "string", "format": "date" },
                              "period_end": { "type": "string", "format": "date" },
                              "status": { "type": "string", "enum": ["upcoming", "in_progress", "ready", "paid", "cancelled"] },
                              "gross_cents": { "type": "integer" },
                              "tax_cents": { "type": "integer" },
                              "super_cents": { "type": "integer" },
                              "deductions_cents": { "type": "integer" },
                              "net_cents": { "type": "integer" },
                              "employee_count": { "type": "integer" },
                              "prepared_at": { "type": "string", "format": "date-time", "nullable": true },
                              "paid_at": { "type": "string", "format": "date-time", "nullable": true }
                            }
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/payroll/runs/{id}": {
      "get": {
        "tags": ["Payroll"],
        "summary": "Get a pay run",
        "operationId": "getPayRun",
        "description": "One pay run with its per-employee payslip rows (name, status, net in cents). Payslip files are never returned here - the employee downloads them from their portal. Read only. Available on the Essentials plan and above. Read scope.",
        "x-agent-hints": "Per-employee payslip status and net pay for one run. To get the file, the employee uses their portal - the API never returns payslip bytes.",
        "parameters": [
          { "name": "id", "in": "path", "required": true, "schema": { "type": "string" } }
        ],
        "responses": {
          "200": {
            "description": "The run and its payslip rows",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "run": {
                          "type": "object",
                          "properties": {
                            "run_id": { "type": "string" },
                            "pay_date": { "type": "string", "format": "date" },
                            "period_start": { "type": "string", "format": "date" },
                            "period_end": { "type": "string", "format": "date" },
                            "status": { "type": "string", "enum": ["upcoming", "in_progress", "ready", "paid", "cancelled"] },
                            "gross_cents": { "type": "integer" },
                            "tax_cents": { "type": "integer" },
                            "super_cents": { "type": "integer" },
                            "deductions_cents": { "type": "integer" },
                            "net_cents": { "type": "integer" },
                            "employee_count": { "type": "integer" },
                            "prepared_at": { "type": "string", "format": "date-time", "nullable": true },
                            "paid_at": { "type": "string", "format": "date-time", "nullable": true }
                          }
                        },
                        "payslips": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "employee_id": { "type": "string" },
                              "employee_name": { "type": "string" },
                              "status": { "type": "string", "enum": ["pending", "issued", "none"] },
                              "net_cents": { "type": "integer" }
                            }
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Pay run not found",
            "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } }
          }
        }
      }
    },
    "/performance/probation": {
      "get": {
        "tags": ["Performance"],
        "summary": "List probation reviews",
        "operationId": "listProbationReviews",
        "description": "The company's probation picture: open_cases (employees currently on probation, with probation_end_date and whether a review has been recorded) and reviews (recorded decisions confirmed/extended/not_confirmed). READ ONLY: completing a probation review changes employment status and resolves a compliance item, so it is web-only. Review notes are never returned. Growth plan and above. Read scope.",
        "responses": {
          "200": {
            "description": "Open probation cases and recorded decisions",
            "content": { "application/json": { "schema": { "type": "object", "properties": { "data": { "type": "object", "properties": {
              "open_cases": { "type": "array", "items": { "type": "object", "properties": {
                "employee_id": { "type": "string", "format": "uuid" },
                "employee_name": { "type": "string", "nullable": true },
                "probation_end_date": { "type": "string", "format": "date", "nullable": true },
                "reviewed": { "type": "boolean" }
              } } },
              "reviews": { "type": "array", "items": { "type": "object", "properties": {
                "id": { "type": "string", "format": "uuid" },
                "employee_id": { "type": "string", "format": "uuid" },
                "employee_name": { "type": "string", "nullable": true },
                "status": { "type": "string", "enum": ["pending", "completed"] },
                "outcome": { "type": "string", "enum": ["confirmed", "extended", "not_confirmed"], "nullable": true },
                "extended_to_date": { "type": "string", "format": "date", "nullable": true },
                "decided_at": { "type": "string", "format": "date-time", "nullable": true },
                "created_at": { "type": "string", "format": "date-time" }
              } } }
            } } } } } }
          }
        }
      }
    },
    "/performance/reviews": {
      "get": {
        "tags": ["Performance"],
        "summary": "List performance reviews",
        "operationId": "listPerformanceReviews",
        "description": "Shared performance reviews (metadata: employee, review_type, rating 1-5, status shared/acknowledged, dates), newest first. DRAFT reviews are NEVER returned. Creating, sharing and acknowledging are web actions. Growth plan and above. Read scope.",
        "responses": { "200": {
          "description": "Shared review metadata",
          "content": { "application/json": { "schema": { "type": "object", "properties": { "data": { "type": "object", "properties": {
            "reviews": { "type": "array", "items": { "type": "object", "properties": {
              "id": { "type": "string", "format": "uuid" },
              "employee_id": { "type": "string", "format": "uuid" },
              "employee_name": { "type": "string", "nullable": true },
              "review_type": { "type": "string", "enum": ["probation", "quarterly", "annual", "ad_hoc"] },
              "status": { "type": "string", "enum": ["shared", "acknowledged"] },
              "rating": { "type": "integer", "nullable": true },
              "period_label": { "type": "string", "nullable": true },
              "shared_at": { "type": "string", "format": "date-time", "nullable": true },
              "acknowledged_at": { "type": "string", "format": "date-time", "nullable": true },
              "created_at": { "type": "string", "format": "date-time" }
            } } }
          } } } } } }
        } }
      }
    },
    "/performance/reviews/{id}": {
      "get": {
        "tags": ["Performance"],
        "summary": "Get a performance review",
        "operationId": "getPerformanceReview",
        "description": "One shared review with its body (strengths, development, summary). Only shared/acknowledged reviews resolve; a draft returns 404 and is never exposed. Growth plan and above. Read scope.",
        "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "string", "format": "uuid" } } ],
        "responses": { "200": { "description": "One shared review with its body" }, "404": { "description": "Not found, or the review is still a draft" } }
      }
    },
    "/performance/goals": {
      "get": {
        "tags": ["Performance"],
        "summary": "List goals",
        "operationId": "listGoals",
        "description": "The company's goals (employee, title, status, progress 0-100, dates), newest first. Growth plan and above. Read scope.",
        "responses": { "200": { "description": "Goals" } }
      },
      "post": {
        "tags": ["Performance"],
        "summary": "Create a goal",
        "operationId": "createGoal",
        "description": "Creates a goal for an employee. One of the two SAFE, low-stakes performance writes exposed to agents (the career-affecting writes stay web-only). Growth plan and above. Write scope.",
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": ["employee_id", "title"], "properties": {
          "employee_id": { "type": "string", "format": "uuid" },
          "title": { "type": "string" },
          "description": { "type": "string" },
          "status": { "type": "string", "enum": ["draft", "active", "achieved", "missed", "cancelled"] },
          "progress": { "type": "integer", "minimum": 0, "maximum": 100 },
          "start_date": { "type": "string", "format": "date" },
          "target_date": { "type": "string", "format": "date" }
        } } } } },
        "responses": { "201": { "description": "Goal created" }, "400": { "description": "Validation error" } }
      }
    },
    "/performance/goals/{id}": {
      "get": {
        "tags": ["Performance"],
        "summary": "Get a goal",
        "operationId": "getGoal",
        "description": "One goal by id. Growth plan and above. Read scope.",
        "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "string", "format": "uuid" } } ],
        "responses": { "200": { "description": "One goal" }, "404": { "description": "Not found" } }
      },
      "patch": {
        "tags": ["Performance"],
        "summary": "Update goal progress",
        "operationId": "setGoalProgress",
        "description": "Updates a goal's progress (0-100) and/or status. The other SAFE agent write. Growth plan and above. Write scope.",
        "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "string", "format": "uuid" } } ],
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "properties": {
          "progress": { "type": "integer", "minimum": 0, "maximum": 100 },
          "status": { "type": "string", "enum": ["draft", "active", "achieved", "missed", "cancelled"] }
        } } } } },
        "responses": { "200": { "description": "Goal updated" }, "404": { "description": "Not found" } }
      }
    },
    "/performance/one-on-ones": {
      "get": {
        "tags": ["Performance"],
        "summary": "List 1:1s",
        "operationId": "listOneOnOnes",
        "description": "The company's 1:1s, SHARED fields only (employee, scheduled date, status, shared notes, action items, next date). PRIVATE manager notes are NEVER exposed over the API (no employee RLS policy, no API path). Logging a 1:1 is a web action. Growth plan and above. Read scope.",
        "responses": { "200": { "description": "1:1s, shared fields only" } }
      }
    },
    "/compliance": {
      "get": {
        "tags": ["Compliance"],
        "summary": "List compliance items",
        "operationId": "listCompliance",
        "description": "The company's open compliance items, the current compliance score, and items resolved in the last 30 days. Severity is critical/warning/info; the score is 100 minus weighted open items (critical -20, warning -5, info -1). Available on the Essentials plan and above. Read scope.",
        "responses": {
          "200": {
            "description": "Compliance items and score",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "score": {
                          "type": "object",
                          "properties": {
                            "score": { "type": "integer" },
                            "critical": { "type": "integer" },
                            "warning": { "type": "integer" },
                            "info": { "type": "integer" },
                            "total": { "type": "integer" },
                            "categories": {
                              "type": "object",
                              "description": "Per-category breakdown keyed by pay/records/safety/leave; each has score, critical, warning, info, total."
                            }
                          }
                        },
                        "items": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "id": { "type": "string", "format": "uuid" },
                              "type": { "type": "string" },
                              "severity": { "type": "string", "enum": ["critical", "warning", "info"] },
                              "title": { "type": "string" },
                              "description": { "type": "string", "nullable": true },
                              "due_date": { "type": "string", "format": "date", "nullable": true },
                              "employee_id": { "type": "string", "format": "uuid", "nullable": true },
                              "employee_name": { "type": "string", "nullable": true },
                              "auto_generated": { "type": "boolean" },
                              "category": { "type": "string", "enum": ["pay", "records", "safety", "leave"], "nullable": true },
                              "detail": { "type": "object", "description": "Finding-specific data, e.g. the pay gap (actual/minimum/gap cents) or a cannot-verify reason." },
                              "created_at": { "type": "string", "format": "date-time" },
                              "resolved_at": { "type": "string", "format": "date-time", "nullable": true }
                            }
                          }
                        },
                        "resolved": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "id": { "type": "string", "format": "uuid" },
                              "type": { "type": "string" },
                              "severity": { "type": "string", "enum": ["critical", "warning", "info"] },
                              "title": { "type": "string" },
                              "resolved_at": { "type": "string", "format": "date-time", "nullable": true }
                            }
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/compliance/{id}/resolve": {
      "post": {
        "tags": ["Compliance"],
        "summary": "Resolve a compliance item",
        "operationId": "resolveComplianceItem",
        "description": "Marks one compliance item resolved. Auto-generated items reappear on the next check if the underlying condition still holds. Write scope.",
        "parameters": [
          { "name": "id", "in": "path", "required": true, "schema": { "type": "string", "format": "uuid" } }
        ],
        "responses": {
          "200": {
            "description": "Resolved",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "id": { "type": "string", "format": "uuid" },
                        "status": { "type": "string" }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/compliance/refresh": {
      "post": {
        "tags": ["Compliance"],
        "summary": "Re-run compliance checks",
        "operationId": "refreshCompliance",
        "description": "Re-runs the compliance rules (probation reviews, contract expiry, missing emergency contacts) for the company and returns the fresh score. Idempotent. Write scope.",
        "responses": {
          "200": {
            "description": "Fresh score",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "score": {
                          "type": "object",
                          "properties": {
                            "score": { "type": "integer" },
                            "critical": { "type": "integer" },
                            "warning": { "type": "integer" },
                            "info": { "type": "integer" },
                            "total": { "type": "integer" }
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/compliance/policies": {
      "get": {
        "tags": ["Compliance"],
        "summary": "List policies",
        "operationId": "listPolicies",
        "description": "The company's HR policies and acknowledgement coverage. Available on the Essentials plan and above. Read scope.",
        "x-agent-hints": ["A required policy the business has not activated is flagged by the compliance engine."],
        "responses": {
          "200": {
            "description": "Policies and acknowledgement coverage",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "policies": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "id": { "type": "string", "format": "uuid" },
                              "policyKey": { "type": "string" },
                              "title": { "type": "string" },
                              "status": { "type": "string", "enum": ["draft", "active", "archived"] },
                              "ackDone": { "type": "integer" },
                              "ackTotal": { "type": "integer" }
                            }
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/compliance/training": {
      "get": {
        "tags": ["Compliance"],
        "summary": "List training",
        "operationId": "listTraining",
        "description": "The company's required training and completion coverage, with renewals flagged before they lapse. Essentials plan and above. Read scope.",
        "x-agent-hints": ["Coverage is per in-scope employee; expiries are flagged before they lapse."],
        "responses": {
          "200": {
            "description": "Training requirements and coverage",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "training": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "id": { "type": "string", "format": "uuid" },
                              "title": { "type": "string" },
                              "completed": { "type": "integer" },
                              "total": { "type": "integer" },
                              "expiryMonths": { "type": "integer", "nullable": true }
                            }
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/compliance/incidents": {
      "get": {
        "tags": ["Compliance"],
        "summary": "List incidents",
        "operationId": "listIncidents",
        "description": "The company's WHS/HR incident register. Sensitive - a company-scoped key reads only its own register. Essentials plan and above. Read scope.",
        "responses": {
          "200": {
            "description": "Incident register",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "incidents": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "id": { "type": "string", "format": "uuid" },
                              "reference": { "type": "string" },
                              "type": { "type": "string" },
                              "severity": { "type": "string", "enum": ["critical", "warning", "info"] },
                              "status": { "type": "string", "enum": ["open", "investigating", "resolved", "closed"] },
                              "title": { "type": "string" }
                            }
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": ["Compliance"],
        "summary": "Log an incident",
        "operationId": "logIncident",
        "description": "Logs a workplace incident and returns its server-generated reference. severity critical is treated as notifiable. The one compliance write an agent performs - award and rule data is Emplorea-managed and never writable here. Write scope.",
        "x-agent-hints": ["Provide type, severity and title; the reference is generated server-side."],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["type", "severity", "title"],
                "properties": {
                  "type": { "type": "string" },
                  "severity": { "type": "string", "enum": ["critical", "warning", "info"] },
                  "title": { "type": "string" },
                  "description": { "type": "string" },
                  "occurred_on": { "type": "string", "format": "date" },
                  "location": { "type": "string" },
                  "affected_employee_id": { "type": "string", "format": "uuid" }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Logged incident",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "id": { "type": "string", "format": "uuid" },
                        "reference": { "type": "string" }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/compliance/incidents/{id}": {
      "post": {
        "tags": ["Compliance"],
        "summary": "Update an incident",
        "operationId": "updateIncident",
        "description": "Update an incident's status (and resolution). Closing it records the resolution. Write scope.",
        "parameters": [
          { "name": "id", "in": "path", "required": true, "schema": { "type": "string", "format": "uuid" } }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["status"],
                "properties": {
                  "status": { "type": "string", "enum": ["open", "investigating", "resolved", "closed"] },
                  "resolution": { "type": "string" }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated incident",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "id": { "type": "string", "format": "uuid" },
                        "status": { "type": "string" }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/compliance/results": {
      "get": {
        "tags": ["Compliance"],
        "summary": "List compliance run snapshots",
        "operationId": "listComplianceResults",
        "description": "Recent compliance run snapshots (the score trend, newest first) so a result can be traced over time. Defaults to the blended company-wide series (jurisdiction null, one point per run-day); pass ?jurisdiction=AU|NZ|UK to read that jurisdiction's attributed series instead (only multi-jurisdiction companies have those rows). Essentials plan and above. Read scope.",
        "parameters": [
          {
            "name": "jurisdiction",
            "in": "query",
            "required": false,
            "description": "Read a single jurisdiction's attributed trend instead of the blended company-wide series. Only multi-jurisdiction companies have per-jurisdiction rows.",
            "schema": { "type": "string", "enum": ["AU", "NZ", "UK"] }
          }
        ],
        "responses": {
          "200": {
            "description": "Run snapshots",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "results": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "score": { "type": "integer" },
                              "as_of": { "type": "string", "format": "date" },
                              "created_at": { "type": "string", "format": "date-time" },
                              "jurisdiction": {
                                "type": "string",
                                "nullable": true,
                                "enum": ["AU", "NZ", "UK", null],
                                "description": "null for the blended company-wide snapshot; a value for a per-jurisdiction snapshot."
                              }
                            }
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/ask-hr": {
      "post": {
        "tags": ["Ask HR"],
        "summary": "Ask an HR question",
        "operationId": "askHr",
        "description": "Submit a question to Vera. Requires the Essentials plan or above. Do not include real names, salaries or tax file numbers - company data is tokenised server-side. Write scope.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["question"],
                "properties": {
                  "question": { "type": "string", "maxLength": 2000 },
                  "conversation_id": { "type": "string", "format": "uuid" }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Vera's answer",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "answer": { "type": "string" },
                        "conversationId": { "type": "string", "format": "uuid" },
                        "cached": { "type": "boolean" }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      },
      "get": {
        "tags": ["Ask HR"],
        "summary": "List HR Q&A conversations",
        "operationId": "listHrConversations",
        "description": "Lists the company's Vera conversations, newest first. Read scope.",
        "responses": {
          "200": {
            "description": "Conversations",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": { "type": "string", "format": "uuid" },
                          "title": { "type": "string", "nullable": true },
                          "message_count": { "type": "integer" },
                          "created_at": { "type": "string", "format": "date-time" }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/ask-hr/{id}": {
      "get": {
        "tags": ["Ask HR"],
        "summary": "Get an HR Q&A conversation",
        "operationId": "getHrConversation",
        "description": "Returns one Vera conversation with all its messages. Message content is tokenised. Read scope.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": { "type": "string", "format": "uuid" }
          }
        ],
        "responses": {
          "200": {
            "description": "Conversation with messages",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "conversation": {
                          "type": "object",
                          "properties": {
                            "id": { "type": "string", "format": "uuid" },
                            "title": { "type": "string", "nullable": true },
                            "created_at": { "type": "string", "format": "date-time" }
                          }
                        },
                        "messages": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "role": { "type": "string", "enum": ["user", "assistant"] },
                              "content": { "type": "string" },
                              "created_at": { "type": "string", "format": "date-time" }
                            }
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/jobs": {
      "get": {
        "tags": ["Recruitment"],
        "summary": "Public job listings",
        "operationId": "listJobs",
        "x-status": "coming-soon",
        "x-agent-hints": "The job board API arrives in Phase 3.",
        "responses": {
          "501": {
            "description": "Coming soon",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "UNAUTHORISED",
                            "FORBIDDEN",
                            "NOT_FOUND",
                            "VALIDATION_ERROR",
                            "CONFLICT",
                            "RATE_LIMITED",
                            "NOT_IMPLEMENTED",
                            "INTERNAL_ERROR"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  },
                  "required": [
                    "error"
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/documents/{id}": {
      "parameters": [
        {
          "name": "id",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string",
            "format": "uuid"
          }
        }
      ],
      "get": {
        "tags": ["Documents"],
        "summary": "Get a document",
        "operationId": "getDocument",
        "x-agent-hints": "Metadata only - call /documents/{id}/download for the file itself.",
        "responses": {
          "200": {
            "description": "Document",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Document"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": ["Documents"],
        "summary": "Remove a document",
        "operationId": "deleteDocument",
        "x-agent-hints": "Soft delete - the record is kept and the file stays in storage for legal retention. Requires the write scope.",
        "responses": {
          "200": {
            "description": "Removed",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Document"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/documents/{id}/download": {
      "parameters": [
        {
          "name": "id",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string",
            "format": "uuid"
          }
        }
      ],
      "get": {
        "tags": ["Documents"],
        "summary": "Get a download URL",
        "operationId": "getDocumentDownloadUrl",
        "x-agent-hints": "Returns a signed URL that expires after 15 minutes (expires_in_seconds). Fetch it right before downloading - never store it.",
        "responses": {
          "200": {
            "description": "Signed URL",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "url": {
                          "type": "string"
                        },
                        "expires_in_seconds": {
                          "type": "integer"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/documents/{id}/send-for-signature": {
      "parameters": [
        {
          "name": "id",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string",
            "format": "uuid"
          }
        }
      ],
      "post": {
        "tags": ["Documents"],
        "summary": "Send a document for signature",
        "operationId": "sendDocumentForSignature",
        "x-agent-hints": "Creates a one-time signing link valid for 7 days (in-house e-sign - signing captures timestamp, IP and user agent). Returns sign_path - prefix with the app origin and share it with the signer. The document must be linked to an employee. Requires the write scope.",
        "responses": {
          "200": {
            "description": "Signing link created",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "sign_path": {
                          "type": "string",
                          "example": "/sign/abc123"
                        },
                        "expires_at": {
                          "type": "string",
                          "format": "date-time"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Already signed or no employee linked",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/wellbeing/score": {
      "get": {
        "tags": ["Wellbeing"],
        "summary": "Get aggregate wellbeing score",
        "operationId": "getTeamWellbeingScore",
        "parameters": [ { "name": "team_key", "in": "query", "required": false, "schema": { "type": "string" }, "description": "A team key (manager id). Omit for the company score." } ],
        "x-agent-hints": "AGGREGATES ONLY: a team or company wellbeing score (0-100, band, contributor count). NEVER returns an individual - an employee_id query param is refused with 403 by construction. A team below the anonymity floor returns { insufficient: true }. Growth plan and above. Read scope.",
        "responses": {
          "200": { "description": "Success", "content": { "application/json": { "schema": { "type": "object", "properties": { "data": { "type": "object" } } } } } },
          "401": { "description": "Missing or invalid API key" },
          "403": { "description": "Plan does not include Wellbeing, or an individual score was requested", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }
        }
      }
    },
    "/wellbeing/incidents": {
      "post": {
        "tags": ["Wellbeing"],
        "summary": "Log a WHS incident",
        "operationId": "logWhsIncident",
        "x-agent-hints": "Logs a workplace health and safety incident and returns its server-generated reference (INC-YYYY-NNNN). Required: type, severity (critical/warning/info), title. Optional WHS detail: injury_type, body_part, treatment_required, witness_details, notifiable. The compliance engine reconciles it on its next run. Growth plan and above. Write scope.",
        "responses": {
          "201": { "description": "Created", "content": { "application/json": { "schema": { "type": "object", "properties": { "data": { "type": "object", "properties": { "id": { "type": "string" }, "reference": { "type": "string" } } } } } } } },
          "401": { "description": "Missing or invalid API key" }
        }
      }
    },
    "/wellbeing/resources": {
      "get": {
        "tags": ["Wellbeing"],
        "summary": "Get the EAP directory",
        "operationId": "getWellbeingResources",
        "x-agent-hints": "The company's EAP directory - published support providers, categories and resources (Emplorea-curated plus the company's own). Help, not personal data: no per-employee EAP access is ever recorded or returned. Growth plan and above. Read scope.",
        "responses": {
          "200": { "description": "Success", "content": { "application/json": { "schema": { "type": "object", "properties": { "data": { "type": "object" } } } } } },
          "401": { "description": "Missing or invalid API key" }
        }
      }
    },
    "/wellbeing/absence-patterns": {
      "get": {
        "tags": ["Wellbeing"],
        "summary": "Get aggregate absence patterns",
        "operationId": "getAbsencePatterns",
        "x-agent-hints": "AGGREGATES ONLY: the latest run's TEAM absence-pattern flags. NEVER returns an individual - the core reads team-scoped flags exclusively. Growth plan and above. Read scope.",
        "responses": {
          "200": { "description": "Success", "content": { "application/json": { "schema": { "type": "object", "properties": { "data": { "type": "object" } } } } } },
          "401": { "description": "Missing or invalid API key" }
        }
      }
    },
    "/learn/courses": {
      "get": {
        "tags": ["Learn"],
        "summary": "List courses",
        "operationId": "listCourses",
        "x-agent-hints": "The training library the company can see - its own courses (any status) plus the global Emplorea-published library, each with a lesson count, jurisdiction and category. Quiz answer keys are never included. Growth plan with the Learn add-on. Read scope.",
        "responses": {
          "200": { "description": "Success", "content": { "application/json": { "schema": { "type": "object", "properties": { "data": { "type": "object" } } } } } },
          "401": { "description": "Missing or invalid API key" }
        }
      },
      "post": {
        "tags": ["Learn"],
        "summary": "Create a course",
        "operationId": "createCourse",
        "x-agent-hints": "Creates a DRAFT company course. Required: title. Optional: description, summary, category_id, estimated_minutes, jurisdiction, pass_score. Adding lessons and publishing are separate steps. Growth plan with the Learn add-on. Write scope.",
        "responses": {
          "201": { "description": "Created", "content": { "application/json": { "schema": { "type": "object", "properties": { "data": { "type": "object", "properties": { "id": { "type": "string" } } } } } } } },
          "401": { "description": "Missing or invalid API key" }
        }
      }
    },
    "/learn/courses/{id}": {
      "get": {
        "tags": ["Learn"],
        "summary": "Get a course",
        "operationId": "getCourse",
        "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "string", "format": "uuid" } } ],
        "x-agent-hints": "One course with its ordered lessons, returned as a LEARNER: every quiz lesson's answer key (correct_index and explanation) is stripped server-side, so the API never exposes quiz answers. Growth plan with the Learn add-on. Read scope.",
        "responses": {
          "200": { "description": "Success", "content": { "application/json": { "schema": { "type": "object", "properties": { "data": { "type": "object" } } } } } },
          "401": { "description": "Missing or invalid API key" },
          "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }
        }
      }
    },
    "/learn/assignments": {
      "post": {
        "tags": ["Learn"],
        "summary": "Assign a course",
        "operationId": "assignCourse",
        "x-agent-hints": "Assigns a course to one or more employees with an optional deadline. Idempotent per course + employee. Required: course_id, employee_ids[]. Optional: is_mandatory, due_date. Only this company's own employees are assigned. Growth plan with the Learn add-on. Write scope.",
        "responses": {
          "201": { "description": "Created", "content": { "application/json": { "schema": { "type": "object", "properties": { "data": { "type": "object", "properties": { "assigned": { "type": "integer" }, "assignment_ids": { "type": "array", "items": { "type": "string" } } } } } } } } },
          "401": { "description": "Missing or invalid API key" }
        }
      }
    },
    "/learn/completions": {
      "post": {
        "tags": ["Learn"],
        "summary": "Mark a lesson complete",
        "operationId": "markLessonComplete",
        "x-agent-hints": "Marks a single lesson complete for an employee's own assignment. Required: assignment_id, lesson_id, employee_id. When every lesson of the course is then complete the course completes and a certificate is issued. Growth plan with the Learn add-on. Write scope.",
        "responses": {
          "201": { "description": "Created", "content": { "application/json": { "schema": { "type": "object", "properties": { "data": { "type": "object", "properties": { "lesson_id": { "type": "string" }, "course_completed": { "type": "boolean" }, "certificate_id": { "type": "string", "nullable": true } } } } } } } },
          "401": { "description": "Missing or invalid API key" }
        }
      }
    },
    "/learn/certificates/{id}": {
      "get": {
        "tags": ["Learn"],
        "summary": "Get a certificate",
        "operationId": "getCertificate",
        "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "string", "format": "uuid" } } ],
        "x-agent-hints": "One certificate's metadata (holder name, course title, issue date, revoked flag) plus its public verify_url (https://app.emplorea.com/verify/cert/{token}). Scoped to the caller's company. The token in verify_url is the verification capability. Growth plan with the Learn add-on. Read scope.",
        "responses": {
          "200": { "description": "Success", "content": { "application/json": { "schema": { "type": "object", "properties": { "data": { "type": "object", "properties": { "id": { "type": "string" }, "course_title": { "type": "string" }, "holder_name": { "type": "string" }, "issued_on": { "type": "string" }, "revoked": { "type": "boolean" }, "verify_url": { "type": "string" } } } } } } } },
          "401": { "description": "Missing or invalid API key" },
          "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }
        }
      }
    }
  }
}
